refactor and move composer to status-im2 (#14758)

refactor and move composer to status-im2
This commit is contained in:
flexsurfer 2023-01-16 17:20:10 +01:00 committed by GitHub
parent d6c899be3d
commit 685c95591c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 583 additions and 616 deletions

View File

@ -134,7 +134,7 @@
:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
(when (and ring? identicon?)
(when (and false (and ring? identicon?)) ;;TODO not implemented yet
[icons/icon :i/identicon-ring
{:size outer-dimensions
:no-color true}])

View File

@ -4,7 +4,6 @@
(def container
{:height 40
:flex 1
:background-color colors/primary-50-opa-20
:flex-direction :row
:align-items :center

View File

@ -0,0 +1,5 @@
(ns react-native.blur
(:require ["@react-native-community/blur" :as blur]
[reagent.core :as reagent]))
(def view (reagent/adapt-react-class (.-BlurView blur)))

View File

@ -1,6 +1,5 @@
(ns react-native.core
(:require ["@react-native-community/blur" :as blur]
["react" :as react]
(:require ["react" :as react]
["react-native" :as react-native]
[cljs-bean.core :as bean]
[oops.core :as oops]
@ -10,7 +9,6 @@
[reagent.core :as reagent]))
(def app-state ^js (.-AppState ^js react-native))
(def blur-view (reagent/adapt-react-class (.-BlurView blur)))
(def view (reagent/adapt-react-class (.-View ^js react-native)))
(def scroll-view (reagent/adapt-react-class (.-ScrollView ^js react-native)))
@ -90,13 +88,22 @@
props)]
children))
(defn use-effect
([effect] (use-effect effect []))
([effect deps]
(react/useEffect effect (bean/->js deps))))
(def create-ref react/createRef)
(def use-ref react/useRef)
(defn use-effect-once [effect] (use-effect effect))
(defn use-effect
([effect-fn]
(react/useEffect
#(let [ret (effect-fn)]
(if (fn? ret) ret js/undefined))))
([effect-fn deps]
(react/useEffect effect-fn (bean/->js deps))))
(defn use-effect-once
[effect-fn]
(use-effect effect-fn))
(defn use-unmount
[f]
(let [fn-ref (use-ref f)]

View File

@ -5,12 +5,11 @@
(def ^:private consumer-raw (reagent/adapt-react-class (.-Consumer ^js SafeAreaInsetsContext)))
(def provider (reagent/adapt-react-class SafeAreaProvider))
(defn consumer
[component]
[consumer-raw
(fn [^js insets]
(reagent/as-element
[component (js->clj insets :keywordize-keys true)]))])
(def safe-area-provider (reagent/adapt-react-class SafeAreaProvider))
(def safe-area-consumer consumer-raw)

View File

@ -13,7 +13,8 @@
[i18n.i18n :as i18n]
[utils.datetime :as datetime]
[status-im.utils.utils :as utils]
[taoensso.timbre :as log]))
[taoensso.timbre :as log]
[status-im.ui.screens.chat.components.input :as input]))
(defn text->emoji
"Replaces emojis in a specified `text`"
@ -117,37 +118,36 @@
(rf/defn reply-to-message
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/reply-to-message]}
[{:keys [db] :as cofx} message]
[{:keys [db]} message]
(let [current-chat-id (:current-chat-id db)]
(rf/merge cofx
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))})))
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))}))
(rf/defn edit-message
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/edit-message]}
[{:keys [db] :as cofx} message]
(let [current-chat-id (:current-chat-id db)
text (get-in message [:content :text])]
{:dispatch [:chat.ui.input/set-chat-input-text text current-chat-id]
:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))}))
(rf/merge cofx
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))}
(input/set-input-text text current-chat-id))))
(rf/defn show-contact-request-input
"Sets reference to previous chat message and focuses on input"
{:events [:chat.ui/send-contact-request]}
[{:keys [db] :as cofx}]
[{:keys [db]}]
(let [current-chat-id (:current-chat-id db)]
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :sending-contact-request]

View File

@ -53,7 +53,7 @@
(defn contact-request-message
[their-public-key]
(let [{:keys [input-text]} @(re-frame/subscribe [:chats/current-chat-inputs])]
(let [{:keys [input-text]} @(re-frame/subscribe [:chats/current-chat-input])]
[rn/view {:style {:flex-direction :row}}
[rn/view {:style (styles/contact-request-content)}
[quo/button

View File

@ -212,7 +212,7 @@
"Set input text for current-chat. Takes db and input text and cofx
as arguments and returns new fx. Always clear all validation messages."
{:events [:chat.ui.input/set-chat-input-text]}
[{:keys [db] :as cofx} text chat-id]
[{:keys [db]} text chat-id]
(let [text-with-mentions (mentions/->input-field text)
all-contacts (:contacts/contacts db)
chat (get-in db [:chats chat-id])

View File

@ -8,7 +8,7 @@
[status-im.ui2.screens.chat.components.edit.style :as style]))
(defn edit-message
[reset-composer-callback]
[on-cancel]
[rn/view
{:style style/container
:accessibility-label :edit-message}
@ -24,7 +24,7 @@
(i18n/label :t/editing-message)]]]
[gesture-handler/touchable-without-feedback
{:accessibility-label :reply-cancel-button
:on-press #(do (reset-composer-callback true)
:on-press #(do (on-cancel)
(rf/dispatch [:chat.ui/cancel-message-edit]))}
[quo/button
{:width 24

View File

@ -10,7 +10,7 @@
[utils.re-frame :as rf]
[status-im.ui.screens.chat.sheets :refer [hide-sheet-and-dispatch]]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui2.screens.common.contact-list.view :as contact-list]
[status-im2.common.contact-list.view :as contact-list]
[quo2.components.markdown.text :as text]
[status-im.ui.components.invite.events :as invite.events]
[status-im.ui2.screens.chat.components.new-chat.styles :as style]))

View File

@ -0,0 +1,17 @@
(ns status-im.ui2.screens.chat.components.reply.style)
(defn reply-content
[pin?]
{:padding-horizontal (when-not pin? 10)
:flex 1
:flex-direction :row})
(defn quoted-message
[pin?]
(merge {:flex-direction :row
:align-items :center
:width "45%"}
(when-not pin?
{:position :absolute
:left 34
:top 3})))

View File

@ -1,4 +1,4 @@
(ns status-im.ui2.screens.chat.components.reply
(ns status-im.ui2.screens.chat.components.reply.view
(:require [clojure.string :as string]
[i18n.i18n :as i18n]
[quo.react-native :as rn]
@ -10,8 +10,8 @@
[status-im.ethereum.stateofus :as stateofus]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.screens.chat.photos :as photos]
[status-im.ui2.screens.chat.composer.style :as styles]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[status-im.ui2.screens.chat.components.reply.style :as style]))
(defn get-quoted-text-with-mentions
[parsed-text]
@ -73,16 +73,16 @@
{:style {:flex-direction :row
:height (when-not pin? 24)
:accessibility-label :reply-message}}
[rn/view {:style (styles/reply-content pin?)}
[rn/view {:style (style/reply-content pin?)}
(when-not pin?
;;TODO quo2 icon should be used
[icons/icon :main-icons/connector
{:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
:container-style {:position :absolute :left 10 :bottom -4 :width 16 :height 16}}])
(if (or deleted? deleted-for-me?)
[rn/view {:style (styles/quoted-message pin?)}
[rn/view {:style (style/quoted-message pin?)}
[reply-deleted-message]]
[rn/view {:style (styles/quoted-message pin?)}
[rn/view {:style (style/quoted-message pin?)}
[photos/member-photo from identicon 16]
[quo2.text/text
{:weight :semi-bold

View File

@ -16,8 +16,8 @@
(defn edit-message-auto-focus-wrapper
[text-input-ref _]
(let [had-edit (atom nil)]
(fn [_ edit cleanup-composer-callback]
(fn [_ edit on-cancel]
(focus-input-on-edit edit had-edit text-input-ref)
(when edit
[rn/view {:style style/container}
[edit/edit-message cleanup-composer-callback]]))))
[edit/edit-message on-cancel]]))))

View File

@ -0,0 +1,18 @@
(ns status-im.ui2.screens.chat.composer.images.style
(:require [quo2.foundations.colors :as colors]))
(def remove-photo-container
{:width 14
:height 14
:border-radius 7
:background-color colors/neutral-50
:position :absolute
:top 5
:right 5
:justify-content :center
:align-items :center})
(def small-image
{:width 56
:height 56
:border-radius 8})

View File

@ -1,32 +1,33 @@
(ns status-im.ui2.screens.chat.composer.images.view
(:require [quo2.core :as quo2]
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[re-frame.core :as rf]
[react-native.core :as rn]
[status-im.ui2.screens.chat.composer.style :as style]))
[status-im.ui2.screens.chat.composer.images.style :as style]))
(defn image
[item]
[rn/view
;; there is a bug on Android https://github.com/facebook/react-native/issues/12534
;; so we need some magic here with paddings so close button isn't cut
[rn/view {:padding-top 12 :padding-bottom 8 :padding-right 12}
[rn/image
{:source {:uri (first item)}
:style style/small-image}]
[rn/touchable-opacity
{:on-press (fn [] (rf/dispatch [:chat.ui/image-unselected (first item)]))
{:on-press #(rf/dispatch [:chat.ui/image-unselected (first item)])
:style style/remove-photo-container
:hit-slop {:right 5
:left 5
:top 10
:bottom 10}}
[quo2/icon :i/close {:color colors/white :size 12}]]])
[quo/icon :i/close {:color colors/white :size 12}]]])
(defn images-list
[images]
[rn/flat-list
{:key-fn first
:render-fn image
:data images
:horizontal true
:style {:bottom 50 :position :absolute :z-index 5 :elevation 5}
:content-container-style {:padding-horizontal 20 :margin-top 12 :padding-top 8}
:separator [rn/view {:style {:width 12}}]}])
(when (seq images)
[rn/flat-list
{:key-fn first
:render-fn image
:data images
:horizontal true
:keyboard-should-persist-taps :handled}]))

View File

@ -12,13 +12,14 @@
[status-im.chat.models.mentions :as mentions]
[i18n.i18n :as i18n]
[status-im.ui.components.react :as react]
[status-im.ui2.screens.chat.composer.style :as style]
[utils.re-frame :as rf]
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils.utils]
[utils.transforms :as transforms]))
[utils.transforms :as transforms]
[quo2.foundations.typography :as typography]))
(defonce input-texts (atom {}))
(defonce input-text-content-heights (atom {}))
(defonce mentions-enabled? (reagent/atom {}))
(defonce chat-input-key (reagent/atom 1))
(defonce text-input-ref (reagent/atom nil))
@ -29,6 +30,7 @@
:chat.ui/clear-inputs
(fn []
(reset! input-texts {})
(reset! input-text-content-heights {})
(reset! mentions-enabled? {})
(reset! chat-input-key 1)))
@ -58,7 +60,8 @@
(some-> ^js (quo.react/current-ref (:text-input-ref refs))
.clear)
(swap! mentions-enabled? update :render not)
(swap! input-texts dissoc chat-id))
(swap! input-texts dissoc chat-id)
(swap! input-text-content-heights dissoc chat-id))
(defn clear-input
[chat-id refs]
@ -75,6 +78,7 @@
(defn on-text-change
[val chat-id]
(println "on=text-change" val)
(swap! input-texts assoc chat-id val)
;;we still store it in app-db for mentions, we don't have reactions in views
(rf/dispatch [:chat.ui/set-chat-input-text val]))
@ -157,16 +161,31 @@
(when platform/android?
(rf/dispatch [::mentions/calculate-suggestions mentionable-users]))))
(defn text-input-style
[]
(merge typography/font-regular
typography/paragraph-1
{:flex 1
:min-height 34
:margin 0
:flex-shrink 1
:color (:text-01 @quo.colors/theme)
:margin-horizontal 20}
(if platform/android?
{:padding-vertical 8
:text-align-vertical :top}
{:margin-top 8
:margin-bottom 8})))
(defn text-input
[{:keys [set-active-panel refs chat-id sending-image on-content-size-change initial-value]}]
(let [_ (reset! text-input-ref (:text-input-ref refs))
cooldown-enabled? (rf/sub [:chats/current-chat-cooldown-enabled?])
[{:keys [refs chat-id sending-image on-content-size-change]}]
(let [cooldown-enabled? (rf/sub [:chats/current-chat-cooldown-enabled?])
mentionable-users (rf/sub [:chats/mentionable-users])
timeout-id (reagent/atom nil)
last-text-change (reagent/atom nil)
mentions-enabled? (get @mentions-enabled? chat-id)
props
{:style (style/text-input)
{:style (text-input-style)
:ref (:text-input-ref refs)
:max-font-size-multiplier 1
:accessibility-label :chat-message-input
@ -175,13 +194,12 @@
:editable (not cooldown-enabled?)
:blur-on-submit false
:auto-focus false
:default-value initial-value
:on-focus #(set-active-panel nil)
:max-length chat.constants/max-text-size
:placeholder-text-color (:text-02 @quo.colors/theme)
:placeholder (if cooldown-enabled?
(i18n/label :cooldown/text-input-disabled)
(i18n/label :t/type-a-message))
:default-value (get @input-texts chat-id)
:underline-color-android :transparent
:auto-capitalize :sentences
:auto-correct false
@ -232,13 +250,12 @@
(fn [[chat-id text local-text-input-ref]]
(when local-text-input-ref
(reset! text-input-ref local-text-input-ref))
(on-text-change text chat-id)
(if platform/ios?
(.setNativeProps ^js (quo.react/current-ref @text-input-ref) (clj->js {:text text}))
(do
(on-text-change text chat-id)
(if (string/blank? text)
(.clear ^js (quo.react/current-ref @text-input-ref))
(.setNativeProps ^js (quo.react/current-ref @text-input-ref) (clj->js {:text text})))))))
(if (string/blank? text)
(.clear ^js (quo.react/current-ref @text-input-ref))
(.setNativeProps ^js (quo.react/current-ref @text-input-ref) (clj->js {:text text}))))))
(defn calculate-input-text
[{:keys [full-text selection-start selection-end]} content]
@ -318,7 +335,7 @@
(action params)))
(defn selectable-text-input
[chat-id {:keys [style ref on-selection-change] :as props} children]
[_ _ _]
(let [text-input-ref (reagent/atom nil)
menu-items (reagent/atom first-level-menu-items)
first-level (reagent/atom true)
@ -338,7 +355,7 @@
(oops/ocall manager :startActionMode text-input-handle))))
:reagent-render
(fn [_]
(fn [chat-id {:keys [style ref on-selection-change] :as props} children]
(let [ref #(do (reset! text-input-ref %)
(when ref
(quo.react/set-ref-val! ref %)))
@ -361,7 +378,7 @@
(let [native-event (.-nativeEvent event)
native-event (transforms/js->clj native-event)
{:keys [eventType content selectionStart selectionEnd]} native-event
full-text (:input-text (rf/sub [:chats/current-chat-inputs]))]
full-text (:input-text (rf/sub [:chats/current-chat-input]))]
(on-menu-item-touched {:first-level first-level
:event-type eventType
:content content

View File

@ -3,7 +3,6 @@
[quo.components.text :as text]
[quo.react]
[quo.react-native :as rn]
[react-native.reanimated :as reanimated]
[status-im.ui.components.list.views :as list]
[status-im.ui.screens.chat.photos :as photos]
[utils.re-frame :as rf]))
@ -42,20 +41,11 @@
(defn autocomplete-mentions
[suggestions text-input-ref]
[:f>
(fn []
(let [animation (reanimated/use-shared-value 0)]
(quo.react/effect!
#(reanimated/set-shared-value animation (reanimated/with-timing (if (seq suggestions) 0 200))))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY animation}]}
{:bottom 0 :position :absolute :z-index 5 :elevation 5 :max-height 180})}
[list/flat-list
{:keyboardShouldPersistTaps :always
:data suggestions
:key-fn first
:render-fn mention-item
:render-data text-input-ref
:content-container-style {:padding-bottom 12}
:accessibility-label :mentions-list}]]))])
[list/flat-list
{:keyboardShouldPersistTaps :always
:data suggestions
:key-fn first
:render-fn mention-item
:render-data text-input-ref
:content-container-style {:padding-bottom 12}
:accessibility-label :mentions-list}])

View File

@ -1,6 +1,6 @@
(ns status-im.ui2.screens.chat.composer.reply
(:require [quo.react-native :as rn]
[status-im.ui2.screens.chat.components.reply :as reply]
[status-im.ui2.screens.chat.components.reply.view :as reply]
[status-im.ui2.screens.chat.composer.input :as input]))
(defn focus-input-on-reply
@ -21,4 +21,4 @@
[rn/view
{:style {:padding-horizontal 15
:padding-vertical 8}}
[reply/reply-message reply true]]))))
[reply/reply-message reply true]]))))

View File

@ -1,106 +0,0 @@
(ns status-im.ui2.screens.chat.composer.style
(:require [quo.design-system.colors :as quo.colors]
[quo2.foundations.colors :as colors]
[quo2.foundations.typography :as quo2.typography]
[status-im.utils.platform :as platform]))
(defn text-input
[]
(merge quo2.typography/font-regular
quo2.typography/paragraph-1
{:flex 1
:min-height 34
:margin 0
:flex-shrink 1
:color (:text-01 @quo.colors/theme)
:margin-horizontal 20}
(if platform/android?
{:padding-vertical 8
:text-align-vertical :top}
{:margin-top 8
:margin-bottom 8})))
(defn input-bottom-sheet
[window-height]
(merge {:border-top-left-radius 20
:border-top-right-radius 20
:position :absolute
:left 0
:right 0
:bottom (- window-height)
:height window-height
:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-90)
:z-index 2}
(if platform/ios?
{:shadow-radius 16
:shadow-opacity 1
:shadow-color "rgba(9, 16, 28, 0.04)"
:shadow-offset {:width 0 :height -2}}
{:elevation 2})))
(defn bottom-sheet-handle
[]
{:width 32
:height 4
:background-color (colors/theme-colors colors/neutral-100 colors/white)
:opacity 0.05
:border-radius 100
:align-self :center
:margin-top 8})
(defn bottom-sheet-controls
[insets]
{:flex-direction :row
:padding-horizontal 20
:elevation 2
:z-index 3
:position :absolute
:background-color (colors/theme-colors colors/white colors/neutral-90)
;these 3 props play together, we need this magic to hide message text in the safe area
:padding-top 10
:padding-bottom (+ 12 (:bottom insets))
:bottom (- 2 (:bottom insets))})
(defn bottom-sheet-background
[window-height]
{:position :absolute
:left 0
:right 0
:bottom 0
:height window-height
:background-color colors/neutral-95-opa-70
:z-index 1})
(defn reply-content
[pin?]
{:padding-horizontal (when-not pin? 10)
:flex 1
:flex-direction :row})
(defn quoted-message
[pin?]
(merge {:flex-direction :row
:align-items :center
:width "45%"}
(when-not pin?
{:position :absolute
:left 34
:top 3})))
(def remove-photo-container
{:width 14
:height 14
:border-radius 7
:background-color colors/neutral-50
:position :absolute
:top -7
:right -7
:justify-content :center
:align-items :center})
(def small-image
{:width 56
:height 56
:border-radius 8
:margin-bottom 20})

View File

@ -1,345 +0,0 @@
(ns status-im.ui2.screens.chat.composer.view
(:require [clojure.string :as string]
[i18n.i18n :as i18n]
[oops.core :refer [oget]]
[quo.components.safe-area :as safe-area]
[quo.react]
[quo.react-native :as rn :refer [navigation-const]]
[quo2.components.buttons.button :as quo2.button]
[react-native.gesture :as gesture]
[react-native.reanimated :as reanimated]
[status-im.ui.components.permissions :as permissions]
[status-im.ui2.screens.chat.composer.edit.view :as edit]
[status-im.ui2.screens.chat.composer.images.view :as composer-images]
[status-im.ui2.screens.chat.composer.input :as input]
[status-im.ui2.screens.chat.composer.mentions :as mentions]
[status-im.ui2.screens.chat.composer.reply :as reply]
[status-im.ui2.screens.chat.composer.style :as style]
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
[utils.re-frame :as rf]
[status-im.utils.utils :as utils]
[status-im2.contexts.chat.messages.list.view :refer [scroll-to-bottom]]
[status-im.utils.platform :as platform]
[status-im2.common.not-implemented :as not-implemented]))
(defn calculate-y
[context min-y max-y added-value chat-id set-bg-opacity]
(let [input-text (:input-text (get (rf/sub [:chat/inputs]) chat-id))
num-lines (count (string/split input-text "\n"))]
(if (<= 5 num-lines)
(do (when-not (:minimized-from-handlebar? @context)
(swap! context assoc :state :max)
(set-bg-opacity 1))
max-y)
(when (:minimized-from-handlebar? @context)
(swap! context assoc :state :min :minimized-from-handlebar? false)
(set-bg-opacity 0)
min-y))
(if (= (:state @context) :max)
(do
(set-bg-opacity 1)
max-y)
(when (< (:y @context) max-y)
(+ (:y @context) added-value)))))
(defn calculate-y-with-mentions
[y max-y max-height chat-id suggestions reply]
(let [input-text (:input-text (get (rf/sub [:chat/inputs]) chat-id))
num-lines (count (string/split input-text "\n"))
text-height (* num-lines 22)
mentions-height (min 132 (+ 16 (* 46 (- (count suggestions) 1))))
should-translate? (if (< (- max-height text-height) mentions-height) true false)
min-value (if-not reply mentions-height (+ mentions-height 44))
; translate value when mentions list appear while at bottom of expanded input sheet
mentions-translate-value (if should-translate?
(min min-value (- mentions-height (- max-height text-height)))
mentions-height)]
(when (or (< y max-y) should-translate?) mentions-translate-value)))
(defn get-y-value
[context min-y max-y added-value max-height chat-id suggestions reply edit images set-bg-opacity]
(let [y (calculate-y context min-y max-y added-value chat-id set-bg-opacity)
y-with-mentions (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)]
(+ y (when (seq suggestions) y-with-mentions) (when (seq images) 80) (when edit 38))))
(defn- clean-and-minimize-composer
([context chat-id refs min-y]
(clean-and-minimize-composer context chat-id refs min-y false))
([context chat-id refs min-y edit?]
(input/clear-input chat-id refs)
(swap! context assoc
:y
(if edit?
(- min-y 38)
min-y))
(swap! context assoc :clear true :state :min)))
(defn get-bottom-sheet-gesture
[context translate-y text-input-ref keyboard-shown min-y max-y shared-height max-height set-bg-opacity]
(-> (gesture/gesture-pan)
(gesture/on-start
(fn [_]
(if keyboard-shown
(swap! context assoc :pan-y (reanimated/get-shared-value translate-y))
(input/input-focus text-input-ref))))
(gesture/on-update
(fn [evt]
(when keyboard-shown
(swap! context assoc :dy (- (.-translationY evt) (:pdy @context)))
(swap! context assoc :pdy (.-translationY evt))
(reanimated/set-shared-value
translate-y
(max (min (+ (.-translationY evt) (:pan-y @context)) (- min-y)) (- max-y))))))
(gesture/on-end
(fn [_]
(when keyboard-shown
(if (< (:dy @context) 0)
(do
(swap! context assoc :minimized-from-handlebar? false)
(swap! context assoc :state :max)
(input/input-focus text-input-ref)
(reanimated/set-shared-value translate-y (reanimated/with-timing (- max-y)))
(reanimated/set-shared-value shared-height (reanimated/with-timing max-height))
(set-bg-opacity 1))
(do
(swap! context assoc :minimized-from-handlebar? true)
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
(set-bg-opacity 0)
(rf/dispatch [:dismiss-keyboard]))))))))
(defn get-input-content-change
[context translate-y shared-height max-height set-bg-opacity keyboard-shown min-y max-y blank-composer?
initial-value]
(fn [evt]
(when-not (or blank-composer? (some? initial-value))
(swap! context assoc :clear false))
(if (:clear @context)
(do
(swap! context dissoc :clear)
(swap! context assoc :state :min)
(swap! context assoc :y min-y)
(reanimated/set-shared-value translate-y (reanimated/with-timing (- min-y)))
(reanimated/set-shared-value shared-height (reanimated/with-timing min-y))
(set-bg-opacity 0))
(when (not= (:state @context) :max)
(let [offset-value (if platform/ios? 22 40)
new-y (+ min-y
(- (max (oget evt "nativeEvent" "contentSize" "height") offset-value)
offset-value))]
(if (< new-y max-y)
(do
(if (> (- max-y new-y) 120)
(do
(swap! context assoc :state :custom-chat-available)
(set-bg-opacity 0))
(do
(set-bg-opacity 1)
(swap! context assoc :state :custom-chat-unavailable)))
(swap! context assoc :y new-y)
(when keyboard-shown
(reanimated/set-shared-value
translate-y
(reanimated/with-timing (- new-y)))
(reanimated/set-shared-value
shared-height
(reanimated/with-timing (min new-y max-height)))))
(do
(swap! context assoc :state :max)
(swap! context assoc :y max-y)
(if keyboard-shown
(do (set-bg-opacity 1)
(reanimated/set-shared-value
translate-y
(reanimated/with-timing (- max-y))))
(set-bg-opacity 0)))))))))
(defn composer
[chat-id]
[safe-area/consumer
(fn [insets]
(let [min-y 112
context (atom {:y min-y ;current y value
:min-y min-y ;minimum y value
:dy 0 ;used for gesture
:pdy 0 ;used for gesture
:state :min ;:min, :custom-chat-available,
;:custom-chat-unavailable, :max
:clear false
:minimized-from-handlebar? false})
keyboard-was-shown? (atom false)
text-input-ref (quo.react/create-ref)
send-ref (quo.react/create-ref)
refs {:send-ref send-ref
:text-input-ref text-input-ref}]
(fn []
[:f>
(fn []
(let [reply (rf/sub [:chats/reply-message])
edit (rf/sub [:chats/edit-message])
suggestions (rf/sub [:chat/mention-suggestions])
images (get-in (rf/sub [:chat/inputs])
[chat-id :metadata :sending-image])
{window-height :height} (rn/use-window-dimensions)
{:keys [keyboard-shown keyboard-height]} (rn/use-keyboard)
max-y (- window-height
(if (> keyboard-height 0)
keyboard-height
360)
(:top insets)
(:status-bar-height @navigation-const)) ; 360
; -
; default
; height
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56
; -
; top-bar
; height
added-value (if (and (not (seq suggestions))
(or edit reply))
38
0) ; increased height
; of input box
; needed when reply
min-y (+ min-y (when (or edit reply) 38))
bg-opacity (reanimated/use-shared-value 0)
bg-bottom (reanimated/use-shared-value (-
window-height))
set-bg-opacity
(fn [value]
(reanimated/set-shared-value bg-bottom (if (= value 1) 0 (- window-height)))
(reanimated/set-shared-value bg-opacity (reanimated/with-timing value)))
y (get-y-value
context
min-y
max-y
added-value
max-height
chat-id
suggestions
reply
edit
images
set-bg-opacity)
translate-y (reanimated/use-shared-value 0)
shared-height (reanimated/use-shared-value min-y)
clean-and-minimize-composer-fn
#(clean-and-minimize-composer context chat-id refs min-y %)
blank-composer? (string/blank? (get @input/input-texts
chat-id))
initial-value (or (get @input/input-texts chat-id) nil)
input-content-change (get-input-content-change
context
translate-y
shared-height
max-height
set-bg-opacity
keyboard-shown
min-y
max-y
blank-composer?
initial-value)
bottom-sheet-gesture (get-bottom-sheet-gesture
context
translate-y
text-input-ref
keyboard-shown
min-y
max-y
shared-height
max-height
set-bg-opacity)]
(quo.react/effect!
(fn []
(let [input-text (-> [:chat/inputs]
rf/sub
(get chat-id)
:input-text)
edited? (not= input-text (-> edit :content :text))]
(when (and @keyboard-was-shown? (not keyboard-shown))
(swap! context assoc :state :min)
(set-bg-opacity 0))
(when (and blank-composer? (empty? images) (not edit))
(clean-and-minimize-composer-fn false))
(if (or (seq images) (and (not blank-composer?) edited?))
(input/show-send refs)
(input/hide-send refs))
(reset! keyboard-was-shown? keyboard-shown)
(if (#{:max :custom-chat-unavailable} (:state @context))
(set-bg-opacity 1)
(set-bg-opacity 0))
(reanimated/set-shared-value translate-y (reanimated/with-timing (- y)))
(reanimated/set-shared-value shared-height
(reanimated/with-timing (min y max-height))))))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:height shared-height}
{:z-index 2})}
;;INPUT MESSAGE bottom sheet
[gesture/gesture-detector {:gesture bottom-sheet-gesture}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
(style/input-bottom-sheet window-height))}
;handle
[rn/view {:style (style/bottom-sheet-handle)}]
[edit/edit-message-auto-focus-wrapper text-input-ref edit
clean-and-minimize-composer-fn]
[reply/reply-message-auto-focus-wrapper text-input-ref reply]
[rn/view {:style {:height (- max-y 80 added-value)}}
[input/text-input
{:chat-id chat-id
:on-content-size-change input-content-change
:sending-image (seq images)
:initial-value initial-value
:refs refs
:set-active-panel #()}]]]]
;CONTROLS
(when-not (seq suggestions)
[rn/view {:style (style/bottom-sheet-controls insets)}
[quo2.button/button
{:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
(photo-selector/photo-selector chat-id))}])
:on-denied (fn []
(utils/set-timeout
#(utils/show-popup (i18n/label :t/error)
(i18n/label
:t/external-storage-denied))
50))}))
:icon true
:type :outline
:size 32} :i/image]
[rn/view {:width 12}]
[not-implemented/not-implemented
[quo2.button/button
{:icon true
:type :outline
:size 32} :i/reaction]]
[rn/view {:flex 1}]
;;SEND button
[rn/view
{:ref send-ref
:style (when (seq images)
{:width 0
:right -100})}
[quo2.button/button
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press #(do (clean-and-minimize-composer-fn (some? edit))
(scroll-to-bottom)
(rf/dispatch [:chat.ui/send-current-message]))}
:i/arrow-up]]])
;black background
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity bg-opacity
:transform [{:translateY bg-bottom}]}
(style/bottom-sheet-background window-height))}]
[composer-images/images-list images]
[mentions/autocomplete-mentions suggestions text-input-ref]]))])))])

View File

@ -23,7 +23,7 @@
[status-im.ui.screens.chat.styles.message.message :as style]
[status-im.ui.screens.chat.utils :as chat.utils]
[status-im.ui.screens.communities.icon :as communities.icon]
[status-im.ui2.screens.chat.components.reply :as components.reply]
[status-im.ui2.screens.chat.components.reply.view :as components.reply]
[status-im.utils.config :as config]
[utils.datetime :as datetime]
[status-im.utils.utils :as utils]

View File

@ -1,4 +1,4 @@
(ns status-im.ui2.screens.common.contact-list.view
(ns status-im2.common.contact-list.view
(:require [quo2.core :as quo]
[react-native.core :as rn]
[status-im2.common.contact-list-item.view :as contact-list-item]

View File

@ -3,6 +3,7 @@
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.blur :as blur]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.common.scroll-page.style :as style]
@ -68,7 +69,7 @@
{:source cover
:position :absolute
:style (style/image-slider (get-header-size @scroll-height))}]
[rn/blur-view (style/blur-slider (get-header-size @scroll-height))]]
[blur/view (style/blur-slider (get-header-size @scroll-height))]]
[rn/view {:style {:z-index 6 :margin-top (if platform/ios? 44 0)}}
[quo/page-nav
{:horizontal-description? true

View File

@ -6,7 +6,7 @@
[react-native.core :as rn]
[status-im.chat.models :as chat.models]
[status-im2.contexts.chat.group-details.style :as style]
[status-im.ui2.screens.common.contact-list.view :as contact-list]
[status-im2.common.contact-list.view :as contact-list]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.common.home.actions.view :as actions]
[utils.re-frame :as rf]))

View File

@ -4,7 +4,7 @@
[re-frame.core :as re-frame]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.ui2.screens.common.contact-list.view :as contact-list]
[status-im2.common.contact-list.view :as contact-list]
[status-im2.common.home.view :as common.home]
[status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item]
[status-im2.contexts.chat.home.contact-request.view :as contact-request]

View File

@ -0,0 +1,14 @@
(ns status-im2.contexts.chat.messages.composer.controls.style
(:require [quo2.foundations.colors :as colors]))
(defn controls
[insets]
{:padding-horizontal 20
:elevation 4
:z-index 3
:position :absolute
:background-color (colors/theme-colors colors/white colors/neutral-90)
:padding-bottom (+ 12 (:bottom insets))
:bottom 0
:left 0
:right 0})

View File

@ -0,0 +1,71 @@
(ns status-im2.contexts.chat.messages.composer.controls.view
(:require [react-native.core :as rn]
[react-native.background-timer :as background-timer]
[utils.re-frame :as rf]
[i18n.i18n :as i18n]
[quo2.core :as quo]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.chat.photo-selector.view :as photo-selector]
[status-im2.contexts.chat.messages.composer.controls.style :as style]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[status-im.ui.components.permissions :as permissions]
[status-im.ui2.screens.chat.composer.images.view :as composer-images]
[status-im.utils.utils :as utils-old]
[status-im.ui2.screens.chat.composer.input :as input]))
(defn send-button
[send-ref {:keys [chat-id images]} on-send]
[rn/view
{:ref send-ref
:style (when-not (or (seq (get @input/input-texts chat-id)) (seq images))
{:width 0
:right -100})}
[quo/button
{:icon true
:size 32
:accessibility-label :send-message-button
:on-press (fn []
(on-send)
(messages.list/scroll-to-bottom)
(rf/dispatch [:chat.ui/send-current-message]))}
:i/arrow-up]])
(defn reactions-button
[]
[not-implemented/not-implemented
[quo/button
{:icon true
:type :outline
:size 32} :i/reaction]])
(defn image-button
[chat-id]
[quo/button
{:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
(photo-selector/photo-selector chat-id))}])
:on-denied (fn []
(background-timer/set-timeout
#(utils-old/show-popup (i18n/label :t/error)
(i18n/label
:t/external-storage-denied))
50))}))
:icon true
:type :outline
:size 32}
:i/image])
(defn view
[send-ref params insets chat-id images on-send]
[rn/view {:style (style/controls insets)}
[composer-images/images-list images]
[rn/view {:style {:flex-direction :row :margin-top 12}}
[image-button chat-id]
[rn/view {:width 12}]
[reactions-button]
[rn/view {:flex 1}]
[send-button send-ref params on-send]]])

View File

@ -0,0 +1,42 @@
(ns status-im2.contexts.chat.messages.composer.style
(:require [quo2.foundations.colors :as colors]
[status-im.utils.platform :as platform]))
(defn input-bottom-sheet
[window-height]
(merge {:border-top-left-radius 20
:border-top-right-radius 20
:position :absolute
:left 0
:right 0
:bottom (- window-height)
:height window-height
:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-90)
:z-index 2}
(if platform/ios?
{:shadow-radius 16
:shadow-opacity 1
:shadow-color "rgba(9, 16, 28, 0.04)"
:shadow-offset {:width 0 :height -2}}
{:elevation 4})))
(defn bottom-sheet-handle
[]
{:width 32
:height 4
:background-color (colors/theme-colors colors/neutral-100 colors/white)
:opacity 0.05
:border-radius 100
:align-self :center
:margin-top 8})
(defn bottom-sheet-background
[window-height]
{:position :absolute
:left 0
:right 0
:bottom 0
:height window-height
:background-color colors/neutral-95-opa-70
:z-index 1})

View File

@ -0,0 +1,250 @@
(ns status-im2.contexts.chat.messages.composer.view
(:require [clojure.string :as string]
[oops.core :refer [oget]]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[react-native.gesture :as gesture]
[react-native.reanimated :as reanimated]
[react-native.background-timer :as background-timer]
[utils.re-frame :as rf]
[status-im2.contexts.chat.messages.composer.style :as style]
[status-im2.contexts.chat.messages.composer.controls.view :as controls]
[status-im.ui2.screens.chat.composer.edit.view :as edit]
[status-im.ui2.screens.chat.composer.input :as input]
[status-im.ui2.screens.chat.composer.mentions :as mentions]
[status-im.ui2.screens.chat.composer.reply :as reply]))
(def initial-content-height (atom nil))
(def keyboard-hiding? (atom false))
(defn minimize
[{:keys [min-y set-bg-opacity set-translate-y set-parent-height]}]
(set-bg-opacity 0)
(set-translate-y (- min-y))
(set-parent-height min-y))
(defn maximize
[{:keys [max-y set-bg-opacity set-translate-y set-parent-height max-parent-height]}]
(set-bg-opacity 1)
(set-translate-y (- max-y))
(set-parent-height max-parent-height))
(defn clean-and-minimize
[{:keys [chat-id refs] :as params}]
(input/clear-input chat-id refs)
(minimize params))
(def gesture-values (atom {}))
(defn get-bottom-sheet-gesture
[{:keys [translate-y refs keyboard-shown min-y max-y] :as params}]
(let [{:keys [text-input-ref]} refs]
(-> (gesture/gesture-pan)
(gesture/on-start
(fn [_]
(if keyboard-shown
(swap! gesture-values assoc :pan-y (reanimated/get-shared-value translate-y))
(input/input-focus text-input-ref))))
(gesture/on-update
(fn [evt]
(when keyboard-shown
(let [tY (oget evt "translationY")]
(swap! gesture-values assoc :dy (- tY (:pdy @gesture-values)))
(swap! gesture-values assoc :pdy tY)
(reanimated/set-shared-value
translate-y
(max (min (+ tY (:pan-y @gesture-values)) (- min-y)) (- max-y)))))))
(gesture/on-end
(fn [_]
(when keyboard-shown
(if (< (:dy @gesture-values) 0)
(maximize params)
(do
(reset! keyboard-hiding? true)
(minimize params)
(background-timer/set-timeout #(rf/dispatch [:dismiss-keyboard]) 200)))))))))
(defn update-y
[{:keys [max-parent-height set-bg-opacity keyboard-shown max-y set-translate-y set-parent-height
min-y chat-id]
:as params}]
(let [content-height (get @input/input-text-content-heights chat-id)
new-y (+ min-y
(if (and content-height @initial-content-height)
(- content-height
@initial-content-height)
0))]
(if (< new-y max-y)
(when keyboard-shown
(if (> new-y max-parent-height)
(set-bg-opacity 1)
(set-bg-opacity 0))
(set-translate-y (- new-y))
(set-parent-height (min new-y max-parent-height)))
(if keyboard-shown
(maximize params)
(set-bg-opacity 0)))))
(defn get-input-content-change
[{:keys [chat-id] :as params}]
(fn [evt]
(let [new-height (oget evt "nativeEvent.contentSize.height")]
(swap! input/input-text-content-heights assoc chat-id new-height)
(if @initial-content-height
(do
;;on Android when last symbol removed, height value is wrong, like 300px
(when (string/blank? (get @input/input-texts chat-id))
(swap! input/input-text-content-heights assoc chat-id @initial-content-height))
(update-y params))
(reset! initial-content-height new-height)))))
(defn mentions
[{:keys [refs suggestions max-y]} insets]
[:f>
(fn []
(let [translate-y (reanimated/use-shared-value 0)]
(rn/use-effect
(fn []
(reanimated/set-shared-value translate-y
(reanimated/with-timing (if (seq suggestions) 0 200)))))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
{:bottom (or (:bottom insets) 0)
:position :absolute
:z-index 5
:elevation 5
:max-height (/ max-y 2)})}
[mentions/autocomplete-mentions suggestions (:text-input-ref refs)]]))])
(defn effect!
[{:keys [keyboard-shown] :as params}]
(rn/use-effect
(fn []
(when (or (not @keyboard-hiding?)
(and @keyboard-hiding? (not keyboard-shown)))
(reset! keyboard-hiding? false)
(if (not keyboard-shown)
(minimize params)
(update-y params))))))
(defn prepare-params
[[refs window-height translate-y bg-opacity bg-bottom min-y max-y parent-height
max-parent-height chat-id suggestions reply edit images keyboard-shown]]
{:chat-id chat-id
:translate-y translate-y
:min-y min-y
:max-y max-y
:max-parent-height max-parent-height
:parent-height parent-height
:suggestions suggestions
:reply reply
:edit edit
:images images
:refs refs
:keyboard-shown keyboard-shown
:bg-opacity bg-opacity
:bg-bottom bg-bottom
:window-height window-height
:set-bg-opacity (fn [value]
(reanimated/set-shared-value bg-bottom (if (= value 1) 0 (- window-height)))
(reanimated/set-shared-value bg-opacity (reanimated/with-timing value)))
:set-translate-y (fn [value]
(reanimated/set-shared-value translate-y (reanimated/with-timing value)))
:set-parent-height (fn [value]
(reanimated/set-shared-value parent-height (reanimated/with-timing value)))})
;; IMPORTANT! PLEASE READ BEFORE MAKING CHANGES
;; 1) insets are not stable so we can't rely on the first values and we have to use it from render
;; function, so effect will be triggered a few times, for example first time it will be 0 and second
;; time 38 on ios, and 400 and 0 on Android
;; 2) for keyboard we use hooks, for some reason it triggers effect a few times with the same values,
;; also it changes value only when keyboard completely closed or opened, that's why its not visually
;; smooth, there is a small visible delay between keyboard and sheet animations
;; 3) when we minimize sheet and hide keyboard in `sheet-gesture` function, keyboard hook triggers
;; effect and there is a visual glitch when we have more than one line of text, so we use
;; `keyboard-hiding?` flag
;; 4) we store input content height in `input/input-text-content-heights` atom , we need it when chat
;; screen is reopened
(defn composer
[_ _]
(let [text-input-ref (rn/create-ref)
send-ref (rn/create-ref)
refs {:send-ref send-ref
:text-input-ref text-input-ref}]
(fn [chat-id insets]
[:f>
(fn []
(let [reply (rf/sub [:chats/reply-message])
edit (rf/sub [:chats/edit-message])
suggestions (rf/sub [:chat/mention-suggestions])
images (rf/sub [:chats/sending-image])
{window-height :height} (rn/use-window-dimensions)
{:keys [keyboard-shown keyboard-height]} (hooks/use-keyboard)
translate-y (reanimated/use-shared-value 0)
bg-opacity (reanimated/use-shared-value 0)
bg-bottom (reanimated/use-shared-value (- window-height))
suggestions? (and (seq suggestions)
keyboard-shown
(not @keyboard-hiding?))
max-y (- window-height
(- (if (> keyboard-height 0)
keyboard-height
360)
(:bottom insets))
46)
min-y (+ 108
(:bottom insets)
(if suggestions?
(min (/ max-y 2)
(+ 16
(* 46 (dec (count suggestions)))))
(+ 0
(when (or edit reply) 38)
(when (seq images) 80))))
parent-height (reanimated/use-shared-value min-y)
max-parent-height (Math/abs (- max-y 110 (:bottom insets)))
params
(prepare-params
[refs window-height translate-y bg-opacity bg-bottom min-y max-y parent-height
max-parent-height chat-id suggestions reply edit images keyboard-shown])
input-content-change (get-input-content-change params)
bottom-sheet-gesture (get-bottom-sheet-gesture params)]
(effect! params)
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:height parent-height}
{})}
;;;;input
[gesture/gesture-detector {:gesture bottom-sheet-gesture}
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translate-y}]}
(style/input-bottom-sheet window-height))}
[rn/view {:style (style/bottom-sheet-handle)}]
[edit/edit-message-auto-focus-wrapper text-input-ref edit #(clean-and-minimize params)]
[reply/reply-message-auto-focus-wrapper text-input-ref reply]
[rn/view
{:style {:height (- max-y (- min-y 38))}}
[input/text-input
{:chat-id chat-id
:on-content-size-change input-content-change
:sending-image (seq images)
:refs refs}]]]]
(if suggestions?
[mentions params insets]
[controls/view send-ref params insets chat-id images #(clean-and-minimize params)])
;;;;black background
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:opacity bg-opacity
:transform [{:translateY bg-bottom}]}
(style/bottom-sheet-background window-height))}]]))])))

View File

@ -6,7 +6,7 @@
[i18n.i18n :as i18n]
[status-im2.setup.config :as config]
[status-im.ui.components.react :as react]
[status-im.ui2.screens.chat.components.reply :as components.reply]
[status-im.ui2.screens.chat.components.reply.view :as components.reply]
[status-im2.common.not-implemented :as not-implemented]))
(defn pin-message

View File

@ -2,19 +2,19 @@
(:require [quo2.core :as quo]
[re-frame.db]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im.ui2.screens.chat.composer.view :as composer]
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]
[status-im2.contexts.chat.messages.composer.view :as composer]
[status-im2.common.constants :as constants]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[status-im2.contexts.chat.messages.contact-requests.bottom-drawer :as
contact-requests.bottom-drawer]
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner] ;;TODO move to status-im2
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
[status-im2.navigation.state :as navigation.state]
[status-im2.common.not-implemented :as not-implemented]
[utils.debounce :as debounce]
[utils.re-frame :as rf]
[status-im2.common.not-implemented :as not-implemented]
[quo2.foundations.colors :as colors]))
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]))
(defn navigate-back-handler
[]
@ -64,30 +64,25 @@
(defn chat-render
[]
(let [{:keys [chat-id
contact-request-state
show-input?]
:as chat}
(let [;;NOTE: we want to react only on these fields, do not use full chat map here
{:keys [chat-id contact-request-state show-input?] :as chat}
(rf/sub [:chats/current-chat-chat-view])]
[rn/keyboard-avoiding-view {:style {:position :relative :flex 1}}
[rn/view
{:style {:position :absolute
:top 56
:z-index 2
:background-color (colors/theme-colors colors/white colors/neutral-100)
:width "100%"}}
[safe-area/consumer
(fn [insets]
[rn/keyboard-avoiding-view
{:style {:position :relative :flex 1}
:keyboardVerticalOffset (- (:bottom insets))}
[page-nav]
[pin.banner/banner chat-id]
[not-implemented/not-implemented
[pin-limit-popover/pin-limit-popover chat-id]]
[messages.list/messages-list {:chat chat :show-input? show-input?}]
(cond (and (not show-input?)
contact-request-state)
[contact-requests.bottom-drawer/view chat-id contact-request-state]
[pin.banner/banner chat-id]
[not-implemented/not-implemented
[pin-limit-popover/pin-limit-popover chat-id]]]
[page-nav]
[messages.list/messages-list {:chat chat :show-input? show-input?}]
(cond (and (not show-input?)
contact-request-state)
[contact-requests.bottom-drawer/view chat-id contact-request-state]
show-input?
[composer/composer chat-id])]))
show-input?
[composer/composer chat-id insets])])]))
(defn chat
[]

View File

@ -4,6 +4,7 @@
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.blur :as blur]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.common.constants :as constants]
@ -307,7 +308,7 @@
[channel-heights first-channel-height]
(fn [scroll-height]
(when (> scroll-height @first-channel-height)
[rn/blur-view
[blur/view
{:blur-amount 32
:blur-type :xlight
:overlay-color (if platform/ios? colors/white-opa-70 :transparent)

View File

@ -4,8 +4,8 @@
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im.async-storage.core :as async-storage]
[status-im2.contexts.shell.constants :as shell.constants] ;;TODO remove when not used anymore
))
[status-im2.contexts.shell.constants :as shell.constants])) ;;TODO remove when not used anymore
;; Atoms
(def selected-stack-id (atom nil))

