Implement collectible image preview (#18449)
* Lightbox refactored and moved to common screens that can be reused * Events renamed * Unify constants namespace importing
This commit is contained in:
parent
ed7463132a
commit
8999b2b9e8
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.animations
|
||||
(ns status-im.common.lightbox.animations
|
||||
(:require
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
|
@ -1,25 +1,25 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.bottom-view
|
||||
(ns status-im.common.lightbox.bottom-view
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as c]
|
||||
[status-im.contexts.chat.messenger.lightbox.style :as style]
|
||||
[status-im.contexts.chat.messenger.lightbox.text-sheet.view :as text-sheet]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.style :as style]
|
||||
[status-im.common.lightbox.text-sheet.view :as text-sheet]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-small-item-layout
|
||||
[_ index]
|
||||
#js
|
||||
{:length c/small-image-size
|
||||
:offset (* (+ c/small-image-size 8) index)
|
||||
{:length constants/small-image-size
|
||||
:offset (* (+ constants/small-image-size 8) index)
|
||||
:index index})
|
||||
|
||||
(defn- f-small-image
|
||||
[item index _ {:keys [scroll-index props]}]
|
||||
(let [size (if (= @scroll-index index) c/focused-image-size c/small-image-size)
|
||||
(let [size (if (= @scroll-index index) constants/focused-image-size constants/small-image-size)
|
||||
size-value (anim/use-val size)
|
||||
{:keys [scroll-index-lock? small-list-ref flat-list-ref]}
|
||||
props]
|
||||
|
@ -27,7 +27,7 @@
|
|||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(rf/dispatch [:chat.ui/zoom-out-signal @scroll-index])
|
||||
(rf/dispatch [:lightbox/zoom-out-signal @scroll-index])
|
||||
(reset! scroll-index-lock? true)
|
||||
(js/setTimeout #(reset! scroll-index-lock? false) 500)
|
||||
(js/setTimeout
|
||||
|
@ -38,9 +38,9 @@
|
|||
(.scrollToIndex ^js @flat-list-ref
|
||||
#js {:animated true :index index}))
|
||||
(if platform/ios? 50 150))
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id (:message-id item)]))}
|
||||
(rf/dispatch [:lightbox/update-animation-shared-element-id (:id item)]))}
|
||||
[reanimated/fast-image
|
||||
{:source {:uri (:image (:content item))}
|
||||
{:source {:uri (:image item)}
|
||||
:style (reanimated/apply-animations-to-style {:width size-value
|
||||
:height size-value}
|
||||
{:border-radius 10})}]]))
|
||||
|
@ -50,20 +50,26 @@
|
|||
[:f> f-small-image item index _ render-data])
|
||||
|
||||
(defn bottom-view
|
||||
[messages index scroll-index insets animations derived item-width props state transparent?]
|
||||
(let [padding-horizontal (- (/ item-width 2) (/ c/focused-image-size 2))]
|
||||
[{:keys [images index scroll-index insets animations derived item-width props state transparent?
|
||||
bottom-text-component]}]
|
||||
(let [padding-horizontal (- (/ item-width 2) (/ constants/focused-image-size 2))]
|
||||
[reanimated/linear-gradient
|
||||
{:colors [colors/neutral-100-opa-100 colors/neutral-100-opa-80 colors/neutral-100-opa-0]
|
||||
:location [0.2 0.9]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container insets animations derived transparent?)}
|
||||
[text-sheet/view messages animations state props]
|
||||
(when bottom-text-component
|
||||
[text-sheet/view
|
||||
{:overlay-opacity (:overlay-opacity animations)
|
||||
:overlay-z-index (:overlay-z-index state)
|
||||
:text-sheet-lock? (:text-sheet-lock? props)
|
||||
:text-component bottom-text-component}])
|
||||
[rn/flat-list
|
||||
{:ref #(reset! (:small-list-ref props) %)
|
||||
:key-fn :message-id
|
||||
:style {:height c/small-list-height}
|
||||
:data messages
|
||||
:key-fn :id
|
||||
:style {:height constants/small-list-height}
|
||||
:data images
|
||||
:render-fn small-image
|
||||
:render-data {:scroll-index scroll-index
|
||||
:props props}
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.constants)
|
||||
(ns status-im.common.lightbox.constants)
|
||||
|
||||
(def ^:const small-image-size 40)
|
||||
(def ^:const focused-extra-size 16)
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.effects
|
||||
(ns status-im.common.lightbox.effects
|
||||
(:require [react-native.blob :as blob]
|
||||
[react-native.cameraroll :as cameraroll]
|
||||
[react-native.fs :as fs]
|
||||
|
@ -10,7 +10,7 @@
|
|||
{:trusty platform/ios?
|
||||
:path (str (fs/cache-dir) "/StatusIm_Image.jpeg")})
|
||||
|
||||
(rf/reg-fx :effects.chat/share-image
|
||||
(rf/reg-fx :effects.lightbox/share-image
|
||||
(fn [uri]
|
||||
(blob/fetch uri
|
||||
config
|
||||
|
@ -20,7 +20,7 @@
|
|||
#(fs/unlink downloaded-url)
|
||||
#(fs/unlink downloaded-url))))))
|
||||
|
||||
(rf/reg-fx :effects.chat/save-image-to-gallery
|
||||
(rf/reg-fx :effects.lightbox/save-image-to-gallery
|
||||
(fn [[uri on-success]]
|
||||
(blob/fetch uri
|
||||
config
|
|
@ -0,0 +1,37 @@
|
|||
(ns status-im.common.lightbox.events
|
||||
(:require [reagent.core :as reagent]
|
||||
status-im.common.lightbox.effects
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :lightbox/navigate-to-lightbox
|
||||
(fn [{:keys [db]} [animation-shared-element-id screen-params]]
|
||||
(reagent/next-tick #(rf/dispatch [:navigate-to :lightbox screen-params]))
|
||||
{:db (assoc db :animation-shared-element-id animation-shared-element-id)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/update-animation-shared-element-id
|
||||
(fn [{:keys [db]} [animation-shared-element-id]]
|
||||
{:db (assoc db :animation-shared-element-id animation-shared-element-id)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/exit-lightbox-signal
|
||||
(fn [{:keys [db]} [value]]
|
||||
{:db (assoc db :lightbox/exit-signal value)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/zoom-out-signal
|
||||
(fn [{:keys [db]} [value]]
|
||||
{:db (assoc db :lightbox/zoom-out-signal value)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/orientation-change
|
||||
(fn [{:keys [db]} [value]]
|
||||
{:db (assoc db :lightbox/orientation value)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/lightbox-scale
|
||||
(fn [{:keys [db]} [value]]
|
||||
{:db (assoc db :lightbox/scale value)}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/share-image
|
||||
(fn [_ [uri]]
|
||||
{:effects.lightbox/share-image uri}))
|
||||
|
||||
(rf/reg-event-fx :lightbox/save-image-to-gallery
|
||||
(fn [_ [uri on-success]]
|
||||
{:effects.lightbox/save-image-to-gallery [uri on-success]}))
|
|
@ -1,9 +1,9 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.style
|
||||
(ns status-im.common.lightbox.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as c]))
|
||||
[status-im.common.lightbox.constants :as constants]))
|
||||
|
||||
;;;; VIEW
|
||||
(defn image
|
||||
|
@ -33,7 +33,7 @@
|
|||
{:position :absolute
|
||||
:padding-horizontal 20
|
||||
:top (if (or platform/ios? (not landscape?)) top-inset 0)
|
||||
:height c/top-view-height
|
||||
:height constants/top-view-height
|
||||
:z-index 4
|
||||
:flex-direction :row
|
||||
:justify-content :space-between
|
||||
|
@ -44,7 +44,7 @@
|
|||
(defn top-gradient
|
||||
[insets]
|
||||
{:position :absolute
|
||||
:height (+ c/top-view-height (:top insets) 0)
|
||||
:height (+ constants/top-view-height (:top insets) 0)
|
||||
:top (- (:top insets))
|
||||
:left 0
|
||||
:right 0})
|
||||
|
@ -71,12 +71,12 @@
|
|||
:display (if @transparent? :none :flex)
|
||||
:bottom 0
|
||||
:padding-bottom (:bottom insets)
|
||||
:padding-top c/text-min-height
|
||||
:padding-top constants/text-min-height
|
||||
:z-index 3}))
|
||||
|
||||
(defn content-container
|
||||
[padding-horizontal]
|
||||
{:padding-vertical c/small-list-padding-vertical
|
||||
{:padding-vertical constants/small-list-padding-vertical
|
||||
:padding-horizontal padding-horizontal
|
||||
:align-items :center
|
||||
:justify-content :center})
|
|
@ -1,8 +1,8 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.text-sheet.style
|
||||
(ns status-im.common.lightbox.text-sheet.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as constants]))
|
||||
[status-im.common.lightbox.constants :as constants]))
|
||||
|
||||
(defn sheet-container
|
||||
[{:keys [height top]}]
|
||||
|
@ -14,10 +14,10 @@
|
|||
:right 0}))
|
||||
|
||||
(defn text-style
|
||||
[expanding-message?]
|
||||
[expandable-text?]
|
||||
{:color colors/white
|
||||
:margin-horizontal 20
|
||||
:align-items (when-not expanding-message? :center)
|
||||
:align-items (when-not expandable-text? :center)
|
||||
:flex-grow 1})
|
||||
|
||||
(def bar-container
|
|
@ -1,10 +1,10 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.text-sheet.utils
|
||||
(ns status-im.common.lightbox.text-sheet.utils
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as r]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as constants]))
|
||||
[status-im.common.lightbox.constants :as constants]))
|
||||
|
||||
(defn- collapse-sheet
|
||||
[{:keys [derived-value overlay-opacity saved-top expanded? overlay-z-index]}]
|
||||
|
@ -16,10 +16,10 @@
|
|||
|
||||
(defn sheet-gesture
|
||||
[{:keys [derived-value saved-top overlay-opacity gradient-opacity]}
|
||||
expanded-height max-height full-height overlay-z-index expanded? dragging? expanding-message?]
|
||||
expanded-height max-height full-height overlay-z-index expanded? dragging? expandable-text?]
|
||||
(let [disable-gesture-update (r/atom false)]
|
||||
(-> (gesture/gesture-pan)
|
||||
(gesture/enabled expanding-message?)
|
||||
(gesture/enabled expandable-text?)
|
||||
(gesture/on-start (fn []
|
||||
(reset! overlay-z-index 1)
|
||||
(reset! dragging? true)
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.text-sheet.view
|
||||
(ns status-im.common.lightbox.text-sheet.view
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
|
@ -8,33 +8,31 @@
|
|||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.lightbox.text-sheet.style :as style]
|
||||
[status-im.contexts.chat.messenger.lightbox.text-sheet.utils :as utils]
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as message-view]))
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.text-sheet.style :as style]
|
||||
[status-im.common.lightbox.text-sheet.utils :as utils]))
|
||||
|
||||
(defn- text-sheet
|
||||
[messages overlay-opacity overlay-z-index text-sheet-lock?]
|
||||
[_]
|
||||
(let [text-height (reagent/atom 0)
|
||||
expanded? (reagent/atom false)
|
||||
dragging? (atom false)]
|
||||
(fn []
|
||||
(let [{:keys [chat-id content]} (first messages)
|
||||
insets (safe-area/get-insets)
|
||||
window-height (:height (rn/get-window))
|
||||
max-height (- window-height
|
||||
constants/text-min-height
|
||||
constants/top-view-height
|
||||
(:bottom insets)
|
||||
(when platform/ios? (:top insets)))
|
||||
full-height (+ constants/bar-container-height
|
||||
constants/text-margin
|
||||
constants/line-height
|
||||
@text-height)
|
||||
expanded-height (min max-height full-height)
|
||||
animations (utils/init-animations overlay-opacity)
|
||||
derived (utils/init-derived-animations animations)
|
||||
expanding-message? (> @text-height (* constants/line-height 2))]
|
||||
(fn [{:keys [overlay-opacity overlay-z-index text-sheet-lock? text-component]}]
|
||||
(let [insets (safe-area/get-insets)
|
||||
window-height (:height (rn/get-window))
|
||||
max-height (- window-height
|
||||
constants/text-min-height
|
||||
constants/top-view-height
|
||||
(:bottom insets)
|
||||
(when platform/ios? (:top insets)))
|
||||
full-height (+ constants/bar-container-height
|
||||
constants/text-margin
|
||||
constants/line-height
|
||||
@text-height)
|
||||
expanded-height (min max-height full-height)
|
||||
animations (utils/init-animations overlay-opacity)
|
||||
derived (utils/init-derived-animations animations)
|
||||
expandable-text? (> @text-height (* constants/line-height 2))]
|
||||
[rn/view
|
||||
[reanimated/linear-gradient
|
||||
{:colors [colors/neutral-100-opa-0 colors/neutral-100]
|
||||
|
@ -51,10 +49,10 @@
|
|||
overlay-z-index
|
||||
expanded?
|
||||
dragging?
|
||||
expanding-message?)}
|
||||
expandable-text?)}
|
||||
[gesture/gesture-detector
|
||||
{:gesture (-> (gesture/gesture-tap)
|
||||
(gesture/enabled (and expanding-message? (not @expanded?)))
|
||||
(gesture/enabled (and expandable-text? (not @expanded?)))
|
||||
(gesture/on-start (fn []
|
||||
(utils/expand-sheet animations
|
||||
expanded-height
|
||||
|
@ -63,7 +61,7 @@
|
|||
expanded?
|
||||
text-sheet-lock?))))}
|
||||
[reanimated/view {:style (style/sheet-container derived)}
|
||||
(when expanding-message?
|
||||
(when expandable-text?
|
||||
[rn/view {:style style/bar-container}
|
||||
[rn/view {:style style/bar}]])
|
||||
[linear-gradient/linear-gradient
|
||||
|
@ -72,19 +70,17 @@
|
|||
:end {:x 0 :y 0}
|
||||
:locations [0.7 0.8 1]
|
||||
:style (style/bottom-gradient (:bottom insets))}]
|
||||
|
||||
[gesture/scroll-view
|
||||
{:scroll-enabled false
|
||||
:scroll-event-throttle 16
|
||||
:bounces false
|
||||
:style {:height (- max-height constants/bar-container-height)}
|
||||
:content-container-style {:padding-top (when (not expanding-message?)
|
||||
:content-container-style {:padding-top (when (not expandable-text?)
|
||||
constants/bar-container-height)}}
|
||||
[message-view/render-parsed-text
|
||||
{:content content
|
||||
:chat-id chat-id
|
||||
:style-override (style/text-style expanding-message?)
|
||||
:on-layout #(utils/on-layout % text-height)}]]]]]]))))
|
||||
[rn/view {:on-layout #(utils/on-layout % text-height)}
|
||||
text-component]]]]]]))))
|
||||
|
||||
(defn view
|
||||
[messages {:keys [overlay-opacity]} {:keys [overlay-z-index]} {:keys [text-sheet-lock?]}]
|
||||
[:f> text-sheet messages overlay-opacity overlay-z-index text-sheet-lock?])
|
||||
[props]
|
||||
[:f> text-sheet props])
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.top-view
|
||||
(ns status-im.common.lightbox.top-view
|
||||
(:require
|
||||
[quo.core :as quo]
|
||||
[quo.foundations.colors :as colors]
|
||||
|
@ -6,10 +6,9 @@
|
|||
[react-native.orientation :as orientation]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as c]
|
||||
[status-im.contexts.chat.messenger.lightbox.style :as style]
|
||||
[utils.datetime :as datetime]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.style :as style]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
@ -17,7 +16,7 @@
|
|||
(defn animate-rotation
|
||||
[result screen-width screen-height insets
|
||||
{:keys [rotate top-view-y top-view-x top-view-width top-view-bg]}]
|
||||
(let [top-x (+ (/ c/top-view-height 2) (:top insets))]
|
||||
(let [top-x (+ (/ constants/top-view-height 2) (:top insets))]
|
||||
(cond
|
||||
(= result orientation/landscape-left)
|
||||
(do
|
||||
|
@ -42,9 +41,9 @@
|
|||
(anim/animate top-view-bg colors/neutral-100-opa-0)))))
|
||||
|
||||
(defn drawer
|
||||
[messages index]
|
||||
(let [{:keys [content]} (nth messages index)
|
||||
uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))]
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
|
||||
[quo/action-drawer
|
||||
[[{:icon :i/save
|
||||
:accessibility-label :save-image
|
||||
|
@ -52,7 +51,7 @@
|
|||
:on-press (fn []
|
||||
(rf/dispatch [:hide-bottom-sheet])
|
||||
(rf/dispatch
|
||||
[:chat.ui/save-image-to-gallery
|
||||
[:lightbox/save-image-to-gallery
|
||||
uri
|
||||
#(rf/dispatch [:toasts/upsert
|
||||
{:id :random-id
|
||||
|
@ -61,20 +60,19 @@
|
|||
:text (i18n/label :t/photo-saved)}])]))}]]]))
|
||||
|
||||
(defn share-image
|
||||
[messages index]
|
||||
(let [{:keys [content]} (nth messages index)
|
||||
uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))]
|
||||
(rf/dispatch [:chat.ui/share-image uri])))
|
||||
[images index]
|
||||
(let [{:keys [image]} (nth images index)
|
||||
uri (url/replace-port image (rf/sub [:mediaserver/port]))]
|
||||
(rf/dispatch [:lightbox/share-image uri])))
|
||||
|
||||
(defn top-view
|
||||
[messages insets index animations derived landscape? screen-width]
|
||||
(let [{:keys [from timestamp]} (first messages)
|
||||
[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])
|
||||
bg-color (if landscape?
|
||||
colors/neutral-100-opa-70
|
||||
colors/neutral-100-opa-0)
|
||||
[images insets index animations derived landscape? screen-width]
|
||||
(let [{:keys [description header]} (nth images @index)
|
||||
bg-color (if landscape?
|
||||
colors/neutral-100-opa-70
|
||||
colors/neutral-100-opa-0)
|
||||
{:keys [background-color opacity
|
||||
overlay-opacity]} animations]
|
||||
overlay-opacity]} animations]
|
||||
[reanimated/view
|
||||
{:style
|
||||
(style/top-view-container (:top insets) screen-width bg-color landscape? animations derived)}
|
||||
|
@ -92,7 +90,7 @@
|
|||
(anim/animate opacity 0)
|
||||
(anim/animate overlay-opacity 0)
|
||||
(rf/dispatch (if platform/ios?
|
||||
[:chat.ui/exit-lightbox-signal @index]
|
||||
[:lightbox/exit-lightbox-signal @index]
|
||||
[:navigate-back])))
|
||||
:style style/close-container}
|
||||
[quo/icon :close {:size 20 :color colors/white}]]
|
||||
|
@ -100,22 +98,22 @@
|
|||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-1
|
||||
:style {:color colors/white}} primary-name]
|
||||
:style {:color colors/white}} header]
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2
|
||||
:style {:color colors/neutral-40}} (when timestamp (datetime/to-short-str timestamp))]]]
|
||||
:style {:color colors/neutral-40}} description]]]
|
||||
[rn/view {:style style/top-right-buttons}
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:accessibility-label :share-image
|
||||
:on-press #(share-image messages @index)
|
||||
:on-press #(share-image images @index)
|
||||
:style (merge style/close-container {:margin-right 12})}
|
||||
[quo/icon :share {:size 20 :color colors/white}]]
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:accessibility-label :image-options
|
||||
:on-press #(rf/dispatch [:show-bottom-sheet
|
||||
{:content (fn [] [drawer messages @index])}])
|
||||
{:content (fn [] [drawer images @index])}])
|
||||
:style style/close-container}
|
||||
[quo/icon :options {:size 20 :color colors/white}]]]]))
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.utils
|
||||
(ns status-im.common.lightbox.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
|
@ -9,9 +9,9 @@
|
|||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.lightbox.top-view :as top-view]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.top-view :as top-view]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.worklets.chat.messenger.lightbox :as worklet]))
|
||||
|
||||
|
@ -46,7 +46,7 @@
|
|||
(if platform/ios? 250 100)))
|
||||
(swap! timers assoc :mount-index-lock (js/setTimeout #(reset! scroll-index-lock? false) 300))
|
||||
(fn []
|
||||
(rf/dispatch [:chat.ui/zoom-out-signal nil])
|
||||
(rf/dispatch [:lightbox/zoom-out-signal nil])
|
||||
(when platform/android?
|
||||
(rf/dispatch [:chat.ui/lightbox-scale 1]))
|
||||
(clear-timers timers)))))
|
||||
|
@ -69,7 +69,7 @@
|
|||
landscape? (string/includes? result orientation/landscape)
|
||||
item-width (if (and landscape? platform/ios?) screen-height screen-width)]
|
||||
(when (or landscape? (= result orientation/portrait))
|
||||
(rf/dispatch [:chat.ui/orientation-change result]))
|
||||
(rf/dispatch [:lightbox/orientation-change result]))
|
||||
(cond
|
||||
landscape?
|
||||
(orientation/lock-to-landscape "lightbox")
|
||||
|
@ -148,11 +148,11 @@
|
|||
:timers (atom {})})
|
||||
|
||||
(defn init-state
|
||||
[messages index]
|
||||
[images index]
|
||||
;; The initial value of data is the image that was pressed (and not the whole album) in order
|
||||
;; for the transition animation to execute properly, otherwise it would animate towards
|
||||
;; outside the screen (even if we have `initialScrollIndex` set).
|
||||
{:data (reagent/atom (if (number? index) [(nth messages index)] []))
|
||||
{:data (reagent/atom (if (number? index) [(nth images index)] []))
|
||||
:scroll-index (reagent/atom index)
|
||||
:transparent? (reagent/atom false)
|
||||
:set-full-height? (reagent/atom false)
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.view
|
||||
(ns status-im.common.lightbox.view
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[oops.core :as oops]
|
||||
|
@ -9,13 +9,13 @@
|
|||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.bottom-view :as bottom-view]
|
||||
[status-im.contexts.chat.messenger.lightbox.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.lightbox.style :as style]
|
||||
[status-im.contexts.chat.messenger.lightbox.top-view :as top-view]
|
||||
[status-im.contexts.chat.messenger.lightbox.utils :as utils]
|
||||
[status-im.contexts.chat.messenger.lightbox.zoomable-image.view :as zoomable-image]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.bottom-view :as bottom-view]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.common.lightbox.style :as style]
|
||||
[status-im.common.lightbox.top-view :as top-view]
|
||||
[status-im.common.lightbox.utils :as utils]
|
||||
[status-im.common.lightbox.zoomable-image.view :as zoomable-image]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn get-item-layout
|
||||
|
@ -33,9 +33,10 @@
|
|||
(reset! scroll-index index)
|
||||
(when @small-list-ref
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated true :index index}))
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id (:message-id (oops/oget changed :item))]))))
|
||||
(rf/dispatch [:lightbox/update-animation-shared-element-id
|
||||
(:id (oops/oget changed :item))]))))
|
||||
|
||||
(defn image
|
||||
(defn image-view
|
||||
[message index _ {:keys [screen-width screen-height] :as args}]
|
||||
[rn/view
|
||||
{:style (style/image (+ screen-width constants/separator-width) screen-height)}
|
||||
|
@ -43,30 +44,31 @@
|
|||
[rn/view {:style {:width constants/separator-width}}]])
|
||||
|
||||
(defn lightbox-content
|
||||
[props {:keys [data transparent? scroll-index set-full-height?] :as state}
|
||||
animations derived messages index handle-items-changed]
|
||||
(let [insets (safe-area/get-insets)
|
||||
window (rn/get-window)
|
||||
window-width (:width window)
|
||||
window-height (if platform/android?
|
||||
(+ (:height window) (:top insets))
|
||||
(:height window))
|
||||
curr-orientation (or (rf/sub [:lightbox/orientation]) orientation/portrait)
|
||||
landscape? (string/includes? curr-orientation orientation/landscape)
|
||||
horizontal? (or platform/android? (not landscape?))
|
||||
inverted? (and platform/ios? (= curr-orientation orientation/landscape-right))
|
||||
screen-width (if (or platform/ios? (= curr-orientation orientation/portrait))
|
||||
window-width
|
||||
window-height)
|
||||
screen-height (if (or platform/ios? (= curr-orientation orientation/portrait))
|
||||
window-height
|
||||
window-width)
|
||||
item-width (if (and landscape? platform/ios?) screen-height screen-width)]
|
||||
[{:keys [props state animations derived images index handle-items-changed bottom-text-component]}]
|
||||
(let [{:keys [data transparent? scroll-index
|
||||
set-full-height?]} state
|
||||
insets (safe-area/get-insets)
|
||||
window (rn/get-window)
|
||||
window-width (:width window)
|
||||
window-height (if platform/android?
|
||||
(+ (:height window) (:top insets))
|
||||
(:height window))
|
||||
curr-orientation (or (rf/sub [:lightbox/orientation]) orientation/portrait)
|
||||
landscape? (string/includes? curr-orientation orientation/landscape)
|
||||
horizontal? (or platform/android? (not landscape?))
|
||||
inverted? (and platform/ios? (= curr-orientation orientation/landscape-right))
|
||||
screen-width (if (or platform/ios? (= curr-orientation orientation/portrait))
|
||||
window-width
|
||||
window-height)
|
||||
screen-height (if (or platform/ios? (= curr-orientation orientation/portrait))
|
||||
window-height
|
||||
window-width)
|
||||
item-width (if (and landscape? platform/ios?) screen-height screen-width)]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style {:background-color (:background-color animations)}
|
||||
{:height screen-height})}
|
||||
(when-not @transparent?
|
||||
[:f> top-view/top-view messages insets scroll-index animations derived landscape?
|
||||
[:f> top-view/top-view images insets scroll-index animations derived landscape?
|
||||
screen-width])
|
||||
[gesture/gesture-detector
|
||||
{:gesture (utils/drag-gesture animations (and landscape? platform/ios?) set-full-height?)}
|
||||
|
@ -92,7 +94,7 @@
|
|||
:scroll-event-throttle 8
|
||||
:style {:width (+ screen-width constants/separator-width)}
|
||||
:data @data
|
||||
:render-fn image
|
||||
:render-fn image-view
|
||||
:render-data {:opacity-value (:opacity animations)
|
||||
:overlay-opacity (:overlay-opacity animations)
|
||||
:border-value (:border animations)
|
||||
|
@ -118,26 +120,47 @@
|
|||
;; NOTE: not un-mounting bottom-view based on `transparent?` (like we do with the top-view
|
||||
;; above), since we need to save the state of the text-sheet position. Instead, we use
|
||||
;; the `:display` style property to hide the bottom-sheet.
|
||||
(when (not landscape?)
|
||||
[:f> bottom-view/bottom-view messages index scroll-index insets animations derived
|
||||
item-width props state transparent?])]))
|
||||
(when (and (not landscape?) (or bottom-text-component (> (count images) 1)))
|
||||
[:f> bottom-view/bottom-view
|
||||
{:images images
|
||||
:index index
|
||||
:scroll-index scroll-index
|
||||
:insets insets
|
||||
:animations animations
|
||||
:derived derived
|
||||
:item-width item-width
|
||||
:props props
|
||||
:state state
|
||||
:transparent? transparent?
|
||||
:bottom-text-component bottom-text-component}])]))
|
||||
|
||||
(defn- f-lightbox
|
||||
[]
|
||||
(let [{:keys [messages index]} (rf/sub [:get-screen-params])
|
||||
props (utils/init-props)
|
||||
state (utils/init-state messages index)
|
||||
handle-items-changed (fn [e]
|
||||
(on-viewable-items-changed e props state))]
|
||||
(let [{:keys [images index bottom-text-component]} (rf/sub [:get-screen-params])
|
||||
props
|
||||
(utils/init-props)
|
||||
state
|
||||
(utils/init-state images index)
|
||||
handle-items-changed
|
||||
(fn [e]
|
||||
(on-viewable-items-changed e props state))]
|
||||
(fn []
|
||||
(let [animations (utils/init-animations (count messages) index)
|
||||
(let [animations (utils/init-animations (count images) index)
|
||||
derived (utils/init-derived-animations animations)]
|
||||
(anim/animate (:background-color animations) colors/neutral-100)
|
||||
(reset! (:data state) messages)
|
||||
(reset! (:data state) images)
|
||||
(when platform/ios? ; issue: https://github.com/wix/react-native-navigation/issues/7726
|
||||
(utils/orientation-change props state animations))
|
||||
(utils/effect props animations index)
|
||||
[:f> lightbox-content props state animations derived messages index handle-items-changed]))))
|
||||
[:f> lightbox-content
|
||||
{:props props
|
||||
:state state
|
||||
:animations animations
|
||||
:derived derived
|
||||
:images images
|
||||
:index index
|
||||
:handle-items-changed handle-items-changed
|
||||
:bottom-text-component bottom-text-component}]))))
|
||||
|
||||
(defn lightbox
|
||||
[]
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.zoomable-image.constants)
|
||||
(ns status-im.common.lightbox.zoomable-image.constants)
|
||||
|
||||
(def ^:const min-scale 1)
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.zoomable-image.style
|
||||
(ns status-im.common.lightbox.zoomable-image.style
|
||||
(:require
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]))
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.zoomable-image.utils
|
||||
(ns status-im.common.lightbox.zoomable-image.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
|
@ -6,8 +6,8 @@
|
|||
[react-native.orientation :as orientation]
|
||||
[react-native.platform :as platform]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.zoomable-image.constants :as constants]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.zoomable-image.constants :as constants]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
;;; Helpers
|
||||
|
@ -97,7 +97,7 @@
|
|||
(rescale constants/min-scale true)
|
||||
(js/setTimeout #(rf/dispatch [:navigate-back]) 70))
|
||||
(rf/dispatch [:navigate-back]))
|
||||
(js/setTimeout #(rf/dispatch [:chat.ui/exit-lightbox-signal nil]) 500)))
|
||||
(js/setTimeout #(rf/dispatch [:lightbox/exit-lightbox-signal nil]) 500)))
|
||||
|
||||
(defn handle-zoom-out-signal
|
||||
"Zooms out when pressing on another photo from the small bottom list"
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.zoomable-image.view
|
||||
(ns status-im.common.lightbox.zoomable-image.view
|
||||
(:require
|
||||
[oops.core :refer [oget]]
|
||||
[react-native.core :as rn]
|
||||
|
@ -7,10 +7,10 @@
|
|||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as r]
|
||||
[status-im.contexts.chat.messenger.lightbox.animations :as anim]
|
||||
[status-im.contexts.chat.messenger.lightbox.zoomable-image.constants :as c]
|
||||
[status-im.contexts.chat.messenger.lightbox.zoomable-image.style :as style]
|
||||
[status-im.contexts.chat.messenger.lightbox.zoomable-image.utils :as utils]
|
||||
[status-im.common.lightbox.animations :as anim]
|
||||
[status-im.common.lightbox.zoomable-image.constants :as c]
|
||||
[status-im.common.lightbox.zoomable-image.style :as style]
|
||||
[status-im.common.lightbox.zoomable-image.utils :as utils]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
||||
|
@ -206,7 +206,7 @@
|
|||
(anim/animate-decay pan-y-start velocity [lower-bound upper-bound]))))))))
|
||||
|
||||
(defn- f-zoomable-image
|
||||
[dimensions animations state rescale curr-orientation content focused? index render-data
|
||||
[dimensions animations state rescale curr-orientation image focused? index render-data
|
||||
image-dimensions-nil?]
|
||||
(let [{:keys [transparent? set-full-height?]} render-data
|
||||
portrait? (= curr-orientation orientation/portrait)
|
||||
|
@ -229,7 +229,7 @@
|
|||
(= curr-orientation orientation/portrait))}
|
||||
[reanimated/fast-image
|
||||
(merge
|
||||
{:source {:uri (url/replace-port (:image content) (rf/sub [:mediaserver/port]))}
|
||||
{:source {:uri (url/replace-port image (rf/sub [:mediaserver/port]))}
|
||||
:native-ID (when focused? :shared-element)
|
||||
:style (style/image dimensions animations render-data index)}
|
||||
(when image-dimensions-nil?
|
||||
|
@ -238,12 +238,12 @@
|
|||
(defn zoomable-image
|
||||
[]
|
||||
(let [state (utils/init-state)]
|
||||
(fn [{:keys [image-width image-height content message-id]} index render-data]
|
||||
(let [shared-element-id (rf/sub [:shared-element-id])
|
||||
(fn [{:keys [image-width image-height image id]} index render-data]
|
||||
(let [animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||
exit-lightbox-signal (rf/sub [:lightbox/exit-signal])
|
||||
zoom-out-signal (rf/sub [:lightbox/zoom-out-signal])
|
||||
{:keys [set-full-height? curr-orientation]} render-data
|
||||
focused? (= shared-element-id message-id)
|
||||
focused? (= animation-shared-element-id id)
|
||||
;; TODO - remove `image-dimensions` check, once
|
||||
;; https://github.com/status-im/status-desktop/issues/10944 is fixed
|
||||
image-dimensions-nil? (not (and image-width image-height))
|
||||
|
@ -269,5 +269,5 @@
|
|||
rescale
|
||||
set-full-height?))
|
||||
(utils/handle-zoom-out-signal zoom-out-signal index (anim/get-val (:scale animations)) rescale)
|
||||
[:f> f-zoomable-image dimensions animations state rescale curr-orientation content focused?
|
||||
[:f> f-zoomable-image dimensions animations state rescale curr-orientation image focused?
|
||||
index render-data image-dimensions-nil?]))))
|
|
@ -4,13 +4,12 @@
|
|||
[legacy.status-im.chat.models.loading :as loading]
|
||||
[legacy.status-im.data-store.chats :as chats-store]
|
||||
[re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
status-im.common.lightbox.events
|
||||
[status-im.common.muting.helpers :refer [format-mute-till]]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.contacts.events :as contacts-store]
|
||||
status-im.contexts.chat.effects
|
||||
[status-im.contexts.chat.messenger.composer.link-preview.events :as link-preview]
|
||||
status-im.contexts.chat.messenger.lightbox.events
|
||||
status-im.contexts.chat.messenger.messages.content.reactions.events
|
||||
[status-im.contexts.chat.messenger.messages.delete-message-for-me.events :as delete-for-me]
|
||||
[status-im.contexts.chat.messenger.messages.delete-message.events :as delete-message]
|
||||
|
@ -394,38 +393,6 @@
|
|||
[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]}
|
||||
[{:keys [db]} shared-element-id]
|
||||
{:db (assoc db :shared-element-id shared-element-id)})
|
||||
|
||||
(rf/defn navigate-to-lightbox
|
||||
{:events [:chat.ui/navigate-to-lightbox]}
|
||||
[{:keys [db]} shared-element-id screen-params]
|
||||
(reagent/next-tick #(rf/dispatch [:navigate-to :lightbox screen-params]))
|
||||
{:db (assoc db :shared-element-id shared-element-id)})
|
||||
|
||||
(rf/defn exit-lightbox-signal
|
||||
{:events [:chat.ui/exit-lightbox-signal]}
|
||||
[{:keys [db]} value]
|
||||
{:db (assoc db :lightbox/exit-signal value)})
|
||||
|
||||
(rf/defn zoom-out-signal
|
||||
{:events [:chat.ui/zoom-out-signal]}
|
||||
[{:keys [db]} value]
|
||||
{:db (assoc db :lightbox/zoom-out-signal value)})
|
||||
|
||||
(rf/defn orientation-change
|
||||
{:events [:chat.ui/orientation-change]}
|
||||
[{:keys [db]} value]
|
||||
{:db (assoc db :lightbox/orientation value)})
|
||||
|
||||
(rf/defn lightbox-scale
|
||||
{:events [:chat.ui/lightbox-scale]}
|
||||
[{:keys [db]} value]
|
||||
{:db (assoc db :lightbox/scale value)})
|
||||
|
||||
(rf/defn check-last-chat
|
||||
{:events [:chat/check-last-chat]}
|
||||
[{:keys [db]}]
|
||||
|
@ -452,3 +419,15 @@
|
|||
{:events [:chat.ui/scroll-to-bottom]}
|
||||
[_]
|
||||
{:effects.chat/scroll-to-bottom nil})
|
||||
|
||||
(rf/reg-event-fx :chat.ui/clear-sending-images
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:chat/inputs (:current-chat-id db) :metadata] assoc :sending-image {})}))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/image-unselected
|
||||
(fn [{:keys [db]} [original]]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
{:db (update-in db
|
||||
[:chat/inputs current-chat-id :metadata :sending-image]
|
||||
dissoc
|
||||
(:uri original))})))
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
(ns status-im.contexts.chat.messenger.lightbox.events
|
||||
(:require status-im.contexts.chat.messenger.lightbox.effects
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/clear-sending-images
|
||||
(fn [{:keys [db]}]
|
||||
{:db (update-in db [:chat/inputs (:current-chat-id db) :metadata] assoc :sending-image {})}))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/image-unselected
|
||||
(fn [{:keys [db]} [original]]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
{:db (update-in db
|
||||
[:chat/inputs current-chat-id :metadata :sending-image]
|
||||
dissoc
|
||||
(:uri original))})))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/share-image
|
||||
(fn [_ [uri]]
|
||||
{:effects.chat/share-image uri}))
|
||||
|
||||
(rf/reg-event-fx :chat.ui/save-image-to-gallery
|
||||
(fn [_ [uri on-success]]
|
||||
{:effects.chat/save-image-to-gallery [uri on-success]}))
|
|
@ -7,6 +7,8 @@
|
|||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.content.album.style :as style]
|
||||
[status-im.contexts.chat.messenger.messages.content.image.view :as image]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.utils :as lightbox-utils]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.view :as lightbox]
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as text]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
@ -21,17 +23,19 @@
|
|||
|
||||
(defn album-message
|
||||
[{:keys [albumize?] :as message} context on-long-press message-container-data]
|
||||
(let [shared-element-id (rf/sub [:shared-element-id])
|
||||
media-server-port (rf/sub [:mediaserver/port])
|
||||
first-image (first (:album message))
|
||||
album-style (if (> (:image-width first-image) (:image-height first-image))
|
||||
:landscape
|
||||
:portrait)
|
||||
images-count (count (:album message))
|
||||
(let [animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||
media-server-port (rf/sub [:mediaserver/port])
|
||||
album-messages (:album message)
|
||||
first-image (first album-messages)
|
||||
album-style (if (> (:image-width first-image) (:image-height first-image))
|
||||
:landscape
|
||||
:portrait)
|
||||
images-count (count album-messages)
|
||||
;; album images are always square, except when we have 3 images, then they must be
|
||||
;; rectangular
|
||||
;; (portrait or landscape)
|
||||
portrait? (and (= images-count rectangular-style-count) (= album-style :portrait))]
|
||||
portrait? (and (= images-count rectangular-style-count)
|
||||
(= album-style :portrait))]
|
||||
(if (and albumize? (> images-count 1))
|
||||
[:<>
|
||||
[rn/view {:style {:margin-bottom 4}} [text/text-content first-image]]
|
||||
|
@ -52,14 +56,21 @@
|
|||
{:key (:message-id item)
|
||||
:active-opacity 1
|
||||
:on-long-press #(on-long-press message context)
|
||||
:on-press #(rf/dispatch [:chat.ui/navigate-to-lightbox
|
||||
(:message-id item)
|
||||
{:messages (:album message)
|
||||
:index index}])}
|
||||
:on-press #(rf/dispatch
|
||||
[:lightbox/navigate-to-lightbox
|
||||
(:message-id item)
|
||||
{:index index
|
||||
:images (into []
|
||||
(map
|
||||
lightbox-utils/convert-message-to-lightbox-image
|
||||
album-messages))
|
||||
:bottom-text-component
|
||||
[lightbox/bottom-text-for-lightbox
|
||||
first-image]}])}
|
||||
[fast-image/fast-image
|
||||
{:style (style/image dimensions index portrait? images-count)
|
||||
:source {:uri (url/replace-port (:image (:content item)) media-server-port)}
|
||||
:native-ID (when (and (= shared-element-id (:message-id item))
|
||||
:native-ID (when (and (= animation-shared-element-id (:message-id item))
|
||||
(< index constants/max-album-photos))
|
||||
:shared-element)}]
|
||||
(when (and (> images-count constants/max-album-photos)
|
||||
|
@ -71,11 +82,11 @@
|
|||
:size :heading-2
|
||||
:style {:color colors/white}}
|
||||
(str "+" (- images-count (dec constants/max-album-photos)))]])]))
|
||||
(:album message))]]
|
||||
album-messages)]]
|
||||
[:<>
|
||||
(map-indexed
|
||||
(fn [index item]
|
||||
[:<> {:key (:message-id item)}
|
||||
[image/image-message index item {:on-long-press #(on-long-press message context)}
|
||||
message-container-data]])
|
||||
(:album message))])))
|
||||
album-messages)])))
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
[react-native.fast-image :as fast-image]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.utils :as lightbox-utils]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.view :as lightbox]
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as text]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.url :as url]))
|
||||
|
@ -39,7 +41,7 @@
|
|||
image-height
|
||||
max-container-width
|
||||
max-container-height)
|
||||
shared-element-id (rf/sub [:shared-element-id])
|
||||
animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||
image-local-url (url/replace-port (:image content) (rf/sub [:mediaserver/port]))]
|
||||
[:<>
|
||||
(when (= index 0)
|
||||
|
@ -48,13 +50,16 @@
|
|||
{:active-opacity 1
|
||||
:style {:margin-top 4}
|
||||
:on-long-press on-long-press
|
||||
:on-press #(rf/dispatch [:chat.ui/navigate-to-lightbox
|
||||
:on-press #(rf/dispatch [:lightbox/navigate-to-lightbox
|
||||
message-id
|
||||
{:messages [message]
|
||||
:index 0
|
||||
:insets insets}])}
|
||||
{:images [(lightbox-utils/convert-message-to-lightbox-image
|
||||
message)]
|
||||
:index 0
|
||||
:insets insets
|
||||
:bottom-text-component
|
||||
[lightbox/bottom-text-for-lightbox message]}])}
|
||||
[fast-image/fast-image
|
||||
{:source {:uri image-local-url}
|
||||
:style (merge dimensions {:border-radius 12})
|
||||
:native-ID (when (= shared-element-id message-id) :shared-element)
|
||||
:native-ID (when (= animation-shared-element-id message-id) :shared-element)
|
||||
:accessibility-label :image-message}]]]))
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
(ns status-im.contexts.chat.messenger.messages.content.lightbox.style
|
||||
(:require
|
||||
[quo.foundations.colors :as colors]))
|
||||
|
||||
(defn bottom-text
|
||||
[expandable-text?]
|
||||
{:color colors/white
|
||||
:margin-horizontal 20
|
||||
:align-items (when-not expandable-text? :center)
|
||||
:flex-grow 1})
|
|
@ -0,0 +1,14 @@
|
|||
(ns status-im.contexts.chat.messenger.messages.content.lightbox.utils
|
||||
(:require
|
||||
[utils.datetime :as datetime]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn convert-message-to-lightbox-image
|
||||
[{:keys [timestamp image-width image-height message-id from content]}]
|
||||
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])]
|
||||
{:image (:image content)
|
||||
:image-width image-width
|
||||
:image-height image-height
|
||||
:id message-id
|
||||
:header primary-name
|
||||
:description (when timestamp (datetime/to-short-str timestamp))}))
|
|
@ -0,0 +1,18 @@
|
|||
(ns status-im.contexts.chat.messenger.messages.content.lightbox.view
|
||||
(:require
|
||||
[oops.core :as oops]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.common.lightbox.constants :as constants]
|
||||
[status-im.contexts.chat.messenger.messages.content.lightbox.style :as style]
|
||||
[status-im.contexts.chat.messenger.messages.content.text.view :as message-view]))
|
||||
|
||||
(defn bottom-text-for-lightbox
|
||||
[_]
|
||||
(let [text-height (reagent/atom 0)]
|
||||
(fn [{:keys [content chat-id] :as _message}]
|
||||
(let [expandable-text? (> @text-height (* constants/line-height 2))]
|
||||
[message-view/render-parsed-text
|
||||
{:content content
|
||||
:chat-id chat-id
|
||||
:style-override (style/bottom-text expandable-text?)
|
||||
:on-layout #(reset! text-height (oops/oget % "nativeEvent.layout.height"))}]))))
|
|
@ -75,12 +75,14 @@
|
|||
(let [selected-tab (reagent/atom :overview)
|
||||
on-tab-change #(reset! selected-tab %)]
|
||||
(fn []
|
||||
(let [collectible (rf/sub [:wallet/last-collectible-details])
|
||||
(let [collectible (rf/sub [:wallet/last-collectible-details])
|
||||
animation-shared-element-id (rf/sub [:animation-shared-element-id])
|
||||
{:keys [collectible-data preview-url
|
||||
collection-data]} collectible
|
||||
collection-data id]} collectible
|
||||
token-id (:token-id id)
|
||||
{collection-image :image-url
|
||||
collection-name :name} collection-data
|
||||
{collectible-name :name} collectible-data]
|
||||
collection-name :name} collection-data
|
||||
{collectible-name :name} collectible-data]
|
||||
[scroll-page/scroll-page
|
||||
{:navigate-back? true
|
||||
:height 148
|
||||
|
@ -95,9 +97,26 @@
|
|||
:picture preview-url}}
|
||||
[rn/view {:style style/container}
|
||||
[rn/view {:style style/preview-container}
|
||||
[rn/image
|
||||
{:source preview-url
|
||||
:style style/preview}]]
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press #(rf/dispatch [:lightbox/navigate-to-lightbox
|
||||
token-id
|
||||
{:images [{:image preview-url
|
||||
:image-width 300 ; collectibles don't have
|
||||
; width/height but we need
|
||||
; to pass something
|
||||
:image-height 300 ; without it animation
|
||||
; doesn't work smoothly and
|
||||
; :border-radius not
|
||||
; applied
|
||||
:id token-id
|
||||
:header collectible-name
|
||||
:description collection-name}]
|
||||
:index 0}])}
|
||||
[rn/image
|
||||
{:source preview-url
|
||||
:style style/preview
|
||||
:native-ID (when (= animation-shared-element-id token-id) :shared-element)}]]]
|
||||
[header collectible-name collection-name collection-image]
|
||||
[cta-buttons]
|
||||
[quo/tabs
|
||||
|
|
|
@ -2,13 +2,13 @@
|
|||
(:require
|
||||
[legacy.status-im.ui.screens.screens :as old-screens]
|
||||
[status-im.common.emoji-picker.view :as emoji-picker]
|
||||
[status-im.common.lightbox.view :as lightbox]
|
||||
[status-im.config :as config]
|
||||
[status-im.contexts.chat.group-details.view :as group-details]
|
||||
[status-im.contexts.chat.home.add-new-contact.scan.scan-profile-qr-page :as scan-profile-qr-page]
|
||||
[status-im.contexts.chat.home.add-new-contact.views :as add-new-contact]
|
||||
[status-im.contexts.chat.home.new-chat.view :as new-chat]
|
||||
[status-im.contexts.chat.messenger.camera.view :as camera-screen]
|
||||
[status-im.contexts.chat.messenger.lightbox.view :as lightbox]
|
||||
[status-im.contexts.chat.messenger.messages.view :as chat]
|
||||
[status-im.contexts.chat.messenger.photo-selector.view :as photo-selector]
|
||||
[status-im.contexts.communities.actions.accounts-selection.view :as communities.accounts-selection]
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
;;view
|
||||
(reg-root-key-sub :view-id :view-id)
|
||||
(reg-root-key-sub :screen-params :navigation/screen-params)
|
||||
(reg-root-key-sub :shared-element-id :shared-element-id)
|
||||
(reg-root-key-sub :animation-shared-element-id :animation-shared-element-id)
|
||||
|
||||
;;bottom sheet
|
||||
(reg-root-key-sub :bottom-sheet :bottom-sheet)
|
||||
|
|
Loading…
Reference in New Issue