parent
2dad2b67e8
commit
eed38fe082
|
@ -103,6 +103,8 @@
|
|||
(if (fn? ret) ret js/undefined))
|
||||
(bean/->js deps))))
|
||||
|
||||
(def use-callback react/useCallback)
|
||||
|
||||
(defn use-effect-once
|
||||
[effect-fn]
|
||||
(use-effect effect-fn))
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
(ns react-native.gesture
|
||||
(:require ["react-native-gesture-handler" :refer (GestureDetector Gesture gestureHandlerRootHOC)]
|
||||
[reagent.core :as reagent]))
|
||||
(:require ["react-native-gesture-handler" :refer
|
||||
(GestureDetector Gesture gestureHandlerRootHOC TapGestureHandler State)]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :refer [oget]]))
|
||||
|
||||
(def gesture-detector (reagent/adapt-react-class GestureDetector))
|
||||
(def gesture-handler-root-hoc gestureHandlerRootHOC)
|
||||
|
@ -12,3 +14,14 @@
|
|||
(defn on-start [^js pan handler] (.onStart pan handler))
|
||||
|
||||
(defn on-end [^js pan handler] (.onEnd pan handler))
|
||||
|
||||
(def tap-gesture-handler
|
||||
(reagent/adapt-react-class TapGestureHandler))
|
||||
|
||||
(def states
|
||||
{:began (oget State "BEGAN")
|
||||
:active (oget State "ACTIVE")
|
||||
:cancelled (oget State "CANCELLED")
|
||||
:end (oget State "END")
|
||||
:failed (oget State "FAILED")
|
||||
:undetermined (oget State "UNDETERMINED")})
|
||||
|
|
|
@ -1,20 +1,23 @@
|
|||
(ns status-im2.contexts.chat.lightbox.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn container-view
|
||||
[padding-top]
|
||||
(def container-view
|
||||
{:background-color :black
|
||||
:height "100%"
|
||||
:padding-top padding-top})
|
||||
:height "100%"})
|
||||
|
||||
(defn top-view-container
|
||||
[top-inset]
|
||||
[top-inset opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:position :absolute
|
||||
:left 20
|
||||
:top (+ 12 top-inset)
|
||||
:z-index 1
|
||||
:top (if platform/ios? (+ 12 top-inset) 12)
|
||||
:z-index 4
|
||||
:flex-direction :row
|
||||
:width "100%"})
|
||||
:width "100%"}))
|
||||
|
||||
|
||||
(def close-container
|
||||
{:width 32
|
||||
|
@ -26,15 +29,18 @@
|
|||
|
||||
(def top-right-buttons
|
||||
{:position :absolute
|
||||
:right 20
|
||||
:right 40
|
||||
:flex-direction :row})
|
||||
|
||||
(defn gradient-container
|
||||
[insets]
|
||||
[insets opacity]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
{:width "100%"
|
||||
;:height (+ (:bottom insets) 65)
|
||||
:position :absolute
|
||||
:bottom (:bottom insets)})
|
||||
:bottom 0
|
||||
:padding-bottom (:bottom insets)
|
||||
:z-index 3}))
|
||||
|
||||
(def text-style
|
||||
{:color colors/white
|
||||
|
|
|
@ -1,56 +1,81 @@
|
|||
(ns status-im2.contexts.chat.lightbox.view
|
||||
(:require [quo2.core :as quo]
|
||||
(:require
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[oops.core :as oops]
|
||||
[status-im2.contexts.chat.lightbox.style :as style]
|
||||
[utils.datetime :as datetime]
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
[react-native.gesture :as gesture]
|
||||
[oops.core :refer [oget]]))
|
||||
|
||||
(def flat-list-ref (atom nil))
|
||||
(def small-list-ref (atom nil))
|
||||
(def small-image-size 40)
|
||||
(def focused-image-size 56)
|
||||
|
||||
(defn toggle-opacity
|
||||
[opacity-value border-value transparent?]
|
||||
(let [opacity (reanimated/get-shared-value opacity-value)]
|
||||
(reanimated/set-shared-value opacity-value (reanimated/with-timing (if (= opacity 1) 0 1)))
|
||||
(reanimated/set-shared-value border-value (reanimated/with-timing (if (= opacity 1) 0 12)))
|
||||
(reset! transparent? (not @transparent?))))
|
||||
|
||||
(defn image
|
||||
[message]
|
||||
[message opacity-value border-value transparent?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [shared-element-id (rf/sub [:shared-element-id])
|
||||
window-width (:width (rn/get-window))
|
||||
width (:width (rn/get-window))
|
||||
height (* (or (:image-height message) 1000)
|
||||
(/ window-width (or (:image-width message) 1000)))]
|
||||
(/ width (or (:image-width message) 1000)))]
|
||||
[gesture/tap-gesture-handler
|
||||
{:on-handler-state-change (fn [e]
|
||||
(when (= (oget e "nativeEvent.state") (:active gesture/states))
|
||||
(toggle-opacity opacity-value border-value transparent?)))}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:border-radius border-value}
|
||||
{:overflow :hidden})}
|
||||
[fast-image/fast-image
|
||||
{:source {:uri (:image (:content message))}
|
||||
:style {:width window-width
|
||||
:height height
|
||||
:border-radius 12}
|
||||
:native-ID (when (= shared-element-id (:message-id message)) :shared-element)}]))
|
||||
:style {:width width
|
||||
:height height}
|
||||
:native-ID (when (= shared-element-id (:message-id message)) :shared-element)}]]
|
||||
[rn/view {:style {:width 16}}]]]))])
|
||||
|
||||
|
||||
(defn get-item-layout
|
||||
[_ index]
|
||||
(let [window-width (:width (rn/get-window))]
|
||||
#js {:length window-width :offset (* window-width index) :index index}))
|
||||
#js {:length window-width :offset (* (+ window-width 16) index) :index index}))
|
||||
|
||||
(defn get-small-item-layout
|
||||
[_ index]
|
||||
#js {:length small-image-size :offset (* (+ small-image-size 8) index) :index index})
|
||||
|
||||
(defn on-viewable-items-changed
|
||||
[e]
|
||||
(let [changed (-> e (oops/oget :changed) first)]
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated true :index (oops/oget changed :index)})
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id (:message-id (oops/oget changed :item))])))
|
||||
[e scroll-index]
|
||||
(let [changed (-> e (oget :changed) first)
|
||||
index (oget changed :index)]
|
||||
(reset! scroll-index index)
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated true :index index})
|
||||
(rf/dispatch [:chat.ui/update-shared-element-id (:message-id (oget changed :item))])))
|
||||
|
||||
(defn top-view
|
||||
[{:keys [from timestamp]} insets]
|
||||
[{:keys [from timestamp]} insets opacity-value transparent?]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))]
|
||||
[rn/view
|
||||
{:style (style/top-view-container (:top insets))}
|
||||
[reanimated/view
|
||||
{:style (style/top-view-container (:top insets) opacity-value)}
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
{:on-press #(when-not @transparent? (rf/dispatch [:navigate-back]))
|
||||
:style style/close-container}
|
||||
[quo/icon :close {:size 20 :color colors/white}]]
|
||||
[rn/view {:style {:margin-left 12}}
|
||||
|
@ -72,68 +97,95 @@
|
|||
{:active-opacity 1
|
||||
:on-press #(js/alert "to be implemented")
|
||||
:style style/close-container}
|
||||
[quo/icon :options {:size 20 :color colors/white}]]]]))
|
||||
|
||||
[quo/icon :options {:size 20 :color colors/white}]]]]))])
|
||||
|
||||
|
||||
(defn small-image
|
||||
[item]
|
||||
[fast-image/fast-image
|
||||
[item index scroll-index]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [size (if (= @scroll-index index) focused-image-size small-image-size)
|
||||
size-value (reanimated/use-shared-value size)]
|
||||
(reanimated/set-shared-value size-value (reanimated/with-timing size))
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (fn []
|
||||
(reset! scroll-index index)
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated true :index index})
|
||||
(.scrollToIndex ^js @flat-list-ref #js {:animated true :index index}))}
|
||||
[reanimated/fast-image
|
||||
{:source {:uri (:image (:content item))}
|
||||
:style {:width small-image-size
|
||||
:height small-image-size
|
||||
:border-radius 10}}])
|
||||
:style (reanimated/apply-animations-to-style {:width size-value
|
||||
:height size-value}
|
||||
{:border-radius 10})}]]))])
|
||||
|
||||
(defn bottom-view
|
||||
[messages insets]
|
||||
[messages index scroll-index insets opacity-value]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [text (get-in (first messages) [:content :text])
|
||||
padding-horizontal (- (/ (:width (rn/get-window)) 2) (/ small-image-size 2))]
|
||||
[linear-gradient/linear-gradient
|
||||
padding-horizontal (- (/ (:width (rn/get-window)) 2) (/ focused-image-size 2))]
|
||||
[reanimated/linear-gradient
|
||||
{:colors [:black :transparent]
|
||||
:start {:x 0 :y 1}
|
||||
:end {:x 0 :y 0}
|
||||
:style (style/gradient-container insets)}
|
||||
:style (style/gradient-container insets opacity-value)}
|
||||
[rn/text
|
||||
{:style style/text-style} text]
|
||||
[rn/flat-list
|
||||
{:ref #(reset! small-list-ref %)
|
||||
:key-fn :message-id
|
||||
:style {:height 68}
|
||||
:data messages
|
||||
:render-fn small-image
|
||||
:render-fn (fn [item index] [small-image item index scroll-index])
|
||||
:horizontal true
|
||||
:get-item-layout get-small-item-layout
|
||||
:separator [rn/view {:style {:width 8}}]
|
||||
:initial-scroll-index index
|
||||
:content-container-style {:padding-vertical 12
|
||||
:padding-horizontal padding-horizontal}}]]))
|
||||
:padding-horizontal padding-horizontal
|
||||
:align-items :center
|
||||
:justify-content :center}}]]))])
|
||||
|
||||
|
||||
(defn lightbox
|
||||
[]
|
||||
[:f>
|
||||
(fn []
|
||||
(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
|
||||
;; the transition animation to execute properly, otherwise it would animate towards outside the
|
||||
;; screen (even if we have `initialScrollIndex` set).
|
||||
data (reagent/atom [(nth messages 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 [(nth messages index)])
|
||||
scroll-index (reagent/atom index)
|
||||
transparent? (reagent/atom false)
|
||||
opacity-value (reanimated/use-shared-value 1)
|
||||
border-value (reanimated/use-shared-value 12)
|
||||
window-width (:width (rn/get-window))]
|
||||
(reset! data messages)
|
||||
;; We use setTimeout to enqueue `scrollToIndex` until the `data` has been updated.
|
||||
(js/setTimeout #(do
|
||||
(.scrollToIndex ^js @flat-list-ref #js {:animated false :index index})
|
||||
(.scrollToIndex ^js @small-list-ref #js {:animated false :index index}))
|
||||
0)
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
[rn/view
|
||||
{:style (style/container-view (:top insets))}
|
||||
[top-view (first messages) insets]
|
||||
[:f>
|
||||
(fn []
|
||||
;; We use setTimeout to enqueue `scrollToIndex` until the `data` has been updated.
|
||||
(js/setTimeout #(.scrollToIndex ^js @flat-list-ref #js {:animated false :index index}) 0)
|
||||
[rn/view {:style style/container-view}
|
||||
[top-view (first messages) insets opacity-value transparent?]
|
||||
[rn/flat-list
|
||||
{:ref #(reset! flat-list-ref %)
|
||||
:key-fn :message-id
|
||||
:style {:width (+ window-width 16)}
|
||||
:data @data
|
||||
:render-fn image
|
||||
:render-fn (fn [item] [image item opacity-value border-value
|
||||
transparent?])
|
||||
:horizontal true
|
||||
:paging-enabled true
|
||||
:get-item-layout get-item-layout
|
||||
:viewability-config {:view-area-coverage-percent-threshold 50}
|
||||
:on-viewable-items-changed on-viewable-items-changed
|
||||
:on-viewable-items-changed (rn/use-callback (fn [e]
|
||||
(on-viewable-items-changed e
|
||||
scroll-index)))
|
||||
:content-container-style {:justify-content :center
|
||||
:align-items :center}}]
|
||||
[bottom-view messages insets]])]))
|
||||
[bottom-view messages index scroll-index insets opacity-value]])])]))])
|
||||
|
||||
|
|
|
@ -10,31 +10,6 @@
|
|||
|
||||
(def rectangular-style-count 3)
|
||||
|
||||
(defn border-tlr
|
||||
[index]
|
||||
(when (= index 0) 12))
|
||||
|
||||
(defn border-trr
|
||||
[index count album-style]
|
||||
(when (or (and (= index 1) (not= count rectangular-style-count))
|
||||
(and (= index 0) (= count rectangular-style-count) (= album-style :landscape))
|
||||
(and (= index 1) (= count rectangular-style-count) (= album-style :portrait)))
|
||||
12))
|
||||
|
||||
(defn border-blr
|
||||
[index count album-style]
|
||||
(when (or (and (= index 0) (< count rectangular-style-count))
|
||||
(and (= index 2) (> count rectangular-style-count))
|
||||
(and (= index 1) (= count rectangular-style-count) (= album-style :landscape))
|
||||
(and (= index 0) (= count rectangular-style-count) (= album-style :portrait)))
|
||||
12))
|
||||
|
||||
(defn border-brr
|
||||
[index count]
|
||||
(when (or (and (= index 1) (< count rectangular-style-count))
|
||||
(and (= index (- (min count constants/max-album-photos) 1)) (> count 2)))
|
||||
12))
|
||||
|
||||
(defn find-size
|
||||
[size-arr album-style]
|
||||
(if (= album-style :landscape)
|
||||
|
@ -79,8 +54,7 @@
|
|||
(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)})}
|
||||
{:style style/overlay}
|
||||
[quo/text
|
||||
{:weight :bold
|
||||
:size :heading-2
|
||||
|
|
|
@ -21,7 +21,12 @@
|
|||
{:source {:uri uri}
|
||||
:style style/cover}]
|
||||
[rn/view {:style {:margin-left 12}}
|
||||
[quo/text {:weight :medium} title]
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style {:margin-right 50}}
|
||||
title]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||
|
@ -40,6 +45,10 @@
|
|||
{:label title
|
||||
:container-style style/divider}]))
|
||||
|
||||
(defn key-fn
|
||||
[item index]
|
||||
(str (:title item) index))
|
||||
|
||||
(defn album-selector
|
||||
[]
|
||||
[:f>
|
||||
|
@ -61,4 +70,4 @@
|
|||
:render-section-header-fn section-header
|
||||
:style {:margin-top 12}
|
||||
:content-container-style {:padding-bottom 40}
|
||||
:key-fn :title}]]))])
|
||||
:key-fn key-fn}]]))])
|
||||
|
|
|
@ -29,8 +29,7 @@
|
|||
:position :absolute
|
||||
:right 20})
|
||||
|
||||
(defn camera-button-container
|
||||
[]
|
||||
(def camera-button-container
|
||||
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
|
||||
:width 32
|
||||
:height 32
|
||||
|
@ -82,4 +81,3 @@
|
|||
:border-radius 8
|
||||
:top 8
|
||||
:right 8})
|
||||
|
||||
|
|
|
@ -80,15 +80,23 @@
|
|||
(inc (utils/first-index #(= (:uri item) (:uri %)) @selected))])])
|
||||
|
||||
(defn album-title
|
||||
[photos? selected-album]
|
||||
[photos? selected-album selected temporary-selected]
|
||||
[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]
|
||||
:on-press (fn []
|
||||
(if photos?
|
||||
(do
|
||||
(reset! temporary-selected @selected)
|
||||
(rf/dispatch [:open-modal :album-selector]))
|
||||
(rf/dispatch [:navigate-back])))}
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style {:max-width 150}}
|
||||
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)}]]])
|
||||
|
@ -96,16 +104,17 @@
|
|||
(defn photo-selector
|
||||
[]
|
||||
[:f>
|
||||
(let [temporary-selected (reagent/atom [])] ; used when switching albums
|
||||
(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 [])]
|
||||
(let [selected (reagent/atom []) ; currently selected
|
||||
selected-images (rf/sub [:chats/sending-image]) ; already selected and dispatched
|
||||
selected-album (or (rf/sub [:camera-roll/selected-album]) (i18n/label :t/recent))]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(rf/dispatch [:chat.ui/camera-roll-get-photos 20 nil selected-album])
|
||||
(if selected-images
|
||||
(if (seq selected-images)
|
||||
(reset! selected (vec (vals selected-images)))
|
||||
(reset! selected [])))
|
||||
(reset! selected @temporary-selected)))
|
||||
[selected-album])
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
|
@ -117,7 +126,14 @@
|
|||
[rn/view {:style {:flex 1}}
|
||||
[rn/view
|
||||
{:style style/buttons-container}
|
||||
[album-title true selected-album]
|
||||
(when platform/android?
|
||||
[rn/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:style style/camera-button-container}
|
||||
[quo/icon :i/close
|
||||
{:size 20 :color (colors/theme-colors colors/black colors/white)}]])
|
||||
[album-title true selected-album selected temporary-selected]
|
||||
[clear-button selected]]
|
||||
[rn/flat-list
|
||||
{:key-fn identity
|
||||
|
@ -131,6 +147,4 @@
|
|||
:on-end-reached #(rf/dispatch [:camera-roll/on-end-reached end-cursor
|
||||
selected-album loading?
|
||||
has-next-page?])}]
|
||||
[bottom-gradient selected-images insets selected]]))]))])
|
||||
|
||||
|
||||
[bottom-gradient selected-images insets selected]]))])))])
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||
"owner": "status-im",
|
||||
"repo": "status-go",
|
||||
"version": "v0.126.1",
|
||||
"commit-sha1": "cb624b0cc14d95e46754210c9153f8a0444d2845",
|
||||
"src-sha256": "1wrjlzwqj7qzsvh2aba4fjfp29ckx416lkxsk3c7las88ji93wzn"
|
||||
"version": "v0.128.0",
|
||||
"commit-sha1": "82596b2b67f82ae6329ad88e34be6240d08c8ff1",
|
||||
"src-sha256": "17n461i2cglvs66rpqxdxpka4k9ld9ds2ha6scdli2nrfg9jb4q3"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue