parent
003b0ffb1e
commit
ba41d4b271
2
Makefile
2
Makefile
|
@ -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,8 @@
|
|||
:output-dir "target/test"
|
||||
:optimizations :simple
|
||||
:target :node-test
|
||||
;; When running tests without a REPL you can uncomment the below line to `make test-watch` a specific file
|
||||
;: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
|
||||
|
|
|
@ -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"))))
|
||||
|
@ -77,8 +77,8 @@
|
|||
(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
|
||||
;; 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?
|
||||
|
@ -86,8 +86,8 @@
|
|||
[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.
|
||||
;; 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?})))
|
||||
|
||||
|
@ -100,13 +100,16 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::camera-roll-get-photos
|
||||
(fn [num]
|
||||
(fn [[num end-cursor]]
|
||||
(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"))))})))
|
||||
(-> (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 #(let [response (types/js->clj %)]
|
||||
(re-frame/dispatch [:on-camera-roll-get-photos (:edges response) (:page_info response) end-cursor])))
|
||||
(.catch #(log/warn "could not get camera roll photos"))))})))
|
||||
|
||||
(fx/defn image-captured
|
||||
{:events [:chat.ui/image-captured]}
|
||||
|
@ -117,15 +120,32 @@
|
|||
(not (get images uri)))
|
||||
{::image-selected [uri current-chat-id]})))
|
||||
|
||||
(fx/defn on-end-reached
|
||||
{:events [:camera-roll/on-end-reached]}
|
||||
[_ end-cursor loading? has-next-page?]
|
||||
(when (and (not loading?) has-next-page?)
|
||||
(re-frame/dispatch [:chat.ui/camera-roll-loading-more true])
|
||||
(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20 end-cursor])))
|
||||
|
||||
(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,8 @@
|
|||
(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-test
|
||||
(let [cofx {:db {:camera-roll/loading-more false}}]
|
||||
(is (= {:db {:camera-roll/loading-more true}}
|
||||
(images/camera-roll-loading-more cofx true)))))
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
[quo/radio {:value true}]])]]))
|
||||
|
||||
(defview photos []
|
||||
(letsubs [camera-roll-photos [:camera-roll-photos]
|
||||
(letsubs [camera-roll-photos [:camera-roll/photos]
|
||||
selected [:chats/sending-image]
|
||||
panel-height (reagent/atom nil)]
|
||||
[react/view {:style {:flex 1
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
:source {:uri uri}}]])
|
||||
|
||||
(defview photos []
|
||||
(letsubs [camera-roll-photos [:camera-roll-photos]]
|
||||
(letsubs [camera-roll-photos [:camera-roll/photos]]
|
||||
{:component-did-mount #(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20])}
|
||||
[react/scroll-view {:horizontal true
|
||||
:style {:max-height 88}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
(ns status-im.ui2.screens.chat.composer.images.view
|
||||
(: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}}]}])
|
|
@ -102,7 +102,7 @@
|
|||
prev-text (get @input-texts chat-id)]
|
||||
(when (and (seq prev-text) (empty? text) (not sending-image))
|
||||
(hide-send refs))
|
||||
(when (and (empty? prev-text) (seq text))
|
||||
(when (and (empty? prev-text) (or (seq text) sending-image))
|
||||
(show-send refs))
|
||||
|
||||
(when (and (not (get @mentions-enabled? chat-id)) (string/index-of text "@"))
|
||||
|
|
|
@ -79,3 +79,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.images.view :as composer-images]
|
||||
[status-im.ui2.screens.chat.composer.style :as style]))
|
||||
|
||||
(defn calculate-y [context min-y max-y added-value chat-id]
|
||||
(let [input-text (:input-text (get (<sub [:chat/inputs]) chat-id))
|
||||
|
@ -41,8 +43,9 @@
|
|||
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 min-y max-y added-value max-height chat-id suggestions reply]
|
||||
(defn get-y-value [context min-y max-y added-value max-height chat-id suggestions reply images]
|
||||
(let [y (calculate-y context min-y max-y added-value chat-id)
|
||||
y (+ y (when (seq images) 80))
|
||||
y-with-mentions (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)]
|
||||
(+ y (when (seq suggestions) y-with-mentions))))
|
||||
|
||||
|
@ -146,13 +149,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 min-y max-y added-value max-height chat-id suggestions reply)
|
||||
y (get-y-value context 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)
|
||||
|
@ -170,8 +174,10 @@
|
|||
(quo.react/effect! #(do
|
||||
(when (and @keyboard-was-shown? (not keyboard-shown))
|
||||
(swap! context assoc :state :min))
|
||||
(when blank-composer?
|
||||
(when (and blank-composer? (not (seq images)))
|
||||
(clean-and-minimize-composer-fn false))
|
||||
(when (seq images)
|
||||
(input/show-send refs))
|
||||
(reset! keyboard-was-shown? keyboard-shown)
|
||||
(if (#{:max :custom-chat-unavailable} (:state @context))
|
||||
(set-bg-opacity 1)
|
||||
|
@ -185,26 +191,27 @@
|
|||
[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))}
|
||||
(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 edit clean-and-minimize-composer-fn]
|
||||
[reply/reply-message-auto-focus-wrapper text-input-ref reply]
|
||||
[rn/view {:style {:height (- max-y 80 added-value)}}
|
||||
[input/text-input {:chat-id chat-id
|
||||
:on-content-size-change input-content-change
|
||||
:sending-image false
|
||||
:sending-image (seq images)
|
||||
:initial-value initial-value
|
||||
:refs refs
|
||||
: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]}])
|
||||
{:content (fn []
|
||||
(photo-selector/photo-selector chat-id))}])
|
||||
:on-denied (fn []
|
||||
(utils/set-timeout
|
||||
#(utils/show-popup (i18n/label :t/error)
|
||||
|
@ -219,8 +226,8 @@
|
|||
[rn/view {:flex 1}]
|
||||
;;SEND button
|
||||
[rn/view {:ref send-ref
|
||||
:style (when-not (seq (get @input/input-texts chat-id)) {:width 0
|
||||
:right -100})}
|
||||
:style (when (seq images) {:width 0
|
||||
:right -100})}
|
||||
[quo2.button/button {:icon true
|
||||
:size 32
|
||||
:accessibility-label :send-message-button
|
||||
|
@ -231,5 +238,6 @@
|
|||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
||||
{:opacity bg-opacity
|
||||
:transform [{:translateY bg-bottom}]}
|
||||
(styles/bottom-sheet-background window-height))}]
|
||||
(style/bottom-sheet-background window-height))}]
|
||||
[composer-images/images-list images]
|
||||
[mentions/autocomplete-mentions suggestions text-input-ref]]))])))])
|
||||
|
|
|
@ -1,22 +1,12 @@
|
|||
(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})
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]))
|
||||
|
||||
(defn gradient-container [safe-area]
|
||||
{:width "100%"
|
||||
:height (+ (:bottom safe-area) 161)
|
||||
:height (+ (:bottom safe-area) 65)
|
||||
:position :absolute
|
||||
:bottom 0})
|
||||
:bottom (if platform/ios? 0 80)})
|
||||
|
||||
(defn buttons-container [safe-area]
|
||||
{:flex-direction :row
|
||||
|
|
|
@ -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,14 @@
|
|||
: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
|
||||
(doseq [item @selected]
|
||||
(rf/dispatch [:chat.ui/camera-roll-pick item]))
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))}
|
||||
(i18n/label :t/confirm-selection)]])))])
|
||||
|
||||
(defn clear-button []
|
||||
(when (pos? (count @selected))
|
||||
|
@ -60,17 +38,13 @@
|
|||
:style (style/clear-container)}
|
||||
[quo2/text {:weight :medium} (i18n/label :t/clear)]]))
|
||||
|
||||
(defn image [item index window-width]
|
||||
(defn image [item index _ {:keys [window-width]}]
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(if (some #{item} @selected)
|
||||
(do
|
||||
(reset! selected (vec (remove #(= % item) @selected)))
|
||||
(rf/dispatch [:chat.ui/image-unselected item]))
|
||||
(do
|
||||
(swap! selected conj item)
|
||||
(rf/dispatch [:chat.ui/camera-roll-pick item]))))}
|
||||
(reset! selected (vec (remove #(= % item) @selected)))
|
||||
(swap! selected conj item)))}
|
||||
[rn/image {:source {:uri item}
|
||||
:style (style/image window-width index)}]
|
||||
(when (some #{item} @selected)
|
||||
|
@ -78,31 +52,38 @@
|
|||
(when (some #{item} @selected)
|
||||
[info-count/info-count (+ (utils/first-index #(= item %) @selected) 1) (style/image-count)])])
|
||||
|
||||
(defn photo-selector []
|
||||
(defn photo-selector [chat-id]
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20])
|
||||
[:f>
|
||||
(fn []
|
||||
(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])]
|
||||
[rn/view {:style {:height (- window-height (:top safe-area))}}
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(js/alert "Camera: not implemented")
|
||||
:style (style/camera-button-container)}
|
||||
[quo2/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:position :absolute
|
||||
:align-self :center}}
|
||||
[quo2/text {:weight :medium} (i18n/label :t/recent)]
|
||||
[rn/view {:style (style/chevron-container)}
|
||||
[quo2/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
|
||||
[clear-button]
|
||||
[rn/flat-list {:key-fn (fn [item] item)
|
||||
:render-fn (fn [item index] (image item index window-width))
|
||||
:data camera-roll-photos
|
||||
:num-columns 3
|
||||
:content-container-style {:width "100%"
|
||||
:padding-bottom (+ (:bottom safe-area) 100)}
|
||||
:style {:border-radius 20}}]
|
||||
[bottom-gradient]]))])
|
||||
(let [selected-images (keys (get-in (rf/sub [:chat/inputs]) [chat-id :metadata :sending-image]))]
|
||||
(when selected-images
|
||||
(reset! selected (vec selected-images)))
|
||||
[:f>
|
||||
(fn []
|
||||
(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])
|
||||
end-cursor (rf/sub [:camera-roll/end-cursor])
|
||||
loading? (rf/sub [:camera-roll/loading-more])
|
||||
has-next-page? (rf/sub [:camera-roll/has-next-page])]
|
||||
[rn/view {:style {:height (- window-height (:top safe-area))}}
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(js/alert "Camera: not implemented")
|
||||
:style (style/camera-button-container)}
|
||||
[quo2/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
||||
[rn/view {:style {:flex-direction :row
|
||||
:position :absolute
|
||||
:align-self :center}}
|
||||
[quo2/text {:weight :medium} (i18n/label :t/recent)]
|
||||
[rn/view {:style (style/chevron-container)}
|
||||
[quo2/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
|
||||
[clear-button]
|
||||
[rn/flat-list {:key-fn (fn [item] item)
|
||||
:render-fn image
|
||||
:render-data {:window-width window-width}
|
||||
:data camera-roll-photos
|
||||
:num-columns 3
|
||||
:content-container-style {:width "100%"
|
||||
:padding-bottom (+ (:bottom safe-area) 100)}
|
||||
:style {:border-radius 20}
|
||||
:on-end-reached #(rf/dispatch [:camera-roll/on-end-reached end-cursor loading? has-next-page?])}]
|
||||
[bottom-gradient]]))]))
|
||||
|
|
|
@ -99,7 +99,10 @@
|
|||
(reg-root-key-sub :selected-participants :selected-participants)
|
||||
(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/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)
|
||||
|
|
|
@ -1911,5 +1911,6 @@
|
|||
"try-your-luck-again": "Try your luck again!",
|
||||
"instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”",
|
||||
"show-existing-keys": "Show Existing Keys",
|
||||
"scan-sync-code": "Scan Sync Code"
|
||||
"scan-sync-code": "Scan Sync Code",
|
||||
"confirm-selection": "Confirm selection"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue