Photo selector and album selector screens (#14867)
* feat: photo & album selector screens
This commit is contained in:
parent
fb9309f700
commit
b8eab0c328
|
@ -14,7 +14,7 @@
|
|||
counter-value -> number
|
||||
increase-padding-top? -> boolean
|
||||
blur? -> boolean"
|
||||
[{:keys [label chevron-position counter-value increase-padding-top? blur?]}]
|
||||
[{:keys [label chevron-position counter-value increase-padding-top? blur? container-style]}]
|
||||
(let [dark? (colors/dark?)
|
||||
border-and-counter-bg-color (if dark?
|
||||
(if blur? colors/white-opa-5 colors/neutral-70)
|
||||
|
@ -25,12 +25,13 @@
|
|||
[rn/view
|
||||
{:accessible true
|
||||
:accessibility-label :divider-label
|
||||
:style {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}}
|
||||
:style (merge {:border-top-width 1
|
||||
:border-top-color border-and-counter-bg-color
|
||||
:padding-top padding-top
|
||||
:padding-horizontal 16
|
||||
:align-items :center
|
||||
:flex-direction :row}
|
||||
container-style)}
|
||||
(when (= chevron-position :left)
|
||||
[rn/view
|
||||
{:test-ID :divider-label-icon-left
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
(def ^:private themes
|
||||
{:container {:dark {:background-color colors/white-opa-70}
|
||||
:light {:background-color colors/neutral-80-opa-70}}
|
||||
:light {:background-color colors/neutral-80-opa-90}}
|
||||
:text {:dark {:color colors/neutral-100}
|
||||
:light {:color colors/white}}
|
||||
:icon {:dark {:color colors/neutral-100}
|
||||
|
@ -51,8 +51,8 @@
|
|||
[i18n/label :t/undo]]])
|
||||
|
||||
(defn- toast-container
|
||||
[{:keys [left middle right]}]
|
||||
[rn/view {:style {:padding-left 12 :padding-right 12}}
|
||||
[{:keys [left middle right container-style]}]
|
||||
[rn/view {:style (merge {:padding-left 12 :padding-right 12} container-style)}
|
||||
[rn/view
|
||||
{:style (merge-theme-style :container
|
||||
{:flex-direction :row
|
||||
|
@ -74,14 +74,15 @@
|
|||
(when right right)]])
|
||||
|
||||
(defn toast
|
||||
[{:keys [icon icon-color text action undo-duration undo-on-press]}]
|
||||
[{:keys [icon icon-color text action undo-duration undo-on-press container-style]}]
|
||||
[toast-container
|
||||
{:left (when icon
|
||||
[icon/icon icon
|
||||
{:container-style {:width 20 :height 20}
|
||||
:color (or icon-color
|
||||
(get-in themes [:icon (theme/get-theme) :color]))}])
|
||||
:middle text
|
||||
:right (if undo-duration
|
||||
[toast-undo-action undo-duration undo-on-press]
|
||||
action)}])
|
||||
{:left (when icon
|
||||
[icon/icon icon
|
||||
{:container-style {:width 20 :height 20}
|
||||
:color (or icon-color
|
||||
(get-in themes [:icon (theme/get-theme) :color]))}])
|
||||
:middle text
|
||||
:right (if undo-duration
|
||||
[toast-undo-action undo-duration undo-on-press]
|
||||
action)
|
||||
:container-style container-style}])
|
||||
|
|
|
@ -104,7 +104,7 @@
|
|||
|
||||
(re-frame/reg-fx
|
||||
::camera-roll-get-photos
|
||||
(fn [[num end-cursor]]
|
||||
(fn [[num end-cursor album]]
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage]
|
||||
:on-allowed (fn []
|
||||
|
@ -115,19 +115,69 @@
|
|||
{:first num
|
||||
:after end-cursor
|
||||
:assetType "Photos"
|
||||
:groupTypes "All"
|
||||
:groupTypes (if (= album (i18n/label :t/recent)) "All" "Albums")
|
||||
:groupName (when (not= album (i18n/label :t/recent)) album)
|
||||
:include (clj->js ["imageSize"])})
|
||||
(.getPhotos CameraRoll
|
||||
#js
|
||||
{:first num
|
||||
:assetType "Photos"
|
||||
:groupTypes "All"
|
||||
:include (clj->js ["imageSize"])}))
|
||||
(.getPhotos
|
||||
CameraRoll
|
||||
#js
|
||||
{:first num
|
||||
:assetType "Photos"
|
||||
:groupTypes (if (= album (i18n/label :t/recent)) "All" "Albums")
|
||||
:groupName (when (not= album (i18n/label :t/recent)) album)
|
||||
:include (clj->js ["imageSize"])}))
|
||||
(.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"))))})))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:chat.ui/camera-roll-get-albums
|
||||
(fn []
|
||||
(let [albums (atom [{:title :smart-albums :data []}
|
||||
{:title (i18n/label :t/my-albums) :data []}])]
|
||||
;; Get the "recent" album first
|
||||
(->
|
||||
(.getPhotos CameraRoll
|
||||
#js
|
||||
{:first 1
|
||||
:groupTypes "All"})
|
||||
(.then
|
||||
(fn [res]
|
||||
(let [recent-album {:title (i18n/label :t/recent)
|
||||
:count "--"
|
||||
:uri (get-in (first (:edges (types/js->clj res))) [:node :image :uri])}]
|
||||
(swap! albums update-in [0 :data] conj recent-album)
|
||||
;; Get albums, then loop over albums and get each one's cover (first photo)
|
||||
(->
|
||||
(.getAlbums CameraRoll #js {:assetType "All"})
|
||||
(.then
|
||||
(fn [response]
|
||||
(let [response (types/js->clj response)]
|
||||
(reduce
|
||||
(fn [_ album]
|
||||
(->
|
||||
(.getPhotos
|
||||
CameraRoll
|
||||
#js
|
||||
{:first 1
|
||||
:groupTypes "Albums"
|
||||
:groupName (:title album)})
|
||||
(.then (fn [res]
|
||||
(let [uri (get-in (first (:edges (types/js->clj res)))
|
||||
[:node :image :uri])]
|
||||
(swap! albums update-in [1 :data] conj (merge album {:uri uri}))
|
||||
(when (= (count (get-in @albums [1 :data])) (count response))
|
||||
(swap! albums update-in
|
||||
[1 :data]
|
||||
#(->> %
|
||||
(sort-by :title)))
|
||||
(re-frame/dispatch [:on-camera-roll-get-albums @albums])))))))
|
||||
nil
|
||||
response))))
|
||||
(.catch #(log/warn "could not get camera roll albums"))))))))))
|
||||
|
||||
|
||||
(rf/defn image-captured
|
||||
{:events [:chat.ui/image-captured]}
|
||||
[{:keys [db]} chat-id uri]
|
||||
|
@ -139,15 +189,20 @@
|
|||
|
||||
(rf/defn on-end-reached
|
||||
{:events [:camera-roll/on-end-reached]}
|
||||
[_ end-cursor loading? has-next-page?]
|
||||
[_ end-cursor selected-album 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])))
|
||||
(re-frame/dispatch [:chat.ui/camera-roll-get-photos 20 end-cursor selected-album])))
|
||||
|
||||
(rf/defn camera-roll-get-photos
|
||||
{:events [:chat.ui/camera-roll-get-photos]}
|
||||
[_ num end-cursor]
|
||||
{::camera-roll-get-photos [num end-cursor]})
|
||||
[_ num end-cursor selected-album]
|
||||
{::camera-roll-get-photos [num end-cursor selected-album]})
|
||||
|
||||
(rf/defn camera-roll-get-albums
|
||||
{:events [:chat.ui/camera-roll-get-albums]}
|
||||
[_]
|
||||
{:chat.ui/camera-roll-get-albums []})
|
||||
|
||||
(rf/defn camera-roll-loading-more
|
||||
{:events [:chat.ui/camera-roll-loading-more]}
|
||||
|
@ -164,22 +219,32 @@
|
|||
(assoc :camera-roll/has-next-page (:has_next_page page-info))
|
||||
(assoc :camera-roll/loading-more false))}))
|
||||
|
||||
(rf/defn on-camera-roll-get-albums
|
||||
{:events [:on-camera-roll-get-albums]}
|
||||
[{:keys [db]} albums]
|
||||
{:db (-> db
|
||||
(assoc :camera-roll/albums albums)
|
||||
(assoc :camera-roll/loading-albums false))})
|
||||
|
||||
(rf/defn clear-sending-images
|
||||
{:events [:chat.ui/clear-sending-images]}
|
||||
[{:keys [db]} current-chat-id]
|
||||
{:db (update-in db [:chat/inputs current-chat-id :metadata] assoc :sending-image {})})
|
||||
[{:keys [db]}]
|
||||
{:db (update-in db [:chat/inputs (:current-chat-id db) :metadata] assoc :sending-image {})})
|
||||
|
||||
(rf/defn cancel-sending-image
|
||||
{:events [:chat.ui/cancel-sending-image]}
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
(clear-sending-images cofx current-chat-id)))
|
||||
(clear-sending-images cofx))
|
||||
|
||||
(rf/defn image-selected
|
||||
{:events [:chat.ui/image-selected]}
|
||||
[{:keys [db]} current-chat-id original uri]
|
||||
{:db
|
||||
(update-in db [:chat/inputs current-chat-id :metadata :sending-image uri] merge original {:uri uri})})
|
||||
(update-in db
|
||||
[:chat/inputs current-chat-id :metadata :sending-image (:uri original)]
|
||||
merge
|
||||
original
|
||||
{:resized-uri uri})})
|
||||
|
||||
(rf/defn image-unselected
|
||||
{:events [:chat.ui/image-unselected]}
|
||||
|
@ -215,6 +280,11 @@
|
|||
(not (some #(= (:uri image) (:uri %)) images)))
|
||||
{::image-selected [image current-chat-id]}))))
|
||||
|
||||
(rf/defn camera-roll-select-album
|
||||
{:events [:chat.ui/camera-roll-select-album]}
|
||||
[{:keys [db]} album]
|
||||
{:db (assoc db :camera-roll/selected-album album)})
|
||||
|
||||
(rf/defn save-image-to-gallery
|
||||
{:events [:chat.ui/save-image-to-gallery]}
|
||||
[_ base64-uri]
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
(rf/defn set-chat-input-text
|
||||
"Set input text for current-chat. Takes db and input text and cofx
|
||||
as arguments and returns new fx. Always clear all validation messages."
|
||||
as arguments and returns new fx. Always clear all validation messages."
|
||||
{:events [:chat.ui/set-chat-input-text]}
|
||||
[{db :db} new-input chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
|
@ -150,11 +150,11 @@
|
|||
[{db :db} chat-id input-text]
|
||||
(let [images (get-in db [:chat/inputs chat-id :metadata :sending-image])
|
||||
album-id (str (random-uuid))]
|
||||
(mapv (fn [[_ {:keys [uri width height]}]]
|
||||
(mapv (fn [[_ {:keys [resized-uri width height]}]]
|
||||
{:chat-id chat-id
|
||||
:album-id album-id
|
||||
:content-type constants/content-type-image
|
||||
:image-path (utils/safe-replace uri #"file://" "")
|
||||
:image-path (utils/safe-replace resized-uri #"file://" "")
|
||||
:image-width width
|
||||
:image-height height
|
||||
;; TODO: message not received if text field is
|
||||
|
|
|
@ -161,8 +161,10 @@
|
|||
|
||||
(rf/defn on-going-in-background
|
||||
[{:keys [db now]}]
|
||||
{:db (assoc db :app-in-background-since now)
|
||||
:dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]]})
|
||||
{:db (assoc db :app-in-background-since now)
|
||||
;; event not implemented
|
||||
;; :dispatch-n [[:audio-recorder/on-background] [:audio-message/on-background]]
|
||||
})
|
||||
|
||||
(rf/defn app-state-change
|
||||
{:events [:app-state-change]}
|
||||
|
|
|
@ -90,8 +90,10 @@
|
|||
{:style {:padding-top 16
|
||||
:align-items :center}}
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (bottom-sheet (boolean image) editing?)}])}
|
||||
{:on-press (fn []
|
||||
(rn/dismiss-keyboard!)
|
||||
(rf/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (bottom-sheet (boolean image) editing?)}]))}
|
||||
[rn/view
|
||||
{:style {:width 128
|
||||
:height 128}}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
;; so we need some magic here with paddings so close button isn't cut
|
||||
[rn/view {:padding-top 12 :padding-bottom 8 :padding-right 12}
|
||||
[rn/image
|
||||
{:source {:uri (:uri (val item))}
|
||||
{:source {:uri (:resized-uri (val item))}
|
||||
:style style/small-image}]
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn [] (rf/dispatch [:chat.ui/image-unselected (val item)]))
|
||||
|
|
|
@ -207,27 +207,30 @@
|
|||
(def ^:const delete-message-undo-time-limit-ms 4000)
|
||||
(def ^:const delete-message-for-me-undo-time-limit-ms 4000)
|
||||
|
||||
(def ^:const album-image-sizes
|
||||
{2 {0 146
|
||||
1 146}
|
||||
3 {0 [292 194]
|
||||
1 [145 97]
|
||||
2 [145 97]}
|
||||
4 {0 146
|
||||
1 146
|
||||
2 146
|
||||
3 146}
|
||||
5 {0 146
|
||||
1 146
|
||||
2 97
|
||||
3 97
|
||||
4 97}
|
||||
:default {0 146
|
||||
1 146
|
||||
2 72.5
|
||||
3 72.5
|
||||
4 72.5
|
||||
5 72.5}})
|
||||
(def ^:const max-album-photos 6)
|
||||
(def ^:const image-size 146)
|
||||
|
||||
(def album-image-sizes ; sometimes we subtract 1 or 0.5 for padding
|
||||
{2 {0 image-size
|
||||
1 image-size}
|
||||
3 {0 [(* image-size 2) (* image-size 1.5)]
|
||||
1 [(- image-size 1) (- (* image-size 0.67) 1)]
|
||||
2 [(- image-size 1) (- (* image-size 0.67) 1)]}
|
||||
4 {0 image-size
|
||||
1 image-size
|
||||
2 image-size
|
||||
3 image-size}
|
||||
5 {0 image-size
|
||||
1 image-size
|
||||
2 (- (* image-size 0.67) 1)
|
||||
3 (- (* image-size 0.67) 1)
|
||||
4 (- (* image-size 0.67) 1)}
|
||||
:default {0 image-size
|
||||
1 image-size
|
||||
2 (- (* image-size 0.5) 0.5)
|
||||
3 (- (* image-size 0.5) 0.5)
|
||||
4 (- (* image-size 0.5) 0.5)
|
||||
5 (- (* image-size 0.5) 0.5)}})
|
||||
|
||||
(def ^:const spam-message-frequency-threshold 4)
|
||||
(def ^:const spam-interval-ms 1000)
|
||||
|
|
|
@ -324,10 +324,12 @@
|
|||
(rf/dispatch [:bottom-sheet/hide])
|
||||
(rf/dispatch [:chat.ui/remove-chat chat-id]))}})
|
||||
|
||||
(rf/defn navigate-to-horizontal-images
|
||||
{:events [:chat.ui/navigate-to-horizontal-images]}
|
||||
[cofx messages index]
|
||||
(navigation/navigate-to cofx :images-horizontal {:messages messages :index index}))
|
||||
(rf/defn navigate-to-user-pinned-messages
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
{:events [:chat.ui/navigate-to-pinned-messages]}
|
||||
[cofx chat-id]
|
||||
(navigation/navigate-to cofx :chat-pinned-messages {:chat-id chat-id}))
|
||||
|
||||
|
||||
(rf/defn update-shared-element-id
|
||||
{:events [:chat.ui/update-shared-element-id]}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im2.contexts.chat.images-horizontal.style
|
||||
(ns status-im2.contexts.chat.lightbox.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn container-view
|
|
@ -1,12 +1,13 @@
|
|||
(ns status-im2.contexts.chat.images-horizontal.view
|
||||
(ns status-im2.contexts.chat.lightbox.view
|
||||
(:require [quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :as oops]
|
||||
[status-im2.contexts.chat.images-horizontal.style :as style]
|
||||
[status-im2.contexts.chat.lightbox.style :as style]
|
||||
[utils.datetime :as datetime]
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
|
@ -20,7 +21,7 @@
|
|||
window-width (:width (rn/get-window))
|
||||
height (* (or (:image-height message) 1000)
|
||||
(/ window-width (or (:image-width message) 1000)))]
|
||||
[rn/image
|
||||
[fast-image/fast-image
|
||||
{:source {:uri (:image (:content message))}
|
||||
:style {:width window-width
|
||||
:height height
|
||||
|
@ -77,7 +78,7 @@
|
|||
|
||||
(defn small-image
|
||||
[item]
|
||||
[rn/image
|
||||
[fast-image/fast-image
|
||||
{:source {:uri (:image (:content item))}
|
||||
:style {:width small-image-size
|
||||
:height small-image-size
|
||||
|
@ -105,7 +106,7 @@
|
|||
:content-container-style {:padding-vertical 12
|
||||
:padding-horizontal padding-horizontal}}]]))
|
||||
|
||||
(defn images-horizontal
|
||||
(defn lightbox
|
||||
[]
|
||||
(let [{:keys [messages index]} (rf/sub [:get-screen-params])
|
||||
;; The initial value of data is the image that was pressed (and not the whole album) in order for
|
|
@ -5,7 +5,6 @@
|
|||
[utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[status-im2.common.not-implemented :as not-implemented]
|
||||
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
|
||||
[status-im2.contexts.chat.messages.composer.controls.style :as style]
|
||||
[status-im2.contexts.chat.messages.list.view :as messages.list]
|
||||
[status-im.ui.components.permissions :as permissions]
|
||||
|
@ -45,9 +44,7 @@
|
|||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage :write-external-storage]
|
||||
:on-allowed #(rf/dispatch
|
||||
[:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
(photo-selector/photo-selector chat-id))}])
|
||||
[:open-modal :photo-selector {:chat-id chat-id}])
|
||||
:on-denied (fn []
|
||||
(background-timer/set-timeout
|
||||
#(utils-old/show-popup (i18n/label :t/error)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im2.contexts.chat.messages.content.album.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[status-im2.constants :as constants]))
|
||||
|
||||
(def max-album-height 292)
|
||||
|
||||
|
@ -7,15 +8,18 @@
|
|||
[portrait?]
|
||||
{:flex-direction (if portrait? :column :row)
|
||||
:flex-wrap :wrap
|
||||
:max-height max-album-height})
|
||||
:max-height max-album-height
|
||||
:border-radius 12
|
||||
:width (inc (* constants/image-size 2))
|
||||
:overflow :hidden})
|
||||
|
||||
(defn image
|
||||
[dimensions index]
|
||||
[dimensions index portrait?]
|
||||
{:width (:width dimensions)
|
||||
:height (:height dimensions)
|
||||
:margin-left (when (or (and (not= index 0) (not= index 2) (not= count 3))
|
||||
(= count 3)
|
||||
(= index 2))
|
||||
(and portrait? (= index 2)))
|
||||
1)
|
||||
:margin-bottom (when (< index 2) 1)
|
||||
:align-self :flex-start})
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
(:require [quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[status-im2.contexts.chat.messages.content.album.style :as style]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.messages.content.image.view :as image]))
|
||||
(def max-display-count 6)
|
||||
|
||||
(def rectangular-style-count 3)
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
(defn border-brr
|
||||
[index count]
|
||||
(when (or (and (= index 1) (< count rectangular-style-count))
|
||||
(and (= index (- (min count max-display-count) 1)) (> count 2)))
|
||||
(and (= index (- (min count constants/max-album-photos) 1)) (> count 2)))
|
||||
12))
|
||||
|
||||
(defn find-size
|
||||
|
@ -42,7 +42,7 @@
|
|||
{:width (second size-arr) :height (first size-arr) :album-style album-style}))
|
||||
|
||||
(defn album-message
|
||||
[{:keys [albumize?] :as message} {:keys [on-long-press] :as context}]
|
||||
[{:keys [albumize?] :as message}]
|
||||
(let [shared-element-id (rf/sub [:shared-element-id])
|
||||
first-image (first (:album message))
|
||||
album-style (if (> (:image-width first-image) (:image-height first-image))
|
||||
|
@ -57,7 +57,7 @@
|
|||
{:style (style/album-container portrait?)}
|
||||
(map-indexed
|
||||
(fn [index item]
|
||||
(let [images-size-key (if (< images-count max-display-count) images-count :default)
|
||||
(let [images-size-key (if (< images-count constants/max-album-photos) images-count :default)
|
||||
size (get-in constants/album-image-sizes [images-size-key index])
|
||||
dimensions (if (not= images-count rectangular-style-count)
|
||||
{:width size :height size}
|
||||
|
@ -67,22 +67,17 @@
|
|||
:active-opacity 1
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id (:message-id item)])
|
||||
(js/setTimeout #(rf/dispatch [:chat.ui/navigate-to-horizontal-images
|
||||
(:album message) index])
|
||||
100))
|
||||
:on-long-press on-long-press}
|
||||
[rn/image
|
||||
{:style (merge
|
||||
(style/image dimensions index)
|
||||
{:border-top-left-radius (border-tlr index)
|
||||
:border-top-right-radius (border-trr index images-count album-style)
|
||||
:border-bottom-left-radius (border-blr index images-count album-style)
|
||||
:border-bottom-right-radius (border-brr index images-count)})
|
||||
(js/setTimeout #(rf/dispatch [:navigate-to :lightbox
|
||||
{:messages (:album message) :index index}])
|
||||
100))}
|
||||
[fast-image/fast-image
|
||||
{:style (style/image dimensions index portrait?)
|
||||
:source {:uri (:image (:content item))}
|
||||
:native-ID (when (and (= shared-element-id (:message-id item))
|
||||
(< index max-display-count))
|
||||
(< index constants/max-album-photos))
|
||||
:shared-element)}]
|
||||
(when (and (> images-count max-display-count) (= index (- max-display-count 1)))
|
||||
(when (and (> images-count constants/max-album-photos)
|
||||
(= index (- constants/max-album-photos 1)))
|
||||
[rn/view
|
||||
{:style (merge style/overlay
|
||||
{:border-bottom-right-radius (border-brr index images-count)})}
|
||||
|
@ -90,11 +85,10 @@
|
|||
{:weight :bold
|
||||
:size :heading-2
|
||||
:style {:color colors/white}}
|
||||
(str "+" (- images-count (dec max-display-count)))]])]))
|
||||
(str "+" (- images-count (dec constants/max-album-photos)))]])]))
|
||||
(:album message))]
|
||||
|
||||
[:<>
|
||||
(map-indexed
|
||||
(fn [index item]
|
||||
[image/image-message index item context])
|
||||
[image/image-message index item])
|
||||
(:album message))])))
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im2.contexts.chat.messages.content.image.view
|
||||
(:require [react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn calculate-dimensions
|
||||
|
@ -15,24 +16,24 @@
|
|||
{:width calculated-width :height calculated-height}))))
|
||||
|
||||
(defn image-message
|
||||
[index {:keys [content image-width image-height message-id] :as message} {:keys [on-long-press]}]
|
||||
[index {:keys [content image-width image-height message-id] :as message}]
|
||||
(let [dimensions (calculate-dimensions (or image-width 1000) (or image-height 1000))
|
||||
text (:text content)]
|
||||
(fn []
|
||||
(let [shared-element-id (rf/sub [:shared-element-id])]
|
||||
[rn/touchable-opacity
|
||||
{:style {:margin-top (when (> index 0) 20) :width (:width dimensions)}
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id message-id])
|
||||
(js/setTimeout #(rf/dispatch [:chat.ui/navigate-to-horizontal-images
|
||||
[message] 0])
|
||||
100))
|
||||
:on-long-press on-long-press}
|
||||
[rn/view
|
||||
;; This text comp is temporary. Should later use
|
||||
;; `status-im2.contexts.chat.messages.content.text.view`
|
||||
(when (and (not= text "placeholder") (= index 0)) [rn/text text])
|
||||
[rn/image
|
||||
{:source {:uri (:image content)}
|
||||
:style (merge dimensions {:border-radius 12})
|
||||
:native-ID (when (= shared-element-id message-id) :shared-element)}]]]))))
|
||||
{:active-opacity 1
|
||||
:key message-id
|
||||
:style {:margin-top (when (> index 0) 20)}
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id message-id])
|
||||
(js/setTimeout #(rf/dispatch [:navigate-to :lightbox
|
||||
{:messages [message] :index 0}])
|
||||
100))}
|
||||
;; This text comp is temporary. Should later use
|
||||
;; `status-im2.contexts.chat.messages.content.text.view`
|
||||
(when (and (not= text "placeholder") (= index 0)) [rn/text text])
|
||||
[fast-image/fast-image
|
||||
{:source {:uri (:image content)}
|
||||
:style (merge dimensions {:border-radius 12})
|
||||
:native-ID (when (= shared-element-id message-id) :shared-element)}]]))))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im2.contexts.chat.messages.content.view
|
||||
(:require [react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im.utils.utils :as utils]
|
||||
[status-im2.contexts.chat.messages.content.style :as style]
|
||||
[status-im2.contexts.chat.messages.content.pin.view :as pin]
|
||||
[status-im2.constants :as constants]
|
||||
|
@ -16,8 +17,7 @@
|
|||
[utils.re-frame :as rf]
|
||||
[status-im.ui2.screens.chat.messages.message :as old-message]
|
||||
[status-im2.common.not-implemented :as not-implemented]
|
||||
[utils.datetime :as datetime]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[utils.datetime :as datetime]))
|
||||
|
||||
(defn avatar
|
||||
[{:keys [content last-in-group? pinned quoted-message from]}]
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
(ns status-im2.contexts.chat.photo-selector.album-selector.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(defn album-container
|
||||
[selected?]
|
||||
{:flex-direction :row
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 8
|
||||
:margin-horizontal 8
|
||||
:border-radius 12
|
||||
:align-items :center
|
||||
:background-color (when selected? colors/primary-50-opa-5)})
|
||||
|
||||
(def cover
|
||||
{:width 40
|
||||
:height 40
|
||||
:border-radius 10})
|
||||
|
||||
(def divider
|
||||
{:padding-horizontal 20
|
||||
:margin-top 16
|
||||
:margin-bottom 8})
|
|
@ -0,0 +1,64 @@
|
|||
(ns status-im2.contexts.chat.photo-selector.album-selector.view
|
||||
(:require
|
||||
[quo2.core :as quo]
|
||||
[react-native.core :as rn]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im2.contexts.chat.photo-selector.view :refer [album-title]]
|
||||
[status-im2.contexts.chat.photo-selector.album-selector.style :as style]))
|
||||
|
||||
(defn album
|
||||
[{:keys [title count uri]} index _ selected-album]
|
||||
(let [selected? (= selected-album title)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/camera-roll-select-album title])
|
||||
(rf/dispatch [:navigate-back]))
|
||||
:style (style/album-container selected?)
|
||||
:accessibility-label (str "album-" index)}
|
||||
[rn/image
|
||||
{:source {:uri uri}
|
||||
:style style/cover}]
|
||||
[rn/view {:style {:margin-left 12}}
|
||||
[quo/text {:weight :medium} title]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
(str count " " (i18n/label :t/images))]]
|
||||
(when selected?
|
||||
[rn/view
|
||||
{:style {:position :absolute
|
||||
:right 16}}
|
||||
[quo/icon :i/check
|
||||
{:size 20 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]])]))
|
||||
|
||||
(defn section-header
|
||||
[{:keys [title]}]
|
||||
(when (not= title "smart-albums")
|
||||
[quo/divider-label
|
||||
{:label title
|
||||
:container-style style/divider}]))
|
||||
|
||||
(defn album-selector
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [albums (rf/sub [:camera-roll/albums])
|
||||
selected-album (or (rf/sub [:camera-roll/selected-album]) (i18n/label :t/recent))]
|
||||
(rn/use-effect-once
|
||||
(fn []
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-albums])
|
||||
js/undefined))
|
||||
[rn/view {:style {:padding-top 20}}
|
||||
[album-title false selected-album]
|
||||
[rn/section-list
|
||||
{:data albums
|
||||
:render-fn album
|
||||
:render-data selected-album
|
||||
:sections albums
|
||||
:sticky-section-headers-enabled false
|
||||
:render-section-header-fn section-header
|
||||
:style {:margin-top 12}
|
||||
:content-container-style {:padding-bottom 40}
|
||||
:key-fn :title}]]))])
|
|
@ -3,28 +3,31 @@
|
|||
[react-native.platform :as platform]))
|
||||
|
||||
(defn gradient-container
|
||||
[safe-area]
|
||||
{:width "100%"
|
||||
:height (+ (:bottom safe-area) 65)
|
||||
[insets]
|
||||
{:left 0
|
||||
:right 0
|
||||
:height (+ (:bottom insets) (if platform/ios? 65 85))
|
||||
:position :absolute
|
||||
:bottom (if platform/ios? 0 (:bottom safe-area))})
|
||||
:bottom 0})
|
||||
|
||||
(defn buttons-container
|
||||
[safe-area]
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:padding-horizontal 20
|
||||
:bottom (+ (:bottom safe-area) 33)})
|
||||
(def buttons-container
|
||||
{:position :absolute
|
||||
:flex-direction :row
|
||||
:left 0
|
||||
:right 0
|
||||
:margin-top 20
|
||||
:margin-bottom 12
|
||||
:justify-content :center
|
||||
:z-index 1})
|
||||
|
||||
(defn clear-container
|
||||
[]
|
||||
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
|
||||
:position :absolute
|
||||
:align-self :flex-end
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 5
|
||||
:right 20
|
||||
:border-radius 10})
|
||||
:border-radius 10
|
||||
:position :absolute
|
||||
:right 20})
|
||||
|
||||
(defn camera-button-container
|
||||
[]
|
||||
|
@ -34,17 +37,21 @@
|
|||
:border-radius 10
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:margin-left 20
|
||||
:margin-bottom 24})
|
||||
:position :absolute
|
||||
:left 20})
|
||||
|
||||
(def title-container
|
||||
{:flex-direction :row
|
||||
:position :absolute
|
||||
:align-self :center})
|
||||
(defn title-container
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
|
||||
:border-radius 10
|
||||
:padding-horizontal 12
|
||||
:padding-vertical 5
|
||||
:align-self :center})
|
||||
|
||||
(defn chevron-container
|
||||
[]
|
||||
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
|
||||
{:background-color (colors/theme-colors colors/neutral-30 colors/neutral-100)
|
||||
:width 14
|
||||
:height 14
|
||||
:border-radius 7
|
||||
|
@ -55,10 +62,12 @@
|
|||
|
||||
(defn image
|
||||
[window-width index]
|
||||
{:width (- (/ window-width 3) 0.67)
|
||||
:height (/ window-width 3)
|
||||
:margin-left (when (not= (mod index 3) 0) 1)
|
||||
:margin-bottom 1})
|
||||
{:width (- (/ window-width 3) 0.67)
|
||||
:height (/ window-width 3)
|
||||
:margin-left (when (not= (mod index 3) 0) 1)
|
||||
:margin-bottom 1
|
||||
:border-top-left-radius (when (= index 0) 10)
|
||||
:border-top-right-radius (when (= index 2) 10)})
|
||||
|
||||
(defn overlay
|
||||
[window-width]
|
||||
|
|
|
@ -1,48 +1,46 @@
|
|||
(ns status-im2.contexts.chat.photo-selector.view
|
||||
(:require [utils.i18n :as i18n]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[quo2.components.notifications.info-count :as info-count]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.photo-selector.style :as style]
|
||||
[status-im.utils.core :as utils]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(def selected (reagent/atom []))
|
||||
(:require
|
||||
[react-native.platform :as platform]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[quo2.components.notifications.info-count :as info-count]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.photo-selector.style :as style]
|
||||
[status-im.utils.core :as utils]
|
||||
[quo.react]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn on-press-confirm-selection
|
||||
[chat-id]
|
||||
(rf/dispatch [:chat.ui/clear-sending-images chat-id])
|
||||
[selected]
|
||||
(rf/dispatch [:chat.ui/clear-sending-images])
|
||||
(doseq [item @selected]
|
||||
(rf/dispatch [:chat.ui/camera-roll-pick item]))
|
||||
(reset! selected [])
|
||||
(rf/dispatch [:bottom-sheet/hide]))
|
||||
(rf/dispatch [:navigate-back]))
|
||||
|
||||
(defn bottom-gradient
|
||||
[chat-id selected-images]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [safe-area (safe-area/use-safe-area)]
|
||||
(when (or (seq @selected) selected-images)
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container safe-area)}
|
||||
[quo/button
|
||||
{:style {:align-self :stretch
|
||||
:margin-horizontal 20}
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:bottom-sheet/hide])
|
||||
(on-press-confirm-selection chat-id))
|
||||
:accessibility-label :confirm-selection}
|
||||
(i18n/label :t/confirm-selection)]])))])
|
||||
[selected-images insets selected]
|
||||
(when (or (seq @selected) (seq selected-images))
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container insets)}
|
||||
[quo/button
|
||||
{:style {:align-self :stretch
|
||||
:margin-horizontal 20
|
||||
:margin-top 12}
|
||||
:on-press #(on-press-confirm-selection selected)
|
||||
:accessibility-label :confirm-selection}
|
||||
(i18n/label :t/confirm-selection)]]))
|
||||
|
||||
(defn clear-button
|
||||
[]
|
||||
[selected]
|
||||
(when (seq @selected)
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(reset! selected [])
|
||||
|
@ -52,66 +50,87 @@
|
|||
|
||||
(defn remove-selected
|
||||
[coll item]
|
||||
(vec (remove #(= % item) coll)))
|
||||
(vec (remove #(= (:uri item) (:uri %)) coll)))
|
||||
|
||||
(defn image
|
||||
[item index _ {:keys [window-width]}]
|
||||
[item index _ {:keys [window-width selected]}]
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(if (some #{item} @selected)
|
||||
(if (some #(= (:uri item) (:uri %)) @selected)
|
||||
(swap! selected remove-selected item)
|
||||
(swap! selected conj item)))
|
||||
(if (>= (count @selected) constants/max-album-photos)
|
||||
(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
:icon :info
|
||||
:icon-color colors/danger-50-opa-40
|
||||
:container-style {:top (when platform/ios? 20)}
|
||||
:text (i18n/label :t/only-6-images)}])
|
||||
(swap! selected conj item))))
|
||||
:accessibility-label (str "image-" index)}
|
||||
[rn/image
|
||||
{:source {:uri (:uri item)}
|
||||
:style (style/image window-width index)}]
|
||||
(when (some #{item} @selected)
|
||||
(when (some #(= (:uri item) (:uri %)) @selected)
|
||||
[rn/view {:style (style/overlay window-width)}])
|
||||
(when (some #{item} @selected)
|
||||
(when (some #(= (:uri item) (:uri %)) @selected)
|
||||
[info-count/info-count
|
||||
{:style style/image-count
|
||||
:accessibility-label (str "count-" index)}
|
||||
(inc (utils/first-index #(= item %) @selected))])])
|
||||
(inc (utils/first-index #(= (:uri item) (:uri %)) @selected))])])
|
||||
|
||||
(defn album-title
|
||||
[photos? selected-album]
|
||||
[rn/touchable-opacity
|
||||
{:style (style/title-container)
|
||||
:active-opacity 1
|
||||
:accessibility-label :album-title
|
||||
:on-press #(rf/dispatch (if photos?
|
||||
[:open-modal :album-selector]
|
||||
[:navigate-back]))}
|
||||
[quo/text {:weight :medium} selected-album]
|
||||
[rn/view {:style (style/chevron-container)}
|
||||
[quo/icon (if photos? :i/chevron-down :i/chevron-up)
|
||||
{:color (colors/theme-colors colors/neutral-100 colors/white)}]]])
|
||||
|
||||
(defn photo-selector
|
||||
[chat-id]
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20])
|
||||
(let [selected-images (keys (rf/sub [:chats/sending-image]))]
|
||||
[:f>
|
||||
(fn []
|
||||
(rn/use-effect-once
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [selected-images (rf/sub [:chats/sending-image])
|
||||
selected-album (or (rf/sub [:camera-roll/selected-album]) (i18n/label :t/recent))
|
||||
selected (reagent/atom [])]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20 nil selected-album])
|
||||
(if selected-images
|
||||
(reset! selected (vec selected-images))
|
||||
(reset! selected []))
|
||||
js/undefined))
|
||||
(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)}
|
||||
[quo/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
||||
[rn/view
|
||||
{:style style/title-container}
|
||||
[quo/text {:weight :medium} (i18n/label :t/recent)]
|
||||
[rn/view {:style (style/chevron-container)}
|
||||
[quo/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
|
||||
[clear-button]
|
||||
[rn/flat-list
|
||||
{:key-fn identity
|
||||
: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 chat-id selected-images]]))]))
|
||||
(reset! selected (vec (vals selected-images)))
|
||||
(reset! selected [])))
|
||||
[selected-album])
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
(let [window-width (:width (rn/get-window))
|
||||
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 {:flex 1}}
|
||||
[rn/view
|
||||
{:style style/buttons-container}
|
||||
[album-title true selected-album]
|
||||
[clear-button selected]]
|
||||
[rn/flat-list
|
||||
{:key-fn identity
|
||||
:render-fn image
|
||||
:render-data {:window-width window-width :selected selected}
|
||||
:data camera-roll-photos
|
||||
:num-columns 3
|
||||
:content-container-style {:width "100%"
|
||||
:padding-bottom (+ (:bottom insets) 100)
|
||||
:padding-top 80}
|
||||
:on-end-reached #(rf/dispatch [:camera-roll/on-end-reached end-cursor
|
||||
selected-album loading?
|
||||
has-next-page?])}]
|
||||
[bottom-gradient selected-images insets selected]]))]))])
|
||||
|
||||
|
||||
|
|
|
@ -9,9 +9,12 @@
|
|||
[status-im2.contexts.quo-preview.main :as quo.preview]
|
||||
[status-im2.contexts.shell.view :as shell]
|
||||
[status-im2.contexts.syncing.view :as settings-syncing]
|
||||
[status-im2.contexts.chat.images-horizontal.view :as images-horizontal]
|
||||
[status-im2.contexts.chat.lightbox.view :as lightbox]
|
||||
[status-im2.config :as config]
|
||||
[quo.design-system.colors :as colors]))
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im2.contexts.chat.photo-selector.album-selector.view :as album-selector]
|
||||
[react-native.platform :as platform]
|
||||
[status-im2.contexts.chat.photo-selector.view :as photo-selector]))
|
||||
|
||||
(def components
|
||||
[])
|
||||
|
@ -32,7 +35,7 @@
|
|||
:options {:topBar {:visible false}}
|
||||
:component chat/chat}
|
||||
|
||||
{:name :images-horizontal
|
||||
{:name :lightbox
|
||||
:insets {:top false :bottom false}
|
||||
:options {:topBar {:visible false}
|
||||
:statusBar {:backgroundColor colors/black-persist
|
||||
|
@ -46,7 +49,15 @@
|
|||
:toId :shared-element
|
||||
:interpolation {:type
|
||||
:decelerate}}]}}}
|
||||
:component images-horizontal/images-horizontal}
|
||||
:component lightbox/lightbox}
|
||||
{:name :photo-selector
|
||||
:options {:topBar {:visible false}}
|
||||
:component photo-selector/photo-selector}
|
||||
|
||||
{:name :album-selector
|
||||
:options {:topBar {:visible false}
|
||||
:modalPresentationStyle (if platform/ios? :overCurrentContext :none)}
|
||||
:component album-selector/album-selector}
|
||||
|
||||
{:name :new-contact
|
||||
:options {:topBar {:visible false}}
|
||||
|
|
|
@ -110,23 +110,24 @@
|
|||
|
||||
(defn albumize-messages
|
||||
[messages]
|
||||
(get (reduce (fn [{:keys [messages albums]} message]
|
||||
(let [album-id (:album-id message)
|
||||
albums (cond-> albums album-id (update album-id conj message))
|
||||
messages (if album-id
|
||||
(conj (filterv #(not= album-id (:album-id %)) messages)
|
||||
{:album (get albums album-id)
|
||||
:album-id album-id
|
||||
:albumize? (:albumize? message)
|
||||
:message-id album-id
|
||||
:content-type constants/content-type-album})
|
||||
(conj messages message))]
|
||||
{:messages messages
|
||||
:albums albums}))
|
||||
{:messages []
|
||||
:albums {}}
|
||||
messages)
|
||||
:messages))
|
||||
(get
|
||||
(reduce (fn [{:keys [messages albums]} message]
|
||||
(let [album-id (:album-id message)
|
||||
albums (cond-> albums album-id (update album-id conj message))
|
||||
messages (if album-id
|
||||
(conj (filterv #(not= album-id (:album-id %)) messages)
|
||||
{:album (get albums album-id)
|
||||
:album-id album-id
|
||||
:albumize? (:albumize? message)
|
||||
:message-id album-id
|
||||
:content-type constants/content-type-album})
|
||||
(conj messages message))]
|
||||
{:messages messages
|
||||
:albums albums}))
|
||||
{:messages []
|
||||
:albums {}}
|
||||
messages)
|
||||
:messages))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/chat-messages
|
||||
|
|
|
@ -109,6 +109,8 @@
|
|||
(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 :camera-roll/albums :camera-roll/albums)
|
||||
(reg-root-key-sub :camera-roll/selected-album :camera-roll/selected-album)
|
||||
(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)
|
||||
|
|
|
@ -1956,5 +1956,8 @@
|
|||
"wants-to-join": "wants to join",
|
||||
"connect-with-users": "Connect with users",
|
||||
"invite-friends-and-family": "Invite your friends and family to Status",
|
||||
"you-have-no-contacts": "You have no contacts"
|
||||
"you-have-no-contacts": "You have no contacts",
|
||||
"my-albums": "My albums",
|
||||
"images": "images",
|
||||
"only-6-images": "You can only add 6 images to your message"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue