Compare commits

...
Author SHA1 Message Date
Omar Basem 85d9909084 updates 2023-07-04 11:27:11 +04:00
Omar Basem 21ce4aabd8 updates 2023-07-04 11:24:34 +04:00
Omar Basem b9247cb517 updates 2023-07-04 11:15:32 +04:00
Omar Basem 24b8349b95 updates 2023-07-04 11:01:03 +04:00
Omar Basem e9adebc3fb updates 2023-07-04 10:47:31 +04:00
Omar Basem 531e63e2ea updates 2023-07-04 10:33:25 +04:00
Omar Basem 47b5470a91 updates 2023-07-04 10:23:21 +04:00
Omar Basem 3b0a7911e3 updates 2023-07-04 09:45:02 +04:00
Omar Basem bf7d36b899 updates 2023-07-04 09:19:57 +04:00
Omar Basem b9ba4fdf42 updates 2023-07-04 09:10:29 +04:00
Omar Basem b16c45f2fc updates 2023-07-04 08:56:57 +04:00
Omar Basem 0255eb051e fix 2023-07-03 18:59:25 +04:00
Omar Basem 1fd1d0ee79 feat: lightbox text 2023-07-03 17:21:01 +04:00
Omar Basem 2cc844111c feat: lightbox text 2023-07-03 16:08:41 +04:00
Omar Basem 75926edb81 feat: lightbox text 2023-07-03 11:22:44 +04:00
11 changed files with 241 additions and 40 deletions
+7
View File
@@ -6,3 +6,10 @@ export function infoLayout(input, isTop) {
return isTop ? input.value : -input.value;
});
}
export function textSheet(input, isHeight) {
return useDerivedValue(function () {
'worklet';
return isHeight ? input.value : -input.value;
});
}
+2
View File
@@ -88,6 +88,8 @@
(def neutral-100-opa-5 (alpha neutral-100 0.05))
(def neutral-100-opa-10 (alpha neutral-100 0.1))
(def neutral-100-opa-30 (alpha neutral-100 0.3))
(def neutral-100-opa-50 (alpha neutral-100 0.5))
(def neutral-100-opa-60 (alpha neutral-100 0.6))
(def neutral-100-opa-70 (alpha neutral-100 0.7))
(def neutral-100-opa-80 (alpha neutral-100 0.8))
@@ -1,13 +1,16 @@
(ns status-im2.contexts.chat.lightbox.bottom-view
(:require
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.lightbox.style :as style]
[utils.re-frame :as rf]
[status-im2.contexts.chat.lightbox.animations :as anim]
[status-im2.contexts.chat.lightbox.constants :as c]
[status-im2.contexts.chat.messages.content.text.view :as message-view]))
[status-im2.contexts.chat.messages.content.text.view :as message-view]
[status-im2.contexts.chat.lightbox.text-sheet.view :as text-sheet]))
(defn get-small-item-layout
[_ index]
@@ -48,20 +51,16 @@
[item index _ render-data]
[:f> f-small-image item index _ render-data])
(defn bottom-view
[messages index scroll-index insets animations derived item-width props]
(let [{:keys [chat-id content]} (first messages)
padding-horizontal (- (/ item-width 2) (/ c/focused-image-size 2))]
[messages index scroll-index insets animations derived item-width props state]
(let [padding-horizontal (- (/ item-width 2) (/ c/focused-image-size 2))]
[reanimated/linear-gradient
{:colors [:black :transparent]
{:colors [colors/neutral-100-opa-100 colors/neutral-100-opa-50]
:start {:x 0 :y 1}
:end {:x 0 :y 0}
:style (style/gradient-container insets animations derived)}
(when c/image-description-in-lightbox?
[message-view/render-parsed-text
{:content content
:chat-id chat-id
:style-override style/text-style}])
[text-sheet/view messages animations state]
[rn/flat-list
{:ref #(reset! (:small-list-ref props) %)
:key-fn :message-id
@@ -75,4 +74,10 @@
:get-item-layout get-small-item-layout
:separator [rn/view {:style {:width 8}}]
:initial-scroll-index index
:content-container-style (style/content-container padding-horizontal)}]]))
:content-container-style (style/content-container padding-horizontal)}]
[rn/view
{:style {:height (:bottom insets)
:position :absolute
:bottom 0
:left 0
:right 0}}]]))
@@ -66,6 +66,7 @@
{:transform [{:translateY bottom-layout}]
:opacity opacity}
{:position :absolute
:overflow :visible
:bottom 0
:padding-bottom (:bottom insets)
:z-index 3}))
@@ -77,8 +78,15 @@
:align-items :center
:justify-content :center})
(def text-style
{:color colors/white
:align-self :center
:margin-horizontal 20
:margin-vertical 12})
(defn background
[{:keys [overlay-opacity]} {:keys [overlay-z-index]}]
(reanimated/apply-animations-to-style
{:opacity overlay-opacity}
{:background-color colors/neutral-100-opa-70
:position :absolute
:top 0
:bottom 0
:z-index @overlay-z-index
:left 0
:right 0}))
@@ -0,0 +1,32 @@
(ns status-im2.contexts.chat.lightbox.text-sheet.style
(:require [quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(def text-style
{:color colors/white
:align-self :center
:margin-horizontal 20
:margin-vertical 12
:flex-grow 1})
(def bar-container
{:height 20
:left 0
:right 0
:top 0
:z-index 1
:justify-content :center
:align-items :center})
(defn bar
[]
{:width 32
:height 4
:border-radius 100
:background-color colors/white-opa-40
:border-width 0.5
:border-color colors/neutral-100})
@@ -0,0 +1,127 @@
(ns status-im2.contexts.chat.lightbox.text-sheet.view
(:require
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[react-native.linear-gradient :as linear-gradient]
[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.constants :as c]
[oops.core :as oops]
[status-im2.contexts.chat.lightbox.text-sheet.style :as style]
[status-im2.contexts.chat.messages.content.text.view :as message-view]
[utils.worklets.lightbox :as worklet]))
(defn drag-gesture
[derived-value saved-top expanded-height max-height opacity gradient-opacity overlay-z-index expanded?]
(-> (gesture/gesture-pan)
(gesture/enabled true)
(gesture/max-pointers 1)
(gesture/on-start (fn []
(reset! overlay-z-index 1)
(reanimated/animate gradient-opacity 0)))
(gesture/on-update
(fn [e]
(let [new-value (+ (reanimated/get-shared-value saved-top) (oops/oget e "translationY"))
progress (/ (- new-value) max-height)]
(reanimated/set-shared-value opacity progress)
(reanimated/set-shared-value derived-value (max (min (- new-value) expanded-height) c/small-list-height)))))
(gesture/on-end (fn [e]
(if (or (> (- (reanimated/get-shared-value derived-value))
(reanimated/get-shared-value saved-top))
(= (reanimated/get-shared-value derived-value) c/small-list-height))
(do
(reanimated/animate derived-value c/small-list-height)
(reanimated/animate opacity 0)
(reanimated/set-shared-value saved-top (- c/small-list-height))
(reset! expanded? false)
(js/setTimeout #(reset! overlay-z-index 0) 300))
(reanimated/set-shared-value saved-top (- (reanimated/get-shared-value derived-value))))
(when (= (reanimated/get-shared-value derived-value) expanded-height)
(reset! expanded? true))))))
(defn bar
[]
[rn/view {:style style/bar-container}
[rn/view {:style (style/bar)}]])
(defn text-sheet
[messages text-height expanded? opacity overlay-z-index]
(let [{:keys [chat-id content]} (first messages)
insets (safe-area/get-insets)
window-height (:height (rn/get-window))
max-height (- window-height
c/small-list-height
c/top-view-height
(:bottom insets)
(when platform/ios? (:top insets)))
text-padding 24
expanded-height (min max-height (+ 20 @text-height text-padding))
derived-value (reanimated/use-shared-value c/small-list-height)
height (worklet/text-sheet derived-value true)
top (worklet/text-sheet derived-value false)
saved-top (reanimated/use-shared-value (- c/small-list-height))
gradient-opacity (reanimated/use-shared-value 0)]
[gesture/gesture-detector
{:gesture (drag-gesture derived-value saved-top expanded-height max-height opacity gradient-opacity overlay-z-index expanded?)}
[reanimated/touchable-opacity
{:active-opacity 1
:on-press (fn []
(reanimated/animate derived-value expanded-height)
(reanimated/animate opacity 1)
(reanimated/set-shared-value saved-top (- expanded-height))
(reset! overlay-z-index 1)
(reset! expanded? true))
:style (reanimated/apply-animations-to-style
{:height height
:top top}
{:position :absolute
:left 0
:right 0})}
(when (> @text-height 44)
[bar])
[reanimated/linear-gradient
{:colors [colors/neutral-100-opa-0 colors/neutral-100]
:start {:x 0 :y 1}
:end {:x 0 :y 0}
:style (reanimated/apply-animations-to-style
{:opacity gradient-opacity}
{:position :absolute
:left 0
:right 0
:top (- (+ c/top-view-height (:top insets)))
:height (+ c/top-view-height (:top insets) 20 12 44)
:z-index 1})}]
[linear-gradient/linear-gradient
{:colors [colors/neutral-100-opa-50 colors/neutral-100-opa-0]
:start {:x 0 :y 1}
:end {:x 0 :y 0}
:style {:position :absolute
:left 0
:right 0
:height 28
:bottom 0
:z-index 1}}]
[gesture/scroll-view
{:scroll-enabled true
:scroll-event-throttle 16
:on-scroll (fn [e]
(if (and (> (oops/oget e "nativeEvent.contentOffset.y") 0) @expanded?)
(reanimated/animate gradient-opacity 1)
(reanimated/animate gradient-opacity 0)))
:style {:height (- max-height 20)}}
[message-view/render-parsed-text
{:content content
:chat-id chat-id
:style-override style/text-style
:on-layout (fn [event]
(reset! text-height (oops/oget event "nativeEvent.layout.height")))}]]]]))
(defn view
[messages {:keys [overlay-opacity]} {:keys [overlay-z-index]}]
(let [text-height (reagent/atom 0)
expanded? (reagent/atom false)]
[:f> text-sheet messages text-height expanded? overlay-opacity overlay-z-index]))
@@ -43,8 +43,9 @@
(anim/animate top-view-bg colors/neutral-100-opa-0)))))
(defn drawer
[content]
(let [uri (http/replace-port (:image content)
[messages index]
(let [{:keys [content]} (nth messages @index)
uri (http/replace-port (:image content)
(rf/sub [:mediaserver/port]))]
[quo/action-drawer
[[{:icon :i/save
@@ -61,17 +62,22 @@
:container-style {:bottom (when platform/android? 20)}
:text (i18n/label :t/photo-saved)}])))}]]]))
(defn share-image
[messages index]
(let [{:keys [content]} (nth messages @index)
uri (http/replace-port (:image content)
(rf/sub [:mediaserver/port]))]
(images/share-image uri)))
(defn top-view
[messages insets index animations derived landscape? screen-width]
(let [{:keys [from timestamp content]} (nth @messages @index)
(let [{:keys [from timestamp]} (first messages)
display-name (first (rf/sub [:contacts/contact-two-names-by-identity
from]))
bg-color (if landscape?
colors/neutral-100-opa-70
colors/neutral-100-opa-0)
{:keys [background-color opacity]} animations
uri (http/replace-port (:image content)
(rf/sub [:mediaserver/port]))]
{:keys [background-color opacity overlay-opacity]} animations]
[reanimated/view
{:style
(style/top-view-container (:top insets) screen-width bg-color landscape? animations derived)}
@@ -87,6 +93,7 @@
{:on-press (fn []
(anim/animate background-color :transparent)
(anim/animate opacity 0)
(anim/animate overlay-opacity 0)
(rf/dispatch (if platform/ios?
[:chat.ui/exit-lightbox-signal @index]
[:navigate-back])))
@@ -100,15 +107,15 @@
[quo/text
{:weight :medium
:size :paragraph-2
:style {:color colors/neutral-40}} (datetime/to-short-str timestamp)]]]
:style {:color colors/neutral-40}} (when timestamp (datetime/to-short-str timestamp))]]]
[rn/view {:style style/top-right-buttons}
[rn/touchable-opacity
{:active-opacity 1
:on-press #(images/share-image uri)
:on-press #(share-image messages index)
:style (merge style/close-container {:margin-right 12})}
[quo/icon :share {:size 20 :color colors/white}]]
[rn/touchable-opacity
{:active-opacity 1
:on-press #(rf/dispatch [:show-bottom-sheet {:content (fn [] [drawer content])}])
:on-press #(rf/dispatch [:show-bottom-sheet {:content (fn [] [drawer messages index])}])
:style style/close-container}
[quo/icon :options {:size 20 :color colors/white}]]]]))
@@ -31,8 +31,9 @@
(fn []
(reagent/next-tick (fn []
(when @flat-list-ref
(.scrollToIndex ^js @flat-list-ref
#js {:animated false :index index}))))
(.scrollToOffset ^js @flat-list-ref
#js {:animated false
:offset (* (+ (:width (rn/get-window)) constants/separator-width) index)}))))
(swap! timers assoc
:mount-animation
(js/setTimeout (fn []
@@ -125,7 +126,9 @@
{:flat-list-ref (atom nil)
:small-list-ref (atom nil)
:scroll-index-lock? (atom true)
:timers (atom {})})
:timers (atom {})
:viewability-config (atom {:view-area-coverage-percent-threshold 50
:wait-for-interaction true})})
(defn init-state
[messages index]
@@ -135,13 +138,15 @@
{:data (reagent/atom (if (number? index) [(nth messages index)] []))
:scroll-index (reagent/atom index)
:transparent? (reagent/atom false)
:set-full-height? (reagent/atom false)})
:set-full-height? (reagent/atom false)
:overlay-z-index (reagent/atom 0)})
(defn init-animations
[]
{:background-color (anim/use-val colors/neutral-100-opa-0)
:border (anim/use-val (if platform/ios? 0 12))
:opacity (anim/use-val 0)
:overlay-opacity (anim/use-val 0)
:rotate (anim/use-val "0deg")
:layout (anim/use-val -10)
:top-view-y (anim/use-val 0)
@@ -43,7 +43,8 @@
[rn/view {:style {:width constants/separator-width}}]])
(defn lightbox-content
[props {:keys [data transparent? scroll-index set-full-height?]} animations derived messages index
[props {:keys [data transparent? scroll-index set-full-height?] :as state} animations derived messages
index
callback]
(let [insets (safe-area/get-insets)
window (rn/get-window)
@@ -66,7 +67,7 @@
{:style (reanimated/apply-animations-to-style {:background-color (:background-color animations)}
{:height screen-height})}
(when-not @transparent?
[:f> top-view/top-view data insets scroll-index animations derived landscape?
[:f> top-view/top-view messages insets scroll-index animations derived landscape?
screen-width])
[gesture/gesture-detector
{:gesture (utils/drag-gesture animations (and landscape? platform/ios?) set-full-height?)}
@@ -75,6 +76,7 @@
{:transform [{:translateY (:pan-y animations)}
{:translateX (:pan-x animations)}]}
{})}
[reanimated/view {:style (style/background animations state)}]
[gesture/flat-list
{:ref #(reset! (:flat-list-ref props) %)
:key-fn :message-id
@@ -95,24 +97,23 @@
:inverted inverted?
:paging-enabled true
:get-item-layout (fn [_ index] (get-item-layout _ index item-width))
:viewability-config {:view-area-coverage-percent-threshold 50
:wait-for-interaction true}
:viewability-config @(:viewability-config props)
:shows-vertical-scroll-indicator false
:shows-horizontal-scroll-indicator false
:on-viewable-items-changed callback}]]]
(when (and (not @transparent?) (not landscape?))
[:f> bottom-view/bottom-view messages index scroll-index insets animations derived
item-width props])]))
item-width props state])]))
(defn- f-lightbox
[{:keys [messages index]}]
(let [props (utils/init-props)
state (utils/init-state messages index)]
state (utils/init-state messages index)
callback (rn/use-callback
#(on-viewable-items-changed % props state))]
(fn [{:keys [messages index]}]
(let [animations (utils/init-animations)
derived (utils/init-derived-animations animations)
callback (fn [e]
(on-viewable-items-changed e props state))]
derived (utils/init-derived-animations animations)]
(anim/animate (:background-color animations) colors/neutral-100)
(reset! (:data state) messages)
(when platform/ios? ; issue: https://github.com/wix/react-native-navigation/issues/7726
@@ -2,6 +2,7 @@
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[oops.core :as oops]
[react-native.core :as rn]
[status-im2.contexts.chat.messages.content.link-preview.view :as link-preview]
[status-im2.contexts.chat.messages.content.text.style :as style]
@@ -139,9 +140,11 @@
(conj parsed-text {:type :edited-block :children [edited-tag]}))))
(defn render-parsed-text
[{:keys [content chat-id edited-at style-override]}]
[{:keys [content chat-id edited-at style-override on-layout]}]
^{:key (:parsed-text content)}
[rn/view {:style style-override}
[rn/view
{:style style-override
:on-layout on-layout}
(reduce (fn [acc e]
(render-block acc e chat-id style-override))
[:<>]
+4
View File
@@ -5,3 +5,7 @@
(defn info-layout
[input top?]
(.infoLayout ^js layout-worklets input top?))
(defn text-sheet
[input height?]
(.textSheet ^js layout-worklets input height?))