View File

@ -1,6 +1,5 @@
(ns status-im2.navigation.view
(:require [oops.core :refer [oget]]
[quo2.foundations.colors :as colors]
(:require [quo2.foundations.colors :as colors]
[re-frame.core :as re-frame]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
@ -38,19 +37,14 @@
(concat screens/components)))
(defn wrapped-screen-style
[{:keys [insets style]} insets-obj]
[screen-insets safe-insets]
(merge
{:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-100)}
style
(when (get insets :bottom)
{:padding-bottom (+ (oget insets-obj "bottom")
(get style :padding-bottom)
(get style :padding-vertical))})
(when (get insets :top true)
{:padding-top (+ (oget insets-obj "top")
(get style :padding-top)
(get style :padding-vertical))})))
(when (get screen-insets :bottom)
{:padding-bottom (:bottom safe-insets)})
(when (get screen-insets :top true)
{:padding-top (:top safe-insets)})))
(defn inactive
[]
@ -75,16 +69,13 @@
screens)
(keyword key))]
^{:key (str "root" key @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/safe-area-consumer
[safe-area/provider
[safe-area/consumer
(fn [safe-insets]
(reagent/as-element
[rn/view
{:style (wrapped-screen-style
{:insets insets}
safe-insets)}
[inactive]
[component]]))]
[rn/view
{:style (wrapped-screen-style insets safe-insets)}
[inactive]
[component]])]
(when js/goog.DEBUG
[reloader/reload-view])]))))
@ -99,7 +90,7 @@
(reagent/reactify-component
(fn []
^{:key (str "popover" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[popover/popover]
(when js/goog.DEBUG
@ -116,7 +107,7 @@
(reagent/reactify-component
(fn []
^{:key (str "visibility-status-popover" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[visibility-status-views/visibility-status-popover]
(when js/goog.DEBUG
@ -126,7 +117,7 @@
(reagent/reactify-component
(fn []
^{:key (str "sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[bottom-sheets/bottom-sheet]
(when js/goog.DEBUG
@ -138,7 +129,7 @@
(reagent/reactify-component
(fn []
^{:key (str "signing-sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[signing/signing]
(when js/goog.DEBUG
@ -148,7 +139,7 @@
(reagent/reactify-component
(fn []
^{:key (str "select-acc-sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[wallet.send.views/select-account]
(when js/goog.DEBUG
@ -158,7 +149,7 @@
(reagent/reactify-component
(fn []
^{:key (str "wallet-connect-sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[wallet-connect/wallet-connect-proposal-sheet]
(when js/goog.DEBUG
@ -168,7 +159,7 @@
(reagent/reactify-component
(fn []
^{:key (str "wallet-connect-success-sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[wallet-connect/wallet-connect-success-sheet-view]
(when js/goog.DEBUG
@ -178,7 +169,7 @@
(reagent/reactify-component
(fn []
^{:key (str "wallet-connect-app-management-sheet" @reloader/cnt)}
[safe-area/safe-area-provider
[safe-area/provider
[inactive]
[wallet-connect/wallet-connect-app-management-sheet-view]
(when js/goog.DEBUG

View File

@ -132,7 +132,7 @@
(get chats current-chat-id)))
(re-frame/reg-sub
:chats/current-chat-inputs
:chats/current-chat-input
:<- [:chats/current-chat-id]
:<- [:chat/inputs]
(fn [[chat-id inputs]]
@ -285,19 +285,19 @@
(re-frame/reg-sub
:chats/reply-message
:<- [:chats/current-chat-inputs]
:<- [:chats/current-chat-input]
(fn [{:keys [metadata]}]
(:responding-to-message metadata)))
(re-frame/reg-sub
:chats/edit-message
:<- [:chats/current-chat-inputs]
:<- [:chats/current-chat-input]
(fn [{:keys [metadata]}]
(:editing-message metadata)))
(re-frame/reg-sub
:chats/sending-contact-request
:<- [:chats/current-chat-inputs]
:<- [:chats/current-chat-input]
(fn [{:keys [metadata]}]
(:sending-contact-request metadata)))