Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0e08529da0 | ||
|
|
95d927c941 | ||
|
|
9dfb855090 | ||
|
|
775d9e5457 | ||
|
|
294eb34418 |
@@ -319,7 +319,7 @@ run-visual-test-ios: XCODE_DERIVED_DATA := $(HOME)/Library/Developer/Xcode/Deriv
|
||||
run-visual-test-ios: APPLICATION_NAME := StatusIm-brfnruzfrkkycpbndmdoeyrigthc
|
||||
run-visual-test-ios: export TEST_BINARY_PATH := $(XCODE_DERIVED_DATA)/$(APPLICATION_NAME)/Build/Products/Debug-iphonesimulator/StatusIm.app
|
||||
run-visual-test-ios: ##@test Run tests once in NodeJS
|
||||
detox test --configuration ios.sim.debug
|
||||
detox test --configuration ios.sim.debug
|
||||
|
||||
component-test-watch: export TARGET := clojure
|
||||
component-test-watch: export COMPONENT_TEST := true
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
:ns-regexp "status-im.chat.models-test$"
|
||||
:main status-im.test-runner/main
|
||||
;; set :ui-driven to true to let shadow-cljs inject node-repl
|
||||
:ui-driven true
|
||||
|
||||
@@ -20,19 +20,19 @@
|
||||
|
||||
(defn- resize-and-call [uri cb]
|
||||
(react/image-get-size
|
||||
uri
|
||||
(fn [width height]
|
||||
(let [resize? (> (max width height) maximum-image-size-px)]
|
||||
(image-processing/resize
|
||||
uri
|
||||
(if resize? maximum-image-size-px width)
|
||||
(if resize? maximum-image-size-px height)
|
||||
60
|
||||
(fn [^js resized-image]
|
||||
(let [path (.-path resized-image)
|
||||
path (if (string/starts-with? path "file") path (str "file://" path))]
|
||||
(cb path)))
|
||||
#(log/error "could not resize image" %))))))
|
||||
uri
|
||||
(fn [width height]
|
||||
(let [resize? (> (max width height) maximum-image-size-px)]
|
||||
(image-processing/resize
|
||||
uri
|
||||
(if resize? maximum-image-size-px width)
|
||||
(if resize? maximum-image-size-px height)
|
||||
60
|
||||
(fn [^js resized-image]
|
||||
(let [path (.-path resized-image)
|
||||
path (if (string/starts-with? path "file") path (str "file://" path))]
|
||||
(cb path)))
|
||||
#(log/error "could not resize image" %))))))
|
||||
|
||||
(defn result->id [^js result]
|
||||
(if platform/ios?
|
||||
@@ -43,7 +43,7 @@
|
||||
|
||||
(defn download-image-http [base64-uri on-success]
|
||||
(-> (.config ReactNativeBlobUtil (clj->js {:trusty platform/ios?
|
||||
:path temp-image-url}))
|
||||
:path temp-image-url}))
|
||||
(.fetch "GET" base64-uri)
|
||||
(.then #(on-success (.path %)))
|
||||
(.catch #(log/error "could not save image"))))
|
||||
@@ -51,62 +51,64 @@
|
||||
(defn save-to-gallery [path] (.save CameraRoll path))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::save-image-to-gallery
|
||||
(fn [base64-uri]
|
||||
(if platform/ios?
|
||||
(-> (download-image-http base64-uri save-to-gallery)
|
||||
(.catch #(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied))))
|
||||
(permissions/request-permissions
|
||||
{:permissions [:write-external-storage]
|
||||
:on-allowed #(download-image-http base64-uri save-to-gallery)
|
||||
:on-denied (fn []
|
||||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied))
|
||||
50))}))))
|
||||
::save-image-to-gallery
|
||||
(fn [base64-uri]
|
||||
(if platform/ios?
|
||||
(-> (download-image-http base64-uri save-to-gallery)
|
||||
(.catch #(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied))))
|
||||
(permissions/request-permissions
|
||||
{:permissions [:write-external-storage]
|
||||
:on-allowed #(download-image-http base64-uri save-to-gallery)
|
||||
:on-denied (fn []
|
||||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied))
|
||||
50))}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::chat-open-image-picker-camera
|
||||
(fn [current-chat-id]
|
||||
(react/show-image-picker-camera
|
||||
#(re-frame/dispatch [:chat.ui/image-captured current-chat-id (.-path %)]) {})))
|
||||
::chat-open-image-picker-camera
|
||||
(fn [current-chat-id]
|
||||
(react/show-image-picker-camera
|
||||
#(re-frame/dispatch [:chat.ui/image-captured current-chat-id (.-path %)]) {})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::chat-open-image-picker
|
||||
(fn [chat-id]
|
||||
(react/show-image-picker
|
||||
(fn [^js images]
|
||||
;; NOTE(Ferossgp): Because we can't highlight the already selected images inside
|
||||
;; gallery, we just clean previous state and set all newly picked images
|
||||
(when (and platform/ios? (pos? (count images)))
|
||||
(re-frame/dispatch [:chat.ui/clear-sending-images chat-id]))
|
||||
(doseq [^js result (if platform/ios?
|
||||
(take config/max-images-batch images)
|
||||
[images])]
|
||||
(resize-and-call (.-path result)
|
||||
#(re-frame/dispatch [:chat.ui/image-selected chat-id (result->id result) %]))))
|
||||
;; NOTE(Ferossgp): On android you cannot set max limit on images, when a user
|
||||
;; selects too many images the app crashes.
|
||||
{:media-type "photo"
|
||||
:multiple platform/ios?})))
|
||||
::chat-open-image-picker
|
||||
(fn [chat-id]
|
||||
(react/show-image-picker
|
||||
(fn [^js images]
|
||||
;; NOTE(Ferossgp): Because we can't highlight the already selected images inside
|
||||
;; gallery, we just clean previous state and set all newly picked images
|
||||
(when (and platform/ios? (pos? (count images)))
|
||||
(re-frame/dispatch [:chat.ui/clear-sending-images chat-id]))
|
||||
(doseq [^js result (if platform/ios?
|
||||
(take config/max-images-batch images)
|
||||
[images])]
|
||||
(resize-and-call (.-path result)
|
||||
#(re-frame/dispatch [:chat.ui/image-selected chat-id (result->id result) %]))))
|
||||
;; NOTE(Ferossgp): On android you cannot set max limit on images, when a user
|
||||
;; selects too many images the app crashes.
|
||||
{:media-type "photo"
|
||||
:multiple platform/ios?})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::image-selected
|
||||
(fn [[uri chat-id]]
|
||||
(resize-and-call
|
||||
uri
|
||||
#(re-frame/dispatch [:chat.ui/image-selected chat-id uri %]))))
|
||||
::image-selected
|
||||
(fn [[uri chat-id]]
|
||||
(resize-and-call
|
||||
uri
|
||||
#(re-frame/dispatch [:chat.ui/image-selected chat-id uri %]))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
::camera-roll-get-photos
|
||||
(fn [num]
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage]
|
||||
:on-allowed (fn []
|
||||
(-> (.getPhotos CameraRoll #js {:first num :assetType "Photos" :groupTypes "All"})
|
||||
(.then #(re-frame/dispatch [:on-camera-roll-get-photos (:edges (types/js->clj %))]))
|
||||
(.catch #(log/warn "could not get cameraroll photos"))))})))
|
||||
::camera-roll-get-photos
|
||||
(fn [[num end-cursor]]
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage]
|
||||
:on-allowed (fn []
|
||||
(-> (if end-cursor
|
||||
(.getPhotos CameraRoll #js {:first num :after end-cursor :assetType "Photos" :groupTypes "All"})
|
||||
(.getPhotos CameraRoll #js {:first num :assetType "Photos" :groupTypes "All"}))
|
||||
(.then #(re-frame/dispatch [:on-camera-roll-get-photos (:edges (types/js->clj %)) (:page_info (types/js->clj %)) end-cursor]))
|
||||
(.catch #(log/warn "could not get camera roll photos"))))})))
|
||||
|
||||
(fx/defn image-captured
|
||||
{:events [:chat.ui/image-captured]}
|
||||
@@ -119,13 +121,23 @@
|
||||
|
||||
(fx/defn camera-roll-get-photos
|
||||
{:events [:chat.ui/camera-roll-get-photos]}
|
||||
[_ num]
|
||||
{::camera-roll-get-photos num})
|
||||
[_ num end-cursor]
|
||||
{::camera-roll-get-photos [num end-cursor]})
|
||||
|
||||
(fx/defn camera-roll-loading-more
|
||||
{:events [:chat.ui/camera-roll-loading-more]}
|
||||
[{:keys [db]} is-loading]
|
||||
{:db (assoc db :camera-roll-loading-more is-loading)})
|
||||
|
||||
(fx/defn on-camera-roll-get-photos
|
||||
{:events [:on-camera-roll-get-photos]}
|
||||
[{db :db} photos]
|
||||
{:db (assoc db :camera-roll-photos (mapv #(get-in % [:node :image :uri]) photos))})
|
||||
[{:keys [db] :as cofx} photos page-info end-cursor]
|
||||
(let [photos_x (when end-cursor (:camera-roll-photos db))]
|
||||
{:db (-> db
|
||||
(assoc :camera-roll-photos (concat photos_x (map #(get-in % [:node :image :uri]) photos)))
|
||||
(assoc :camera-roll-end-cursor (:end_cursor page-info))
|
||||
(assoc :camera-roll-has-next-page (:has_next_page page-info))
|
||||
(assoc :camera-roll-loading-more false))}))
|
||||
|
||||
(fx/defn clear-sending-images
|
||||
{:events [:chat.ui/clear-sending-images]}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(ns status-im.chat.models-test
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.chat.models :as chat]))
|
||||
[status-im.chat.models :as chat]
|
||||
[status-im.chat.models.images :as images]))
|
||||
|
||||
(deftest clear-history-test
|
||||
(let [chat-id "1"
|
||||
@@ -91,3 +92,9 @@
|
||||
(testing "Pagination info should be reset on navigation"
|
||||
(let [res (chat/navigate-to-chat-nav2 {:db db} chat-id false)]
|
||||
(is (nil? (get-in res [:db :pagination-info chat-id :all-loaded?])))))))
|
||||
|
||||
|
||||
|
||||
(deftest camera-roll-loading-more
|
||||
(let [cofx {:db {:camera-roll-loading-more false}}]
|
||||
(is (= true (images/camera-roll-loading-more cofx true)))))
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
(ns status-im.ui2.screens.chat.composer.composer-images.composer-images
|
||||
(:require [react-native.core :as rn]
|
||||
[status-im.ui2.screens.chat.composer.style :as style]
|
||||
[quo2.core :as quo2]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[re-frame.core :as rf]))
|
||||
|
||||
|
||||
(defn image [item]
|
||||
[rn/view
|
||||
[rn/image {:source {:uri (first item)}
|
||||
:style style/small-image}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn [] (rf/dispatch [:chat.ui/image-unselected (first item)]))
|
||||
:style style/remove-photo-container}
|
||||
[quo2/icon :i/close {:color colors/white :size 12}]]])
|
||||
|
||||
(defn images-list [images]
|
||||
[rn/flat-list {:key-fn first
|
||||
:render-fn image
|
||||
:data images
|
||||
:horizontal true
|
||||
:style {:bottom 50 :position :absolute :z-index 5}
|
||||
:content-container-style {:padding-horizontal 20 :margin-top 12}
|
||||
:separator [rn/view {:style {:width 12}}]}])
|
||||
@@ -80,3 +80,20 @@
|
||||
(when-not pin? {:position :absolute
|
||||
:left 34
|
||||
:top 3})))
|
||||
|
||||
(def remove-photo-container
|
||||
{:width 14
|
||||
:height 14
|
||||
:border-radius 7
|
||||
:background-color colors/neutral-50
|
||||
:position :absolute
|
||||
:top -7
|
||||
:right -7
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(def small-image
|
||||
{:width 56
|
||||
:height 56
|
||||
:border-radius 8
|
||||
:margin-bottom 20})
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo.react-native :as rn :refer [navigation-const]]
|
||||
[status-im.ui2.screens.chat.composer.style :as styles]
|
||||
[status-im.ui2.screens.chat.composer.reply :as reply]
|
||||
[quo2.components.buttons.button :as quo2.button]
|
||||
[status-im.utils.handlers :refer [<sub]]
|
||||
@@ -17,7 +16,10 @@
|
||||
[status-im.ui2.screens.chat.photo-selector.view :as photo-selector]
|
||||
[status-im.utils.utils :as utils]
|
||||
[i18n.i18n :as i18n]
|
||||
[status-im.ui2.screens.chat.composer.edit.view :as edit]))
|
||||
[status-im.ui2.screens.chat.composer.edit.view :as edit]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.ui2.screens.chat.composer.composer-images.composer-images :as composer-images]
|
||||
[status-im.ui2.screens.chat.composer.style :as style]))
|
||||
|
||||
(defn calculate-y [context keyboard-shown min-y max-y added-value]
|
||||
(if keyboard-shown
|
||||
@@ -43,41 +45,42 @@
|
||||
mentions-translate-value (if should-translate (min min-value (- mentions-height (- max-height text-height))) mentions-height)]
|
||||
(when (or (< y max-y) should-translate) mentions-translate-value)))
|
||||
|
||||
(defn get-y-value [context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply]
|
||||
(let [y (calculate-y context keyboard-shown min-y max-y added-value)]
|
||||
(defn get-y-value [context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply images]
|
||||
(let [y (calculate-y context keyboard-shown min-y max-y added-value)
|
||||
y (+ y (when (seq images) 80))]
|
||||
y (+ y (when (seq suggestions) (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)))))
|
||||
|
||||
(defn get-bottom-sheet-gesture [context translate-y text-input-ref keyboard-shown min-y max-y shared-height max-height bg-opacity]
|
||||
(-> (gesture/gesture-pan)
|
||||
(gesture/on-start
|
||||
(fn [_]
|
||||
(if keyboard-shown
|
||||
(swap! context assoc :pan-y (reanimated/get-shared-value translate-y))
|
||||
(input/input-focus text-input-ref))))
|
||||
(fn [_]
|
||||
(if keyboard-shown
|
||||
(swap! context assoc :pan-y (reanimated/get-shared-value translate-y))
|
||||
(input/input-focus text-input-ref))))
|
||||
(gesture/on-update
|
||||
(fn [evt]
|
||||
(when keyboard-shown
|
||||
(swap! context assoc :dy (- (.-translationY evt) (:pdy @context)))
|
||||
(swap! context assoc :pdy (.-translationY evt))
|
||||
(reanimated/set-shared-value
|
||||
translate-y
|
||||
(max (min (+ (.-translationY evt) (:pan-y @context)) (- min-y)) (- max-y))))))
|
||||
(fn [evt]
|
||||
(when keyboard-shown
|
||||
(swap! context assoc :dy (- (.-translationY evt) (:pdy @context)))
|
||||
(swap! context assoc :pdy (.-translationY evt))
|
||||
(reanimated/set-shared-value
|
||||
translate-y
|
||||
(max (min (+ (.-translationY evt) (:pan-y @context)) (- min-y)) (- max-y))))))
|
||||
(gesture/on-end
|
||||
(fn [_]
|
||||
(when keyboard-shown
|
||||
(if (< (:dy @context) 0)
|
||||
(do
|
||||
(swap! context assoc :state :max)
|
||||
(input/input-focus text-input-ref)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- max-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing max-height))
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 1)))
|
||||
(do
|
||||
(swap! context assoc :state :min)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 0))
|
||||
(re-frame/dispatch [:dismiss-keyboard]))))))))
|
||||
(fn [_]
|
||||
(when keyboard-shown
|
||||
(if (< (:dy @context) 0)
|
||||
(do
|
||||
(swap! context assoc :state :max)
|
||||
(input/input-focus text-input-ref)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- max-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing max-height))
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 1)))
|
||||
(do
|
||||
(swap! context assoc :state :min)
|
||||
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
|
||||
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 0))
|
||||
(re-frame/dispatch [:dismiss-keyboard]))))))))
|
||||
|
||||
(defn get-input-content-change [context translate-y shared-height max-height bg-opacity keyboard-shown min-y max-y]
|
||||
(fn [evt]
|
||||
@@ -103,19 +106,19 @@
|
||||
(swap! context assoc :y new-y)
|
||||
(when keyboard-shown
|
||||
(reanimated/set-shared-value
|
||||
translate-y
|
||||
(reanimated/with-timing (- new-y)))
|
||||
translate-y
|
||||
(reanimated/with-timing (- new-y)))
|
||||
(reanimated/set-shared-value
|
||||
shared-height
|
||||
(reanimated/with-timing (min new-y max-height)))))
|
||||
shared-height
|
||||
(reanimated/with-timing (min new-y max-height)))))
|
||||
(do
|
||||
(swap! context assoc :state :max)
|
||||
(swap! context assoc :y max-y)
|
||||
(when keyboard-shown
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 1))
|
||||
(reanimated/set-shared-value
|
||||
translate-y
|
||||
(reanimated/with-timing (- max-y)))))))))))
|
||||
translate-y
|
||||
(reanimated/with-timing (- max-y)))))))))))
|
||||
|
||||
(defn composer [chat-id]
|
||||
[safe-area/consumer
|
||||
@@ -138,13 +141,14 @@
|
||||
(let [reply (<sub [:chats/reply-message])
|
||||
edit (<sub [:chats/edit-message])
|
||||
suggestions (<sub [:chat/mention-suggestions])
|
||||
images (get-in (rf/sub [:chat/inputs]) [chat-id :metadata :sending-image])
|
||||
{window-height :height} (rn/use-window-dimensions)
|
||||
{:keys [keyboard-shown keyboard-height]} (rn/use-keyboard)
|
||||
max-y (- window-height (if (> keyboard-height 0) keyboard-height 360) (:top insets) (:status-bar-height @navigation-const)) ; 360 - default height
|
||||
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56 - top-bar height
|
||||
added-value (if (and (not (seq suggestions)) (or edit reply)) 38 0) ; increased height of input box needed when reply
|
||||
min-y (+ min-y (when (or edit reply) 38))
|
||||
y (get-y-value context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply)
|
||||
y (get-y-value context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply images)
|
||||
translate-y (reanimated/use-shared-value 0)
|
||||
shared-height (reanimated/use-shared-value min-y)
|
||||
bg-opacity (reanimated/use-shared-value 0)
|
||||
@@ -169,15 +173,15 @@
|
||||
(reanimated/set-shared-value bg-opacity (reanimated/with-timing 0))
|
||||
(re-frame/dispatch [:dismiss-keyboard])) edit)
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:height shared-height}
|
||||
{:z-index 2})}
|
||||
{:height shared-height}
|
||||
{:z-index 2})}
|
||||
;;INPUT MESSAGE bottom sheet
|
||||
[gesture/gesture-detector {:gesture bottom-sheet-gesture}
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:transform [{:translateY translate-y}]}
|
||||
(styles/input-bottom-sheet window-height))}
|
||||
{:transform [{:translateY translate-y}]}
|
||||
(style/input-bottom-sheet window-height))}
|
||||
;handle
|
||||
[rn/view {:style (styles/bottom-sheet-handle)}]
|
||||
[rn/view {:style (style/bottom-sheet-handle)}]
|
||||
[edit/edit-message-auto-focus-wrapper (:text-input-ref refs) edit]
|
||||
[reply/reply-message-auto-focus-wrapper (:text-input-ref refs) reply]
|
||||
[rn/view {:style {:height (- max-y 80 added-value)}}
|
||||
@@ -188,16 +192,16 @@
|
||||
:set-active-panel #()}]]]]
|
||||
;CONTROLS
|
||||
(when-not (seq suggestions)
|
||||
[rn/view {:style (styles/bottom-sheet-controls insets)}
|
||||
[rn/view {:style (style/bottom-sheet-controls insets)}
|
||||
[quo2.button/button {:on-press (fn []
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage :write-external-storage]
|
||||
:on-allowed #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content [photo-selector/photo-selector]}])
|
||||
:on-denied (fn []
|
||||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied)) 50))}))
|
||||
{:permissions [:read-external-storage :write-external-storage]
|
||||
:on-allowed #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content [photo-selector/photo-selector]}])
|
||||
:on-denied (fn []
|
||||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
(i18n/label :t/external-storage-denied)) 50))}))
|
||||
:icon true :type :outline :size 32} :i/image]
|
||||
[rn/view {:width 12}]
|
||||
[quo2.button/button {:icon true :type :outline :size 32} :i/reaction]
|
||||
@@ -211,6 +215,7 @@
|
||||
:i/arrow-up]]])
|
||||
;black background
|
||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:opacity bg-opacity}
|
||||
(styles/bottom-sheet-background window-height))}]
|
||||
{:opacity bg-opacity}
|
||||
(style/bottom-sheet-background window-height))}]
|
||||
[composer-images/images-list images]
|
||||
[mentions/autocomplete-mentions suggestions]]))])))])
|
||||
|
||||
@@ -1,20 +1,9 @@
|
||||
(ns status-im.ui2.screens.chat.photo-selector.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn remove-photo-container []
|
||||
{:width 14
|
||||
:height 14
|
||||
:border-radius 7
|
||||
:background-color colors/neutral-50
|
||||
:position :absolute
|
||||
:top -7
|
||||
:right -7
|
||||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn gradient-container [safe-area]
|
||||
{:width "100%"
|
||||
:height (+ (:bottom safe-area) 161)
|
||||
:height (+ (:bottom safe-area) 65)
|
||||
:position :absolute
|
||||
:bottom 0})
|
||||
|
||||
|
||||
@@ -13,18 +13,6 @@
|
||||
|
||||
(def selected (reagent/atom []))
|
||||
|
||||
(defn small-image [item]
|
||||
[rn/view
|
||||
[rn/image {:source {:uri item}
|
||||
:style {:width 56
|
||||
:height 56
|
||||
:border-radius 8
|
||||
:margin-bottom 20}}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn [] (reset! selected (vec (remove #(= % item) @selected))))
|
||||
:style (style/remove-photo-container)}
|
||||
[quo2/icon :i/close {:color colors/white :size 12}]]])
|
||||
|
||||
(defn bottom-gradient []
|
||||
[:f>
|
||||
(fn []
|
||||
@@ -35,24 +23,12 @@
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container safe-area)}
|
||||
[rn/flat-list {:key-fn (fn [item] item)
|
||||
:render-fn small-image
|
||||
:data @selected
|
||||
:horizontal true
|
||||
:content-container-style {:padding-horizontal 20 :margin-top 12}
|
||||
:separator [rn/view {:style {:width 12}}]}]
|
||||
[rn/view {:style (style/buttons-container safe-area)}
|
||||
[quo2/button {:type :grey
|
||||
:style {:flex 0.48}
|
||||
:on-press #(js/alert "Add text: to be implemented")}
|
||||
(i18n/label :t/add-text)]
|
||||
[quo2/button {:style {:flex 0.48}
|
||||
:before :send
|
||||
:on-press #(do
|
||||
(rf/dispatch [:chat.ui/send-current-message])
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))}
|
||||
(str (i18n/label :t/send) " " (when (> (count @selected) 1) (count @selected)))]]])))])
|
||||
[quo2/button {:style {:align-self :stretch
|
||||
:margin-horizontal 20}
|
||||
:on-press #(do
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))}
|
||||
(i18n/label :t/confirm-selection)]])))])
|
||||
|
||||
(defn clear-button []
|
||||
(when (pos? (count @selected))
|
||||
@@ -78,14 +54,21 @@
|
||||
(when (some #{item} @selected)
|
||||
[info-count/info-count (+ (utils/first-index #(= item %) @selected) 1) (style/image-count)])])
|
||||
|
||||
(defn on-end-reached [end-cursor]
|
||||
(let [loading? (rf/sub [:camera-roll-loading-more])
|
||||
has-next-page? (rf/sub [:camera-roll-has-next-page])]
|
||||
(when (and (not loading?) has-next-page?)
|
||||
(rf/dispatch [:chat.ui/camera-roll-loading-more true])
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20 end-cursor]))))
|
||||
|
||||
(defn photo-selector []
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20])
|
||||
[:f>
|
||||
(fn []
|
||||
(let [{window-height :height
|
||||
window-width :width} (rn/use-window-dimensions)
|
||||
(let [{window-height :height window-width :width} (rn/use-window-dimensions)
|
||||
safe-area (safe-area/use-safe-area)
|
||||
camera-roll-photos (rf/sub [:camera-roll-photos])]
|
||||
camera-roll-photos (rf/sub [:camera-roll-photos])
|
||||
end-cursor (rf/sub [:camera-roll-end-cursor])]
|
||||
[rn/view {:style {:height (- window-height (:top safe-area))}}
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(js/alert "Camera: not implemented")
|
||||
@@ -104,5 +87,7 @@
|
||||
:num-columns 3
|
||||
:content-container-style {:width "100%"
|
||||
:padding-bottom (+ (:bottom safe-area) 100)}
|
||||
:style {:border-radius 20}}]
|
||||
:style {:border-radius 20}
|
||||
:on-end-reached (fn []
|
||||
(on-end-reached end-cursor))}]
|
||||
[bottom-gradient]]))])
|
||||
|
||||
@@ -100,6 +100,9 @@
|
||||
(reg-root-key-sub :chat/inputs :chat/inputs)
|
||||
(reg-root-key-sub :chat/memberships :chat/memberships)
|
||||
(reg-root-key-sub :camera-roll-photos :camera-roll-photos)
|
||||
(reg-root-key-sub :camera-roll-end-cursor :camera-roll-end-cursor)
|
||||
(reg-root-key-sub :camera-roll-has-next-page :camera-roll-has-next-page)
|
||||
(reg-root-key-sub :camera-roll-loading-more :camera-roll-loading-more)
|
||||
(reg-root-key-sub :group-chat/invitations :group-chat/invitations)
|
||||
(reg-root-key-sub :chats/mention-suggestions :chats/mention-suggestions)
|
||||
(reg-root-key-sub :chat/inputs-with-mentions :chat/inputs-with-mentions)
|
||||
|
||||
@@ -1890,5 +1890,6 @@
|
||||
"unmute-group": "Unmute group",
|
||||
"remove-user-from-group": "Remove {{username}} from the group",
|
||||
"edit-name-image": "Edit name and image",
|
||||
"owner": "Owner"
|
||||
"owner": "Owner",
|
||||
"confirm-selection": "Confirm selection"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user