parent
e8b956d4f4
commit
2b701f9af0
|
@ -4,10 +4,8 @@
|
|||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.navigation :as navigation]
|
||||
[react-native.orientation :as orientation]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.lightbox.animations :as anim]
|
||||
|
@ -83,27 +81,6 @@
|
|||
(when (and enabled? (not= result orientation/landscape-right))
|
||||
(handle-orientation result props state animations))))))))
|
||||
|
||||
(defn toggle-opacity
|
||||
[index {:keys [opacity-value border-value transparent? props]} portrait?]
|
||||
(let [{:keys [small-list-ref]} props
|
||||
opacity (reanimated/get-shared-value opacity-value)]
|
||||
(if (= opacity 1)
|
||||
(do
|
||||
(when platform/ios?
|
||||
;; status-bar issue: https://github.com/status-im/status-mobile/issues/15343
|
||||
(js/setTimeout #(navigation/merge-options "lightbox" {:statusBar {:visible false}}) 75))
|
||||
(anim/animate opacity-value 0)
|
||||
(js/setTimeout #(reset! transparent? (not @transparent?)) 400))
|
||||
(do
|
||||
(reset! transparent? (not @transparent?))
|
||||
(js/setTimeout #(anim/animate opacity-value 1) 50)
|
||||
(js/setTimeout #(when @small-list-ref
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated false :index index}))
|
||||
100)
|
||||
(when (and platform/ios? portrait?)
|
||||
(js/setTimeout #(navigation/merge-options "lightbox" {:statusBar {:visible true}}) 150))))
|
||||
(anim/animate border-value (if (= opacity 1) 0 12))))
|
||||
|
||||
(defn drag-gesture
|
||||
[{:keys [pan-x pan-y background-color opacity layout]} x? set-full-height?]
|
||||
(->
|
||||
|
|
|
@ -38,8 +38,7 @@
|
|||
[message index _ {:keys [screen-width screen-height] :as args}]
|
||||
[rn/view
|
||||
{:style (style/image (+ screen-width constants/separator-width) screen-height)}
|
||||
[zoomable-image/zoomable-image message index args
|
||||
#(utils/toggle-opacity index args %)]
|
||||
[:f> zoomable-image/zoomable-image message index args]
|
||||
[rn/view {:style {:width constants/separator-width}}]])
|
||||
|
||||
(defn lightbox-content
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
(ns status-im2.contexts.chat.lightbox.zoomable-image.utils
|
||||
(:require
|
||||
[clojure.string :as string]
|
||||
[react-native.navigation :as navigation]
|
||||
[react-native.orientation :as orientation]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.lightbox.zoomable-image.constants :as c]
|
||||
[status-im2.contexts.chat.lightbox.animations :as anim]
|
||||
[utils.re-frame :as rf]))
|
||||
|
@ -36,9 +39,9 @@
|
|||
exit?
|
||||
{:keys [x-threshold-scale y-threshold-scale]}
|
||||
{:keys [scale saved-scale] :as animations}
|
||||
{:keys [pan-x-enabled? pan-y-enabled?] :as props}]
|
||||
{:keys [pan-x-enabled? pan-y-enabled?] :as state}]
|
||||
(when (= value c/min-scale)
|
||||
(reset-values exit? animations props))
|
||||
(reset-values exit? animations state))
|
||||
(anim/animate scale value (if exit? 100 c/default-duration))
|
||||
(anim/set-val saved-scale value)
|
||||
(reset! pan-x-enabled? (> value x-threshold-scale))
|
||||
|
@ -102,6 +105,27 @@
|
|||
(when (and (= zoom-out-signal index) (> scale c/min-scale))
|
||||
(rescale c/min-scale true)))
|
||||
|
||||
(defn toggle-opacity
|
||||
[index {:keys [opacity-value border-value transparent? props]} portrait?]
|
||||
(let [{:keys [small-list-ref]} props
|
||||
opacity (reanimated/get-shared-value opacity-value)]
|
||||
(if (= opacity 1)
|
||||
(do
|
||||
(when platform/ios?
|
||||
;; status-bar issue: https://github.com/status-im/status-mobile/issues/15343
|
||||
(js/setTimeout #(navigation/merge-options "lightbox" {:statusBar {:visible false}}) 75))
|
||||
(anim/animate opacity-value 0)
|
||||
(js/setTimeout #(reset! transparent? (not @transparent?)) 400))
|
||||
(do
|
||||
(reset! transparent? (not @transparent?))
|
||||
(js/setTimeout #(anim/animate opacity-value 1) 50)
|
||||
(js/setTimeout #(when @small-list-ref
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated false :index index}))
|
||||
100)
|
||||
(when (and platform/ios? portrait?)
|
||||
(js/setTimeout #(navigation/merge-options "lightbox" {:statusBar {:visible true}}) 150))))
|
||||
(anim/animate border-value (if (= opacity 1) 0 12))))
|
||||
|
||||
;;; Dimensions
|
||||
(defn get-dimensions
|
||||
"Calculates all required dimensions. Dimensions calculations are different on iOS and Android because landscape
|
||||
|
@ -162,3 +186,28 @@
|
|||
(if (or (> focal max) (< focal min))
|
||||
(/ screen-size 2)
|
||||
focal)))
|
||||
|
||||
;;; INITIALIZATIONS
|
||||
(defn init-animations
|
||||
[]
|
||||
{:scale (anim/use-val c/min-scale)
|
||||
:saved-scale (anim/use-val c/min-scale)
|
||||
:pan-x-start (anim/use-val c/init-offset)
|
||||
:pan-x (anim/use-val c/init-offset)
|
||||
:pan-y-start (anim/use-val c/init-offset)
|
||||
:pan-y (anim/use-val c/init-offset)
|
||||
:pinch-x-start (anim/use-val c/init-offset)
|
||||
:pinch-x (anim/use-val c/init-offset)
|
||||
:pinch-y-start (anim/use-val c/init-offset)
|
||||
:pinch-y (anim/use-val c/init-offset)
|
||||
:pinch-x-max (anim/use-val js/Infinity)
|
||||
:pinch-y-max (anim/use-val js/Infinity)
|
||||
:rotate (anim/use-val c/init-rotation)
|
||||
:rotate-scale (anim/use-val c/min-scale)})
|
||||
|
||||
(defn init-state
|
||||
[]
|
||||
{:pan-x-enabled? (reagent/atom false)
|
||||
:pan-y-enabled? (reagent/atom false)
|
||||
:focal-x (reagent/atom nil)
|
||||
:focal-y (reagent/atom nil)})
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
[react-native.gesture :as gesture]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[utils.re-frame :as rf]
|
||||
[oops.core :refer [oget]]
|
||||
[react-native.orientation :as orientation]
|
||||
|
@ -80,7 +79,7 @@
|
|||
[{:keys [width height screen-height screen-width x-threshold-scale y-threshold-scale] :as dimensions}
|
||||
{:keys [saved-scale scale pinch-x pinch-y pinch-x-start pinch-y-start pinch-x-max pinch-y-max]
|
||||
:as animations}
|
||||
{:keys [focal-x focal-y] :as props}
|
||||
{:keys [focal-x focal-y] :as state}
|
||||
rescale
|
||||
transparent?
|
||||
toggle-opacity]
|
||||
|
@ -135,7 +134,7 @@
|
|||
(utils/center-x animations false))
|
||||
(when (< (anim/get-val scale) y-threshold-scale)
|
||||
(utils/center-y animations false))))
|
||||
(finalize-pinch dimensions animations props)))))
|
||||
(finalize-pinch dimensions animations state)))))
|
||||
|
||||
(defn pan-x-gesture
|
||||
[{:keys [width screen-width x-threshold-scale]}
|
||||
|
@ -204,76 +203,61 @@
|
|||
(anim/animate-decay pan-y velocity [lower-bound upper-bound])
|
||||
(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]
|
||||
(let [{:keys [transparent? set-full-height?]} render-data
|
||||
portrait? (= curr-orientation orientation/portrait)
|
||||
on-tap #(utils/toggle-opacity index render-data portrait?)
|
||||
tap (tap-gesture on-tap)
|
||||
double-tap (double-tap-gesture dimensions animations rescale transparent? on-tap)
|
||||
pinch (pinch-gesture dimensions animations state rescale transparent? on-tap)
|
||||
pan-x (pan-x-gesture dimensions animations state rescale)
|
||||
pan-y (pan-y-gesture dimensions animations state rescale)
|
||||
composed-gestures (gesture/exclusive
|
||||
(gesture/simultaneous pinch pan-x pan-y)
|
||||
(gesture/exclusive double-tap tap))]
|
||||
[gesture/gesture-detector {:gesture composed-gestures}
|
||||
[reanimated/view
|
||||
{:style (style/container dimensions
|
||||
animations
|
||||
@set-full-height?
|
||||
(= curr-orientation orientation/portrait))}
|
||||
[reanimated/fast-image
|
||||
{:source {:uri (:image content)}
|
||||
:native-ID (when focused? :shared-element)
|
||||
:style (style/image dimensions animations (:border-value render-data))}]]]))
|
||||
|
||||
(defn zoomable-image
|
||||
[{:keys [image-width image-height content message-id]} index args on-tap]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [{:keys [transparent? set-full-height?]} args
|
||||
shared-element-id (rf/sub [:shared-element-id])
|
||||
exit-lightbox-signal (rf/sub [:lightbox/exit-signal])
|
||||
zoom-out-signal (rf/sub [:lightbox/zoom-out-signal])
|
||||
focused? (= shared-element-id message-id)
|
||||
curr-orientation (or (rf/sub [:lightbox/orientation])
|
||||
orientation/portrait)
|
||||
portrait? (= curr-orientation orientation/portrait)
|
||||
dimensions (utils/get-dimensions
|
||||
(or image-width c/default-dimension)
|
||||
(or image-height c/default-duration)
|
||||
curr-orientation
|
||||
args)
|
||||
animations {:scale (anim/use-val c/min-scale)
|
||||
:saved-scale (anim/use-val c/min-scale)
|
||||
:pan-x-start (anim/use-val c/init-offset)
|
||||
:pan-x (anim/use-val c/init-offset)
|
||||
:pan-y-start (anim/use-val c/init-offset)
|
||||
:pan-y (anim/use-val c/init-offset)
|
||||
:pinch-x-start (anim/use-val c/init-offset)
|
||||
:pinch-x (anim/use-val c/init-offset)
|
||||
:pinch-y-start (anim/use-val c/init-offset)
|
||||
:pinch-y (anim/use-val c/init-offset)
|
||||
:pinch-x-max (anim/use-val js/Infinity)
|
||||
:pinch-y-max (anim/use-val js/Infinity)
|
||||
:rotate (anim/use-val c/init-rotation)
|
||||
:rotate-scale (anim/use-val c/min-scale)}
|
||||
props {:pan-x-enabled? (reagent/atom false)
|
||||
:pan-y-enabled? (reagent/atom false)
|
||||
:focal-x (reagent/atom nil)
|
||||
:focal-y (reagent/atom nil)}
|
||||
rescale (fn [value exit?]
|
||||
(utils/rescale-image value
|
||||
exit?
|
||||
dimensions
|
||||
animations
|
||||
props))]
|
||||
(rn/use-effect (fn []
|
||||
(js/setTimeout #(reset! set-full-height? true) 500)))
|
||||
(when platform/ios?
|
||||
(utils/handle-orientation-change curr-orientation focused? dimensions animations props)
|
||||
(utils/handle-exit-lightbox-signal exit-lightbox-signal
|
||||
index
|
||||
(anim/get-val (:scale animations))
|
||||
rescale
|
||||
set-full-height?))
|
||||
(utils/handle-zoom-out-signal zoom-out-signal index (anim/get-val (:scale animations)) rescale)
|
||||
[:f>
|
||||
(fn []
|
||||
(let [tap (tap-gesture #(on-tap portrait?))
|
||||
double-tap
|
||||
(double-tap-gesture dimensions animations rescale transparent? #(on-tap portrait?))
|
||||
pinch
|
||||
(pinch-gesture dimensions animations props rescale transparent? #(on-tap portrait?))
|
||||
pan-x (pan-x-gesture dimensions animations props rescale)
|
||||
pan-y (pan-y-gesture dimensions animations props rescale)
|
||||
composed-gestures (gesture/exclusive
|
||||
(gesture/simultaneous pinch pan-x pan-y)
|
||||
(gesture/exclusive double-tap tap))]
|
||||
[gesture/gesture-detector {:gesture composed-gestures}
|
||||
[reanimated/view
|
||||
{:style (style/container dimensions
|
||||
animations
|
||||
@set-full-height?
|
||||
(= curr-orientation orientation/portrait))}
|
||||
[reanimated/fast-image
|
||||
{:source {:uri (:image content)}
|
||||
:native-ID (when focused? :shared-element)
|
||||
:style (style/image dimensions animations (:border-value args))}]]]))]))])
|
||||
[{:keys [image-width image-height content message-id]} index render-data]
|
||||
(let [state (utils/init-state)
|
||||
shared-element-id (rf/sub [:shared-element-id])
|
||||
exit-lightbox-signal (rf/sub [:lightbox/exit-signal])
|
||||
zoom-out-signal (rf/sub [:lightbox/zoom-out-signal])
|
||||
curr-orientation (or (rf/sub [:lightbox/orientation])
|
||||
orientation/portrait)
|
||||
{:keys [set-full-height?]} render-data
|
||||
focused? (= shared-element-id message-id)
|
||||
dimensions (utils/get-dimensions
|
||||
(or image-width c/default-dimension)
|
||||
(or image-height c/default-duration)
|
||||
curr-orientation
|
||||
render-data)
|
||||
animations (utils/init-animations)
|
||||
rescale (fn [value exit?]
|
||||
(utils/rescale-image value
|
||||
exit?
|
||||
dimensions
|
||||
animations
|
||||
state))]
|
||||
(rn/use-effect (fn []
|
||||
(js/setTimeout #(reset! set-full-height? true) 500)))
|
||||
(when platform/ios?
|
||||
(utils/handle-orientation-change curr-orientation focused? dimensions animations state)
|
||||
(utils/handle-exit-lightbox-signal exit-lightbox-signal
|
||||
index
|
||||
(anim/get-val (:scale animations))
|
||||
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?
|
||||
index render-data]))
|
||||
|
|
Loading…
Reference in New Issue