chat input performance improvements
Signed-off-by: andrey <motor4ik@gmail.com>
This commit is contained in:
parent
7c4c520712
commit
3de7c37d90
|
@ -65,11 +65,6 @@
|
|||
(s/explain spec prop)
|
||||
false)))
|
||||
|
||||
;; TODO(Ferossgp): Check performance for android layout animations
|
||||
(when (and platform/android?
|
||||
(aget rn/ui-manager "setLayoutAnimationEnabledExperimental"))
|
||||
(ocall rn/ui-manager "setLayoutAnimationEnabledExperimental" true))
|
||||
|
||||
(def height 44) ; 22 line-height + 11*2 vertical padding
|
||||
(def multiline-height 88) ; 3 * 22 three line-height + 11* vertical padding
|
||||
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
(oset! ref "current" val)
|
||||
val)
|
||||
|
||||
(defn set-native-props [^js ref ^js props]
|
||||
(when-let [curr-ref ^js (current-ref ref)]
|
||||
(.setNativeProps curr-ref props)))
|
||||
|
||||
(deftype StateHook [value set-value]
|
||||
cljs.core/IHash
|
||||
(-hash [o] (goog/getUid o))
|
||||
|
|
|
@ -238,12 +238,13 @@
|
|||
|
||||
(fx/defn close-chat
|
||||
{:events [:close-chat]}
|
||||
[{:keys [db] :as cofx} chat-id]
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [chat-id (:current-chat-id db)]
|
||||
(chat.state/reset-visible-item)
|
||||
(fx/merge cofx
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(offload-messages chat-id)
|
||||
(navigation/navigate-back)))
|
||||
(navigation/navigate-back))))
|
||||
|
||||
(fx/defn remove-chat
|
||||
"Removes chat completely from app, producing all necessary effects for that"
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
[{:keys [db] :as cofx} text-input-ref {:keys [alias name searched-text match] :as user}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
new-text (mentions/new-input-text-with-mention cofx user)
|
||||
at-sign-idx (get-in db [:chats chat-id :mentions :at-sign-idx])
|
||||
at-sign-idx (get-in db [:chats/mentions chat-id :mentions :at-sign-idx])
|
||||
cursor (+ at-sign-idx (count name) 2)]
|
||||
(fx/merge
|
||||
cofx
|
||||
|
|
|
@ -122,6 +122,11 @@
|
|||
#(re-frame/dispatch [::messages-loaded chat-id session-id %])
|
||||
#(re-frame/dispatch [::failed-loading-messages chat-id session-id %]))))))))
|
||||
|
||||
(fx/defn load-more-messages-for-current-chat
|
||||
{:events [:chat.ui/load-more-messages-for-current-chat]}
|
||||
[{:keys [db] :as cofx}]
|
||||
(load-more-messages cofx (:current-chat-id db) false))
|
||||
|
||||
(fx/defn load-messages
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
(when-not (get-in db [:pagination-info chat-id :messages-initialized?])
|
||||
|
|
|
@ -448,7 +448,7 @@
|
|||
|
||||
(fx/defn on-text-input
|
||||
{:events [::on-text-input]}
|
||||
[{:keys [db] :as cofx} {:keys [new-text previous-text start end] :as args}]
|
||||
[{:keys [db]} {:keys [previous-text start end] :as args}]
|
||||
(log/debug "[mentions] on-text-input args" args)
|
||||
(let [normalized-previous-text
|
||||
;; NOTE(rasom): on iOS `previous-text` contains entire input's text. To
|
||||
|
@ -457,16 +457,14 @@
|
|||
previous-text
|
||||
(subs previous-text start end))
|
||||
chat-id (:current-chat-id db)
|
||||
previous-state (get-in db [:chats chat-id :mentions])
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
previous-state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-state (-> previous-state
|
||||
(merge args)
|
||||
(assoc :previous-text normalized-previous-text))
|
||||
old-at-idxs (:at-idxs new-state)
|
||||
new-at-idxs (calc-at-idxs new-state)
|
||||
new-state (assoc new-state :at-idxs new-at-idxs)]
|
||||
(log/debug "[mentions] on-text-input state" new-state)
|
||||
{:db (assoc-in db [:chats chat-id :mentions] new-state)}))
|
||||
{:db (assoc-in db [:chats/mentions chat-id :mentions] new-state)}))
|
||||
|
||||
(defn calculate-input [text [first-idx :as idxs]]
|
||||
(if-not first-idx
|
||||
|
@ -496,8 +494,7 @@
|
|||
[{:keys [db]} mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [new-text start end] :as state}
|
||||
(get-in db [:chats chat-id :mentions])
|
||||
state (get-in db [:chats/mentions chat-id :mentions])
|
||||
new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
(:at-idxs state)
|
||||
|
@ -506,25 +503,25 @@
|
|||
(log/debug "[mentions] new-at-idxs" new-at-idxs calculated-input)
|
||||
{:db (-> db
|
||||
(update-in
|
||||
[:chats chat-id :mentions]
|
||||
[:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:at-idxs new-at-idxs)
|
||||
(assoc-in [:chat/inputs-with-mentions chat-id] calculated-input))}))
|
||||
|
||||
(fx/defn calculate-suggestions
|
||||
{:events [::calculate-suggestions]}
|
||||
[{:keys [db] :as cofx} mentionable-users]
|
||||
[{:keys [db]} mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [new-text at-idxs start end] :as state}
|
||||
(get-in db [:chats chat-id :mentions])
|
||||
(get-in db [:chats/mentions chat-id :mentions])
|
||||
new-text (or new-text text)]
|
||||
(log/debug "[mentions] calculate suggestions"
|
||||
"state" state)
|
||||
(if-not (seq at-idxs)
|
||||
{:db (-> db
|
||||
(assoc-in [:chats/mention-suggestions chat-id] nil)
|
||||
(assoc-in [:chats chat-id :mentions :at-idxs] nil)
|
||||
(assoc-in [:chats/mentions chat-id :mentions :at-idxs] nil)
|
||||
(assoc-in [:chat/inputs-with-mentions chat-id] [[:text text]]))}
|
||||
(let [new-at-idxs (check-idx-for-mentions
|
||||
text
|
||||
|
@ -550,7 +547,7 @@
|
|||
"mentions" (count mentions))
|
||||
(log/debug "[mentions] new-at-idxs" new-at-idxs calculated-input)
|
||||
{:db (-> db
|
||||
(update-in [:chats chat-id :mentions]
|
||||
(update-in [:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:at-sign-idx at-sign-idx
|
||||
:at-idxs new-at-idxs
|
||||
|
@ -563,7 +560,7 @@
|
|||
(let [chat-id (:current-chat-id db)
|
||||
text (get-in db [:chat/inputs chat-id :input-text])
|
||||
{:keys [mention-end at-sign-idx]}
|
||||
(get-in db [:chats chat-id :mentions])]
|
||||
(get-in db [:chats/mentions chat-id :mentions])]
|
||||
(log/debug "[mentions] clear suggestions"
|
||||
"state" new-input-text-with-mention)
|
||||
(string/join
|
||||
|
@ -589,7 +586,7 @@
|
|||
(fx/merge
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update-in [:chats chat-id] dissoc :mentions)
|
||||
(update-in [:chats/mentions chat-id] dissoc :mentions)
|
||||
(update :chat/inputs-with-mentions dissoc chat-id))}
|
||||
(clear-suggestions))))
|
||||
|
||||
|
@ -607,7 +604,7 @@
|
|||
mentionable-users]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
{:keys [mention-end at-idxs]}
|
||||
(get-in db [:chats chat-id :mentions])]
|
||||
(get-in db [:chats/mentions chat-id :mentions])]
|
||||
(when (seq at-idxs)
|
||||
(if (some
|
||||
(fn [{:keys [from to] :as idx}]
|
||||
|
@ -617,7 +614,7 @@
|
|||
at-idxs)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:db (update-in db [:chats chat-id :mentions]
|
||||
{:db (update-in db [:chats/mentions chat-id :mentions]
|
||||
assoc
|
||||
:start end
|
||||
:end end
|
||||
|
|
|
@ -4,8 +4,7 @@
|
|||
[status-im.wallet.db :as wallet.db]))
|
||||
|
||||
;; initial state of app-db
|
||||
(def app-db {:keyboard-height 0
|
||||
:contacts/contacts {}
|
||||
(def app-db {:contacts/contacts {}
|
||||
:pairing/installations {}
|
||||
:group/selected-contacts #{}
|
||||
:chats {}
|
||||
|
|
|
@ -66,8 +66,6 @@
|
|||
(reg-root-key-sub :animations :animations)
|
||||
(reg-root-key-sub :ui/search :ui/search)
|
||||
(reg-root-key-sub :web3-node-version :web3-node-version)
|
||||
(reg-root-key-sub :keyboard-height :keyboard-height)
|
||||
(reg-root-key-sub :keyboard-max-height :keyboard-max-height)
|
||||
(reg-root-key-sub :sync-data :sync-data)
|
||||
(reg-root-key-sub :mobile-network/remember-choice? :mobile-network/remember-choice?)
|
||||
(reg-root-key-sub :qr-modal :qr-modal)
|
||||
|
@ -789,12 +787,6 @@
|
|||
(fn [input]
|
||||
(:input-text input)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-input-text
|
||||
:<- [:chats/current-chat-inputs]
|
||||
(fn [input]
|
||||
(:input-text input)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-membership
|
||||
:<- [:chats/current-chat-id]
|
||||
|
@ -827,6 +819,12 @@
|
|||
(not group-chat)
|
||||
(assoc :show-input? true)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-chat-view
|
||||
:<- [:chats/current-chat]
|
||||
(fn [current-chat]
|
||||
(select-keys current-chat [:chat-id :show-input? :group-chat :admins :invitation-admin :public? :chat-type :color :chat-name])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:current-chat/metadata
|
||||
:<- [:chats/current-raw-chat]
|
||||
|
@ -914,6 +912,12 @@
|
|||
(fn [chats [_ chat-id]]
|
||||
(get-in chats [chat-id :public?])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/might-have-join-time-messages?
|
||||
:<- [::chats]
|
||||
(fn [chats [_ chat-id]]
|
||||
(get-in chats [chat-id :might-have-join-time-messages?])))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/message-list
|
||||
:<- [::message-lists]
|
||||
|
@ -1019,6 +1023,31 @@
|
|||
(fn [{:keys [metadata]}]
|
||||
(:sending-image metadata)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/chat-toolbar
|
||||
:<- [:disconnected?]
|
||||
:<- [:multiaccounts/login]
|
||||
:<- [:chats/sending-image]
|
||||
:<- [:mainnet?]
|
||||
:<- [:current-chat/one-to-one-chat?]
|
||||
:<- [:current-chat/metadata]
|
||||
:<- [:chats/reply-message]
|
||||
(fn [[disconnected? {:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply]]
|
||||
(let [sending-image (seq sending-image)]
|
||||
{:send (and (not (or processing disconnected?)))
|
||||
:stickers (and mainnet?
|
||||
(not sending-image)
|
||||
(not reply))
|
||||
:image (and (not reply)
|
||||
(not public?))
|
||||
:extensions (and one-to-one-chat?
|
||||
(or config/commands-enabled? mainnet?)
|
||||
(not reply))
|
||||
:audio (and (not sending-image)
|
||||
(not reply)
|
||||
(not public?))
|
||||
:sending-image sending-image})))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:public-chat.new/topic-error-message
|
||||
:<- [:public-group-topic]
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
(animation/parallel
|
||||
[(animation/timing blue-bar-left-margin (easing :out 0))
|
||||
(animation/timing white-bar-left-margin (easing :out 0))])]))))}
|
||||
[react/view
|
||||
[react/view {:style {:width parent-width
|
||||
:position :absolute
|
||||
:top -3
|
||||
|
@ -62,13 +63,13 @@
|
|||
[react/animated-view {:style (assoc (animated-bar-style white-bar-left-margin
|
||||
parent-width
|
||||
colors/white)
|
||||
:left (* 0.15 parent-width))}]]))
|
||||
:left (* 0.15 parent-width))}]]]))
|
||||
|
||||
(defview loading-indicator []
|
||||
(letsubs [ui-status-properties [:connectivity/ui-status-properties]
|
||||
(letsubs [fetching? [:mailserver/fetching?]
|
||||
window-width [:dimensions/window-width]]
|
||||
(when (:loading-indicator? ui-status-properties)
|
||||
[loading-indicator-anim @window-width])))
|
||||
(when fetching?
|
||||
[loading-indicator-anim window-width])))
|
||||
|
||||
(defn hide-sheet-and-dispatch [event]
|
||||
(re-frame/dispatch [:bottom-sheet/hide])
|
||||
|
|
|
@ -230,7 +230,7 @@
|
|||
[components/separator-dark]
|
||||
[react/view
|
||||
(when loading?
|
||||
[connectivity/loading-indicator window-width])]
|
||||
[connectivity/loading-indicator-anim window-width])]
|
||||
[browser-component {:dapp? dapp?
|
||||
:dapp dapp
|
||||
:error? error?
|
||||
|
|
|
@ -281,7 +281,7 @@
|
|||
[cancel-button (:cancel-disabled? @state) #(stop-recording base-params)]]
|
||||
[rec-button-view (merge base-params {:state state})]
|
||||
[react/animated-view {:style {:opacity ctrl-buttons-anim-value}}
|
||||
[input/send-button {:on-send-press (fn [] (cond
|
||||
[input/send-button (fn [] (cond
|
||||
(= :ready-to-send (:general @state))
|
||||
(do
|
||||
(reset-timer timer)
|
||||
|
@ -291,4 +291,4 @@
|
|||
(#{:recording :recording-paused} (:general @state))
|
||||
(stop-recording (merge base-params
|
||||
{:on-success
|
||||
#(send-audio-msessage state)}))))}]]]])))
|
||||
#(send-audio-msessage state)}))))]]]])))
|
||||
|
|
|
@ -10,16 +10,17 @@
|
|||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[quo.components.animated.pressable :as pressable]
|
||||
[quo.animated :as animated]
|
||||
[status-im.utils.config :as config]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[quo.components.list.item :as list-item]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[reagent.core :as reagent]))
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(defn input-focus [text-input-ref]
|
||||
(some-> ^js (react/current-ref text-input-ref) .focus))
|
||||
|
||||
(def panel->icons {:extensions :main-icons/commands
|
||||
:images :main-icons/photo})
|
||||
|
@ -70,9 +71,8 @@
|
|||
[icons/icon :main-icons/keyboard (styles/icon false)]
|
||||
[icons/icon :main-icons/speech (styles/icon false)])]])
|
||||
|
||||
(defn send-button [{:keys [on-send-press]}]
|
||||
[pressable/pressable {:type :scale
|
||||
:on-press on-send-press}
|
||||
(defn send-button [on-send]
|
||||
[rn/touchable-opacity {:on-press-in on-send}
|
||||
[rn/view {:style (styles/send-message-button)}
|
||||
[icons/icon :main-icons/arrow-up
|
||||
{:container-style (styles/send-message-container)
|
||||
|
@ -107,8 +107,50 @@
|
|||
:end end}
|
||||
mentionable-users]))))
|
||||
|
||||
(defn on-change [on-text-change last-text-change timeout-id mentionable-users args]
|
||||
(let [text (.-text ^js (.-nativeEvent ^js args))]
|
||||
(defonce input-texts (atom {}))
|
||||
(defonce mentions-enabled (reagent/atom {}))
|
||||
|
||||
(defn show-send [{:keys [actions-ref send-ref sticker-ref]}]
|
||||
(quo.react/set-native-props actions-ref #js {:width 0 :left -88})
|
||||
(quo.react/set-native-props send-ref #js {:width nil :right nil})
|
||||
(quo.react/set-native-props sticker-ref #js {:width 0 :right -100}))
|
||||
|
||||
(defn hide-send [{:keys [actions-ref send-ref sticker-ref]}]
|
||||
(quo.react/set-native-props actions-ref #js {:width nil :left nil})
|
||||
(quo.react/set-native-props send-ref #js {:width 0 :right -100})
|
||||
(quo.react/set-native-props sticker-ref #js {:width nil :right nil}))
|
||||
|
||||
(defn reset-input [refs chat-id]
|
||||
(some-> ^js (react/current-ref (:text-input-ref refs)) .clear)
|
||||
(swap! mentions-enabled update :render not)
|
||||
(swap! input-texts dissoc chat-id))
|
||||
|
||||
(defn clear-input [chat-id refs]
|
||||
(hide-send refs)
|
||||
(if (get @mentions-enabled chat-id)
|
||||
(do
|
||||
(swap! mentions-enabled dissoc chat-id)
|
||||
;;we need this timeout, because if we clear text input and first index was a mention object with blue color,
|
||||
;;after clearing text will be typed with this blue color, so we render white text first and then clear it
|
||||
(js/setTimeout #(reset-input refs chat-id) 50))
|
||||
(reset-input refs chat-id)))
|
||||
|
||||
(defn on-text-change [val chat-id]
|
||||
(swap! input-texts assoc chat-id val)
|
||||
;;we still store it in app-db for mentions, we don't have reactions in views
|
||||
(re-frame/dispatch [:chat.ui/set-chat-input-text val]))
|
||||
|
||||
(defn on-change [last-text-change timeout-id mentionable-users refs chat-id sending-image args]
|
||||
(let [text (.-text ^js (.-nativeEvent ^js args))
|
||||
prev-text (get @input-texts chat-id)]
|
||||
(when (and (seq prev-text) (empty? text) (not sending-image))
|
||||
(hide-send refs))
|
||||
(when (and (empty? prev-text) (seq text))
|
||||
(show-send refs))
|
||||
|
||||
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled assoc chat-id true))
|
||||
|
||||
;; NOTE(rasom): on iOS `on-selection-change` is canceled in case if it
|
||||
;; happens during typing because it is not needed for mention
|
||||
;; suggestions calculation
|
||||
|
@ -116,19 +158,23 @@
|
|||
(utils.utils/clear-timeout @timeout-id))
|
||||
(when platform/android?
|
||||
(reset! last-text-change (js/Date.now)))
|
||||
(on-text-change text)
|
||||
|
||||
(on-text-change text chat-id)
|
||||
;; NOTE(rasom): on iOS `on-change` is dispatched after `on-text-input`,
|
||||
;; that's why mention suggestions are calculated on `on-change`
|
||||
(when platform/ios?
|
||||
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users]))))
|
||||
|
||||
(defn on-text-input [mentionable-users args]
|
||||
(defn on-text-input [mentionable-users chat-id args]
|
||||
(let [native-event (.-nativeEvent ^js args)
|
||||
text (.-text ^js native-event)
|
||||
previous-text (.-previousText ^js native-event)
|
||||
range (.-range ^js native-event)
|
||||
start (.-start ^js range)
|
||||
end (.-end ^js range)]
|
||||
(when (and (not (get @mentions-enabled chat-id)) (string/index-of text "@"))
|
||||
(swap! mentions-enabled assoc chat-id true))
|
||||
|
||||
(re-frame/dispatch
|
||||
[::mentions/on-text-input
|
||||
{:new-text text
|
||||
|
@ -141,14 +187,15 @@
|
|||
(when platform/android?
|
||||
(re-frame/dispatch [::mentions/calculate-suggestions mentionable-users]))))
|
||||
|
||||
(defn text-input
|
||||
[{:keys [cooldown-enabled? input-with-mentions on-text-change set-active-panel text-input-ref]}]
|
||||
(let [mentionable-users @(re-frame/subscribe [:chats/mentionable-users])
|
||||
(defn text-input [{:keys [set-active-panel refs chat-id sending-image]}]
|
||||
(let [cooldown-enabled? @(re-frame/subscribe [:chats/cooldown-enabled?])
|
||||
mentionable-users @(re-frame/subscribe [:chats/mentionable-users])
|
||||
timeout-id (atom nil)
|
||||
last-text-change (atom nil)]
|
||||
last-text-change (atom nil)
|
||||
mentions-enabled (get @mentions-enabled chat-id)]
|
||||
[rn/text-input
|
||||
{:style (styles/text-input)
|
||||
:ref text-input-ref
|
||||
:ref (:text-input-ref refs)
|
||||
:max-font-size-multiplier 1
|
||||
:accessibility-label :chat-message-input
|
||||
:text-align-vertical :center
|
||||
|
@ -165,17 +212,17 @@
|
|||
:underline-color-android :transparent
|
||||
:auto-capitalize :sentences
|
||||
:on-selection-change (partial on-selection-change timeout-id last-text-change mentionable-users)
|
||||
:on-change (partial on-change
|
||||
on-text-change last-text-change timeout-id mentionable-users)
|
||||
:on-text-input (partial on-text-input mentionable-users)}
|
||||
:on-change (partial on-change last-text-change timeout-id mentionable-users refs chat-id sending-image)
|
||||
:on-text-input (partial on-text-input mentionable-users chat-id)}
|
||||
(if mentions-enabled
|
||||
(for [[idx [type text]] (map-indexed
|
||||
(fn [idx item]
|
||||
[idx item])
|
||||
input-with-mentions)]
|
||||
@(re-frame/subscribe [:chat/input-with-mentions]))]
|
||||
^{:key (str idx "_" type "_" text)}
|
||||
[rn/text (when (= type :mention)
|
||||
{:style {:color "#0DA4C9"}})
|
||||
text])]))
|
||||
[rn/text (when (= type :mention) {:style {:color "#0DA4C9"}})
|
||||
text])
|
||||
(get @input-texts chat-id))]))
|
||||
|
||||
(defn mention-item
|
||||
[[public-key {:keys [alias name nickname] :as user}] _ _ text-input-ref]
|
||||
|
@ -211,14 +258,14 @@
|
|||
ens-name?
|
||||
(assoc :subtitle alias))]))
|
||||
|
||||
(def chat-input-height (reagent/atom nil))
|
||||
(def chat-toolbar-height (reagent/atom nil))
|
||||
|
||||
(defn autocomplete-mentions [text-input-ref]
|
||||
(defn autocomplete-mentions [text-input-ref bottom]
|
||||
(let [suggestions @(re-frame/subscribe [:chat/mention-suggestions])]
|
||||
(when (and (seq suggestions) @chat-input-height)
|
||||
(when (seq suggestions)
|
||||
(let [height (+ 16 (* 52 (min 4.5 (count suggestions))))]
|
||||
[rn/view
|
||||
{:style (styles/autocomplete-container @chat-input-height)
|
||||
{:style (styles/autocomplete-container bottom)
|
||||
:accessibility-label :suggestions-list}
|
||||
[rn/view
|
||||
{:style {:height height}}
|
||||
|
@ -231,120 +278,87 @@
|
|||
:render-data text-input-ref
|
||||
:render-fn mention-item}]]]))))
|
||||
|
||||
(defn chat-input
|
||||
[{:keys [set-active-panel active-panel on-send-press reply
|
||||
show-send show-image show-stickers show-extensions
|
||||
sending-image input-focus show-audio]
|
||||
:as props}]
|
||||
[rn/view {:style (styles/toolbar)
|
||||
:on-layout #(reset! chat-input-height
|
||||
(-> ^js % .-nativeEvent .-layout .-height))}
|
||||
[rn/view {:style (styles/actions-wrapper (and (not show-extensions)
|
||||
(not show-image)))}
|
||||
(when show-extensions
|
||||
(defn on-chat-toolbar-layout [^js ev]
|
||||
(reset! chat-toolbar-height (-> ev .-nativeEvent .-layout .-height)))
|
||||
|
||||
(defn focus-input-on-reply [reply had-reply text-input-ref]
|
||||
;;when we show reply we focus input
|
||||
(when-not (= reply @had-reply)
|
||||
(reset! had-reply reply)
|
||||
(when reply
|
||||
(js/setTimeout #(input-focus text-input-ref) 250))))
|
||||
|
||||
(defn reply-message [text-input-ref]
|
||||
(let [had-reply (atom nil)]
|
||||
(fn []
|
||||
(let [reply @(re-frame/subscribe [:chats/reply-message])]
|
||||
(focus-input-on-reply reply had-reply text-input-ref)
|
||||
(when reply
|
||||
[reply/reply-message reply])))))
|
||||
|
||||
(defn send-image []
|
||||
(let [sending-image @(re-frame/subscribe [:chats/sending-image])]
|
||||
(when (seq sending-image)
|
||||
[reply/send-image sending-image])))
|
||||
|
||||
(defn actions [extensions image show-send actions-ref active-panel set-active-panel]
|
||||
[rn/view {:style (styles/actions-wrapper show-send)
|
||||
:ref actions-ref}
|
||||
(when extensions
|
||||
[touchable-icon {:panel :extensions
|
||||
:accessibility-label :show-extensions-icon
|
||||
:active active-panel
|
||||
:set-active set-active-panel}])
|
||||
(when show-image
|
||||
(when image
|
||||
[touchable-icon {:panel :images
|
||||
:accessibility-label :show-photo-icon
|
||||
:active active-panel
|
||||
:set-active set-active-panel}])]
|
||||
[:<>
|
||||
;; NOTE(rasom): on iOS `autocomplete-mentions` should be placed inside
|
||||
;; `chat-input` (otherwise suggestions will be hidden by keyboard) but
|
||||
;; outside animated view below because it adds horizontal margin
|
||||
(when platform/ios?
|
||||
[autocomplete-mentions])
|
||||
[animated/view
|
||||
{:style (styles/input-container)}
|
||||
(when reply
|
||||
[reply/reply-message reply])
|
||||
(when (seq sending-image)
|
||||
[reply/send-image sending-image])
|
||||
[rn/view {:style (styles/input-row)}
|
||||
[text-input props]
|
||||
[rn/view {:style (styles/in-input-buttons)}
|
||||
(when show-send
|
||||
[send-button {:on-send-press on-send-press}])
|
||||
(when show-stickers
|
||||
:set-active set-active-panel}])])
|
||||
|
||||
(defn chat-toolbar []
|
||||
(let [actions-ref (quo.react/create-ref)
|
||||
send-ref (quo.react/create-ref)
|
||||
sticker-ref (quo.react/create-ref)
|
||||
toolbar-options (re-frame/subscribe [:chats/chat-toolbar])]
|
||||
(fn [{:keys [active-panel set-active-panel text-input-ref chat-id]}]
|
||||
(let [;we want to control components on native level, so instead of RN state we set native props via reference
|
||||
;we don't react on input text in this view, @input-texts below is a regular atom
|
||||
refs {:actions-ref actions-ref
|
||||
:send-ref send-ref
|
||||
:sticker-ref sticker-ref
|
||||
:text-input-ref text-input-ref}
|
||||
{:keys [send stickers image extensions audio sending-image]} @toolbar-options
|
||||
show-send (or sending-image (seq (get @input-texts chat-id)))]
|
||||
[rn/view {:style (styles/toolbar)
|
||||
:on-layout on-chat-toolbar-layout}
|
||||
;;EXTENSIONS and IMAGE buttons
|
||||
[actions extensions image show-send actions-ref active-panel set-active-panel]
|
||||
[rn/view {:style (styles/input-container)}
|
||||
[reply-message text-input-ref]
|
||||
[send-image]
|
||||
[rn/view {:style styles/input-row}
|
||||
[text-input {:chat-id chat-id
|
||||
:sending-image sending-image
|
||||
:refs refs
|
||||
:set-active-panel set-active-panel}]
|
||||
;;SEND button
|
||||
[rn/view {:ref send-ref :style (when-not show-send {:width 0 :right -100})}
|
||||
(when send
|
||||
[send-button #(do (clear-input chat-id refs)
|
||||
(re-frame/dispatch [:chat.ui/send-current-message]))])]
|
||||
|
||||
;;STICKERS and AUDIO buttons
|
||||
[rn/view {:style (merge {:flex-direction :row} (when show-send {:width 0 :right -100}))
|
||||
:ref sticker-ref}
|
||||
(when stickers
|
||||
[touchable-stickers-icon {:panel :stickers
|
||||
:accessibility-label :show-stickers-icon
|
||||
:active active-panel
|
||||
:input-focus input-focus
|
||||
:input-focus #(input-focus text-input-ref)
|
||||
:set-active set-active-panel}])
|
||||
(when show-audio
|
||||
(when audio
|
||||
[touchable-audio-icon {:panel :audio
|
||||
:accessibility-label :show-audio-message-icon
|
||||
:active active-panel
|
||||
:input-focus input-focus
|
||||
:set-active set-active-panel}])]]]]])
|
||||
|
||||
(defn chat-toolbar []
|
||||
(let [previous-layout (atom nil)
|
||||
had-reply (atom nil)]
|
||||
(fn [{:keys [active-panel set-active-panel text-input-ref on-text-change]}]
|
||||
(let [disconnected? @(re-frame/subscribe [:disconnected?])
|
||||
{:keys [processing]} @(re-frame/subscribe [:multiaccounts/login])
|
||||
mainnet? @(re-frame/subscribe [:mainnet?])
|
||||
input-text
|
||||
@(re-frame/subscribe [:chats/current-chat-input-text])
|
||||
input-with-mentions
|
||||
@(re-frame/subscribe [:chat/input-with-mentions])
|
||||
cooldown-enabled? @(re-frame/subscribe [:chats/cooldown-enabled?])
|
||||
one-to-one-chat? @(re-frame/subscribe [:current-chat/one-to-one-chat?])
|
||||
{:keys [public?
|
||||
chat-id]} @(re-frame/subscribe [:current-chat/metadata])
|
||||
reply @(re-frame/subscribe [:chats/reply-message])
|
||||
sending-image @(re-frame/subscribe [:chats/sending-image])
|
||||
input-focus (fn []
|
||||
(some-> ^js (react/current-ref text-input-ref) .focus))
|
||||
clear-input (fn []
|
||||
(some-> ^js (react/current-ref text-input-ref) .clear))
|
||||
empty-text (string/blank? (string/trim (or input-text "")))
|
||||
show-send (and (or (not empty-text)
|
||||
sending-image)
|
||||
(not (or processing disconnected?)))
|
||||
show-stickers (and empty-text
|
||||
mainnet?
|
||||
(not sending-image)
|
||||
(not reply))
|
||||
show-image (and empty-text
|
||||
(not reply)
|
||||
(not public?))
|
||||
show-extensions (and empty-text
|
||||
one-to-one-chat?
|
||||
(or config/commands-enabled? mainnet?)
|
||||
(not reply))
|
||||
show-audio (and empty-text
|
||||
(not sending-image)
|
||||
(not reply)
|
||||
(not public?))]
|
||||
(when-not (= reply @had-reply)
|
||||
(reset! had-reply reply)
|
||||
(when reply
|
||||
(js/setTimeout input-focus 250)))
|
||||
(when (and platform/ios? (not= @previous-layout [show-send show-stickers show-extensions show-audio]))
|
||||
(reset! previous-layout [show-send show-stickers show-extensions show-audio])
|
||||
(when (seq @previous-layout)
|
||||
(rn/configure-next
|
||||
(:ease-opacity-200 rn/custom-animations))))
|
||||
[chat-input {:set-active-panel set-active-panel
|
||||
:active-panel active-panel
|
||||
:text-input-ref text-input-ref
|
||||
:input-focus input-focus
|
||||
:reply reply
|
||||
:on-send-press #(do (re-frame/dispatch [:chat.ui/send-current-message])
|
||||
(clear-input))
|
||||
:text-value input-text
|
||||
:input-with-mentions input-with-mentions
|
||||
:on-text-change on-text-change
|
||||
:cooldown-enabled? cooldown-enabled?
|
||||
:show-send show-send
|
||||
:show-stickers show-stickers
|
||||
:show-image show-image
|
||||
:show-audio show-audio
|
||||
:sending-image sending-image
|
||||
:show-extensions show-extensions
|
||||
:chat-id chat-id}]))))
|
||||
:input-focus #(input-focus text-input-ref)
|
||||
:set-active set-active-panel}])]]]]))))
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
:padding-vertical 8
|
||||
:border-top-width 1
|
||||
:border-top-color (:ui-01 @colors/theme)
|
||||
:background-color (:ui-background @colors/theme)
|
||||
:align-items :flex-end
|
||||
:flex-direction :row})
|
||||
|
||||
|
@ -21,8 +20,9 @@
|
|||
:border-bottom-left-radius 16
|
||||
:margin-horizontal 8})
|
||||
|
||||
(defn input-row []
|
||||
(def input-row
|
||||
{:flex-direction :row
|
||||
:overflow :hidden
|
||||
:align-items :flex-end})
|
||||
|
||||
(defn text-input-wrapper []
|
||||
|
@ -41,7 +41,6 @@
|
|||
:min-height 34
|
||||
:max-height 144
|
||||
:margin 0
|
||||
:border-width 0
|
||||
:flex-shrink 1
|
||||
:color (:text-01 @colors/theme)
|
||||
:padding-horizontal 12}
|
||||
|
@ -50,11 +49,13 @@
|
|||
{:padding-top 2
|
||||
:padding-bottom 6})))
|
||||
|
||||
(defn actions-wrapper [invisible]
|
||||
(defn actions-wrapper [show-send]
|
||||
(merge
|
||||
(when show-send
|
||||
{:width 0 :left -88})
|
||||
{:flex-direction :row
|
||||
:padding-left 4
|
||||
:min-height 34
|
||||
:left (if invisible -88 0)})
|
||||
:min-height 34}))
|
||||
|
||||
(defn touchable-icon []
|
||||
{:padding-horizontal 10
|
||||
|
@ -104,11 +105,6 @@
|
|||
:justify-content :center
|
||||
:align-items :center})
|
||||
|
||||
(defn in-input-buttons []
|
||||
{:flex-direction :row
|
||||
:height 34
|
||||
:overflow :hidden})
|
||||
|
||||
(defn send-icon-color []
|
||||
colors/white)
|
||||
|
||||
|
@ -118,6 +114,5 @@
|
|||
:right 0
|
||||
:bottom bottom
|
||||
:background-color (colors/get-color :ui-background)
|
||||
:flex-direction :column
|
||||
:border-top-width 1
|
||||
:border-top-color (colors/get-color :ui-01)})
|
|
@ -30,7 +30,7 @@
|
|||
connected? [:mailserver/connected?]]
|
||||
(let [ids (:ids gaps)]
|
||||
(when-not (and first-gap? might-have-join-time-messages?)
|
||||
[react/view {:style style/gap-container}
|
||||
[react/view {:style (style/gap-container)}
|
||||
[react/touchable-highlight
|
||||
{:on-press (when (and connected? (not in-progress?))
|
||||
(on-press ids first-gap? idx list-ref chat-id))
|
||||
|
|
|
@ -163,6 +163,9 @@
|
|||
|
||||
:else [one-to-one-chat-accents current-chat]))
|
||||
|
||||
(defn current-chat-actions []
|
||||
[actions @(re-frame/subscribe [:chats/current-chat])])
|
||||
|
||||
(defn options [chat-id message-id]
|
||||
(fn []
|
||||
[react/view
|
||||
|
|
|
@ -4,5 +4,11 @@
|
|||
|
||||
(defonce scrolling (atom nil))
|
||||
|
||||
(defn start-scrolling []
|
||||
(reset! scrolling true))
|
||||
|
||||
(defn stop-scrolling []
|
||||
(reset! scrolling false))
|
||||
|
||||
(defn reset-visible-item []
|
||||
(reset! first-not-visible-item nil))
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
(ns status-im.ui.screens.chat.styles.input.gap
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def gap-container
|
||||
(defn gap-container []
|
||||
{:align-self :stretch
|
||||
:margin-top 24
|
||||
:margin-bottom 24
|
||||
|
|
|
@ -31,15 +31,9 @@
|
|||
(i18n/label :chat-is-a-contact)
|
||||
(i18n/label :chat-is-not-a-contact))]]))
|
||||
|
||||
(defn toolbar-content-view [{:keys [group-chat
|
||||
invitation-admin
|
||||
color
|
||||
chat-id
|
||||
contacts
|
||||
chat-type
|
||||
chat-name
|
||||
public?]}]
|
||||
(when chat-id
|
||||
(defn toolbar-content-view []
|
||||
(let [{:keys [group-chat invitation-admin color chat-id contacts chat-type chat-name public?]}
|
||||
@(re-frame/subscribe [:chats/current-chat])]
|
||||
[react/view {:style st/toolbar-container}
|
||||
[react/view {:margin-right 10}
|
||||
[react/touchable-highlight {:on-press #(when-not group-chat (re-frame/dispatch [:chat.ui/show-profile chat-id]))}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
[status-im.ui.screens.chat.image.views :as image]
|
||||
[status-im.ui.screens.chat.state :as state]
|
||||
[status-im.ui.screens.chat.extensions.views :as extensions]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.chat.group :as chat.group]
|
||||
[status-im.ui.screens.chat.message.gap :as gap]
|
||||
[status-im.ui.components.invite.chat :as invite.chat]
|
||||
|
@ -32,18 +31,28 @@
|
|||
[clojure.string :as string]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[status-im.utils.utils :as utils]
|
||||
[quo.design-system.colors :as quo.colors]))
|
||||
|
||||
(defn topbar [current-chat]
|
||||
[topbar/topbar
|
||||
{:content [toolbar-content/toolbar-content-view current-chat]
|
||||
:navigation {:on-press #(re-frame/dispatch [:close-chat (:chat-id current-chat)])}
|
||||
:right-accessories [{:icon :main-icons/more
|
||||
:accessibility-label :chat-menu-button
|
||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
(defn topbar []
|
||||
;;we don't use topbar component, because we want chat view as simple (fast) as possible
|
||||
[react/view {:height 56 :border-bottom-width 1 :border-bottom-color (:ui-01 @quo.colors/theme)}
|
||||
[react/touchable-highlight {:on-press-in #(re-frame/dispatch [:close-chat])
|
||||
:accessibility-label :back-button
|
||||
:style {:height 56 :width 40 :align-items :center :justify-content :center
|
||||
:padding-left 16}}
|
||||
[icons/icon :main-icons/arrow-left]]
|
||||
[react/view {:flex 1 :left 52 :right 52 :top 0 :bottom 0 :position :absolute}
|
||||
[toolbar-content/toolbar-content-view]]
|
||||
[react/touchable-highlight {:on-press-in #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[sheets/actions current-chat])
|
||||
:height 256}])}]}])
|
||||
[sheets/current-chat-actions])
|
||||
:height 256}])
|
||||
:accessibility-label :chat-menu-button
|
||||
:style {:right 0 :top 0 :bottom 0 :position :absolute
|
||||
:height 56 :width 40 :align-items :center :justify-content :center
|
||||
:padding-right 16}}
|
||||
[icons/icon :main-icons/more]]])
|
||||
|
||||
(defn invitation-requests [chat-id admins]
|
||||
(let [current-pk @(re-frame/subscribe [:multiaccount/public-key])
|
||||
|
@ -59,8 +68,7 @@
|
|||
(i18n/label :t/group-membership-request)]]])))))
|
||||
|
||||
(defn add-contact-bar [public-key]
|
||||
(let [added? @(re-frame/subscribe [:contacts/contact-added? public-key])]
|
||||
(when-not added?
|
||||
(when-not @(re-frame/subscribe [:contacts/contact-added? public-key])
|
||||
[react/touchable-highlight
|
||||
{:on-press
|
||||
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||
|
@ -68,7 +76,7 @@
|
|||
[react/view {:style (style/add-contact)}
|
||||
[icons/icon :main-icons/add
|
||||
{:color colors/blue}]
|
||||
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]])))
|
||||
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]]))
|
||||
|
||||
(defn chat-intro [{:keys [chat-id
|
||||
chat-name
|
||||
|
@ -114,7 +122,6 @@
|
|||
(defn chat-intro-header-container
|
||||
[{:keys [group-chat invitation-admin
|
||||
chat-type
|
||||
might-have-join-time-messages?
|
||||
color chat-id chat-name
|
||||
public?]}
|
||||
no-messages]
|
||||
|
@ -131,7 +138,7 @@
|
|||
:chat-name chat-name
|
||||
:public? public?
|
||||
:color color
|
||||
:loading-messages? might-have-join-time-messages?
|
||||
:loading-messages? @(re-frame/subscribe [:chats/might-have-join-time-messages? chat-id])
|
||||
:no-messages? no-messages}]
|
||||
(if group-chat
|
||||
[chat-intro opts]
|
||||
|
@ -233,6 +240,7 @@
|
|||
(let [loading-messages? @(re-frame/subscribe [:chats/loading-messages? chat-id])
|
||||
no-messages? @(re-frame/subscribe [:chats/chat-no-messages? chat-id])
|
||||
all-loaded? @(re-frame/subscribe [:chats/all-loaded? chat-id])]
|
||||
(println "LIST FOOTER" (or loading-messages? (not chat-id) (not all-loaded?)))
|
||||
[react/view {:style (when platform/android? {:scaleY -1})}
|
||||
(if (or loading-messages? (not chat-id) (not all-loaded?))
|
||||
[react/view {:height 324 :align-items :center :justify-content :center}
|
||||
|
@ -265,16 +273,28 @@
|
|||
:show-input? show-input?)
|
||||
space-keeper]))])
|
||||
|
||||
(defn messages-view
|
||||
[{:keys [chat bottom-space pan-responder space-keeper show-input?]}]
|
||||
(def list-key-fn #(or (:message-id %) (:value %)))
|
||||
(def list-ref #(reset! messages-list-ref %))
|
||||
|
||||
;;TODO this is not really working in pair with inserting new messages because we stop inserting new messages
|
||||
;;if they outside the viewarea, but we load more here because end is reached,so its slowdown UI because we
|
||||
;;load and render 20 messages more, but we can't prevent this , because otherwise :on-end-reached will work wrong
|
||||
(defn list-on-end-reached []
|
||||
(if @state/scrolling
|
||||
(re-frame/dispatch [:chat.ui/load-more-messages-for-current-chat])
|
||||
(utils/set-timeout #(re-frame/dispatch [:chat.ui/load-more-messages-for-current-chat])
|
||||
(if platform/low-device? 700 200))))
|
||||
|
||||
(defn messages-view [{:keys [chat bottom-space pan-responder space-keeper show-input?]}]
|
||||
(let [{:keys [group-chat chat-id public?]} chat
|
||||
messages @(re-frame/subscribe [:chats/chat-messages-stream chat-id])
|
||||
current-public-key @(re-frame/subscribe [:multiaccount/public-key])]
|
||||
;;do not use anonymous functions for handlers
|
||||
[list/flat-list
|
||||
(merge
|
||||
pan-responder
|
||||
{:key-fn #(or (:message-id %) (:value %))
|
||||
:ref #(reset! messages-list-ref %)
|
||||
{:key-fn list-key-fn
|
||||
:ref list-ref
|
||||
:header [list-header chat]
|
||||
:footer [list-footer chat]
|
||||
:data messages
|
||||
|
@ -286,23 +306,15 @@
|
|||
:show-input? show-input?}
|
||||
:render-fn render-fn
|
||||
:on-viewable-items-changed on-viewable-items-changed
|
||||
;;TODO this is not really working in pair with inserting new messages because we stop inserting new messages
|
||||
;;if they outside the viewarea, but we load more here because end is reached,so its slowdown UI because we
|
||||
;;load and render 20 messages more, but we can't prevent this , because otherwise :on-end-reached will work wrong
|
||||
:on-end-reached (fn []
|
||||
(if @state/scrolling
|
||||
(re-frame/dispatch [:chat.ui/load-more-messages chat-id])
|
||||
(utils/set-timeout #(re-frame/dispatch [:chat.ui/load-more-messages chat-id])
|
||||
(if platform/low-device? 500 200))))
|
||||
|
||||
:on-scroll-to-index-failed #() ;;don't remove this
|
||||
:on-end-reached list-on-end-reached
|
||||
:on-scroll-to-index-failed identity ;;don't remove this
|
||||
:content-container-style {:padding-top (+ bottom-space 16)
|
||||
:padding-bottom 16}
|
||||
:scroll-indicator-insets {:top bottom-space} ;;ios only
|
||||
:keyboard-dismiss-mode :interactive
|
||||
:keyboard-should-persist-taps :handled
|
||||
:onMomentumScrollBegin #(reset! state/scrolling true)
|
||||
:onMomentumScrollEnd #(reset! state/scrolling false)
|
||||
:onMomentumScrollBegin state/start-scrolling
|
||||
:onMomentumScrollEnd state/stop-scrolling
|
||||
;;TODO https://github.com/facebook/react-native/issues/30034
|
||||
:inverted (when platform/ios? true)
|
||||
:style (when platform/android? {:scaleY -1})})]))
|
||||
|
@ -318,43 +330,39 @@
|
|||
pan-responder (accessory/create-pan-responder position-y pan-state)
|
||||
space-keeper (get-space-keeper-ios bottom-space panel-space active-panel text-input-ref)
|
||||
set-active-panel (get-set-active-panel active-panel)
|
||||
on-text-change #(re-frame/dispatch [:chat.ui/set-chat-input-text %])]
|
||||
on-close #(set-active-panel nil)]
|
||||
(fn []
|
||||
(let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as current-chat}
|
||||
@(re-frame/subscribe [:chats/current-chat])]
|
||||
(let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as chat}
|
||||
;;we want to react only on these fields, do not use full chat map here
|
||||
@(re-frame/subscribe [:chats/current-chat-chat-view])
|
||||
max-bottom-space (max @bottom-space @panel-space)]
|
||||
[:<>
|
||||
[topbar]
|
||||
[connectivity/loading-indicator]
|
||||
[topbar current-chat]
|
||||
[:<>
|
||||
(when current-chat
|
||||
(when chat-id
|
||||
(if group-chat
|
||||
[invitation-requests chat-id admins]
|
||||
[add-contact-bar chat-id]))
|
||||
;;MESSAGES LIST
|
||||
[messages-view {:chat current-chat
|
||||
:bottom-space (max @bottom-space @panel-space)
|
||||
[messages-view {:chat chat
|
||||
:bottom-space max-bottom-space
|
||||
:pan-responder pan-responder
|
||||
:space-keeper space-keeper
|
||||
:show-input? show-input?}]]
|
||||
:show-input? show-input?}]
|
||||
(when (and group-chat invitation-admin)
|
||||
[accessory/view {:y position-y
|
||||
:on-update-inset on-update}
|
||||
[invitation-bar chat-id]])
|
||||
;; NOTE(rasom): on android we have to place `autocomplete-mentions`
|
||||
;; outside `accessory/view` because otherwise :keyboardShouldPersistTaps
|
||||
;; :always doesn't work and keyboard is hidden on pressing suggestion.
|
||||
;; Scrolling of suggestions doesn't work neither in this case.
|
||||
(when platform/android?
|
||||
[components/autocomplete-mentions text-input-ref])
|
||||
[components/autocomplete-mentions text-input-ref max-bottom-space]
|
||||
(when show-input?
|
||||
[accessory/view {:y position-y
|
||||
:pan-state pan-state
|
||||
:has-panel (boolean @active-panel)
|
||||
:on-close #(set-active-panel nil)
|
||||
:on-close on-close
|
||||
:on-update-inset on-update}
|
||||
[components/chat-toolbar
|
||||
{:active-panel @active-panel
|
||||
{:chat-id chat-id
|
||||
:active-panel @active-panel
|
||||
:set-active-panel set-active-panel
|
||||
:text-input-ref text-input-ref
|
||||
:on-text-change on-text-change}]
|
||||
:text-input-ref text-input-ref}]
|
||||
[bottom-sheet @active-panel]])]))))
|
||||
|
|
|
@ -152,6 +152,8 @@
|
|||
[communities.views/community-home-list-item home-item]))
|
||||
|
||||
(defn communities-and-chats [items loading? search-filter hide-home-tooltip?]
|
||||
[:<>
|
||||
[connectivity/loading-indicator]
|
||||
(if loading?
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/activity-indicator {:animating true}]]
|
||||
|
@ -161,7 +163,7 @@
|
|||
(not @search-active?))
|
||||
[welcome-blank-page]
|
||||
[list/flat-list
|
||||
{:key-fn :chat-id
|
||||
{:key-fn #(or (:chat-id %) (:id %))
|
||||
:keyboard-should-persist-taps :always
|
||||
:data items
|
||||
:render-fn render-fn
|
||||
|
@ -174,7 +176,7 @@
|
|||
[start-suggestion search-filter])]
|
||||
:footer (if (and (not hide-home-tooltip?) (not @search-active?))
|
||||
[home-tooltip-view]
|
||||
[react/view {:height 68}])}])))
|
||||
[react/view {:height 68}])}]))])
|
||||
|
||||
(views/defview chats-list []
|
||||
(views/letsubs [loading? [:chats/loading?]
|
||||
|
@ -196,6 +198,5 @@
|
|||
[topbar/topbar {:title (i18n/label :t/chat)
|
||||
:navigation :none
|
||||
:right-component [connectivity/connectivity-button]}]
|
||||
[connectivity/loading-indicator]
|
||||
[chats-list]
|
||||
[plus-button]])
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
[status-im.ui.screens.bottom-sheets.views :as bottom-sheets]
|
||||
[status-im.utils.config :as config]
|
||||
[status-im.reloader :as reloader]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
["react-native" :as rn]
|
||||
["react-native-languages" :default react-native-languages]
|
||||
|
@ -60,25 +59,9 @@
|
|||
(reagent/create-class
|
||||
{:component-did-mount
|
||||
(fn [_]
|
||||
(.addListener ^js react/keyboard
|
||||
(if platform/ios?
|
||||
"keyboardWillShow"
|
||||
"keyboardDidShow")
|
||||
(fn [^js e]
|
||||
(let [h (.. e -endCoordinates -height)]
|
||||
(re-frame/dispatch-sync [:set :keyboard-height h])
|
||||
(re-frame/dispatch-sync [:set :keyboard-max-height h]))))
|
||||
(.addListener ^js react/keyboard
|
||||
(if platform/ios?
|
||||
"keyboardWillHide"
|
||||
"keyboardDidHide")
|
||||
(fn [_]
|
||||
(re-frame/dispatch-sync [:set :keyboard-height 0])))
|
||||
(.addEventListener ^js react/app-state "change" app-state-change-handler)
|
||||
(.addEventListener react-native-languages "change" on-languages-change)
|
||||
(.addEventListener react-native-shake
|
||||
"ShakeEvent"
|
||||
on-shake)
|
||||
(.addEventListener react-native-shake "ShakeEvent" on-shake)
|
||||
(.hide ^js splash-screen)
|
||||
(utils.universal-links/initialize))
|
||||
:component-will-unmount
|
||||
|
|
|
@ -108,21 +108,15 @@
|
|||
:font-size 15 :line-height 22}}
|
||||
(str (i18n/format-currency (* amount price) (:code wallet-currency)) " " (:code wallet-currency))])))
|
||||
|
||||
(views/defview select-account-sheet [{:keys [from message]}]
|
||||
(views/letsubs [window-height [:dimensions/window-height]
|
||||
keyboard-height [:keyboard-height]]
|
||||
(let [small-screen? (< (- window-height keyboard-height) 450)]
|
||||
(defn select-account-sheet [{:keys [from message]}]
|
||||
[react/view {:style (styles/acc-sheet)}
|
||||
[header {:small-screen? small-screen?
|
||||
[header {:small-screen? false
|
||||
:label :t/select-account}]
|
||||
[react/view {:flex-direction :row :padding-horizontal 24 :align-items :center
|
||||
:margin-vertical (if small-screen? 8 16)}]
|
||||
(when-not small-screen?
|
||||
:margin-vertical 16}]
|
||||
[quo/list-header
|
||||
(i18n/label :t/from)])
|
||||
(i18n/label :t/from)]
|
||||
[react/view {:flex-direction :row :flex 1 :align-items :center}
|
||||
(when small-screen?
|
||||
[react/i18n-text {:style {:width 50 :text-align :right :color colors/gray} :key :t/from}])
|
||||
[react/view {:flex 1}
|
||||
[render-account from nil ::commands/set-selected-account]]]
|
||||
[toolbar/toolbar
|
||||
|
@ -140,7 +134,7 @@
|
|||
[::commands/accept-request-address-for-transaction
|
||||
(:message-id message)
|
||||
(:address from)])}
|
||||
(i18n/label :t/share)]}]])))
|
||||
(i18n/label :t/share)]}]])
|
||||
|
||||
(defview select-account []
|
||||
(letsubs [data [:commands/select-account]]
|
||||
|
|
|
@ -60,8 +60,6 @@
|
|||
;; TODO: Add message explaining db export
|
||||
(let [db-json (types/clj->json (select-keys db [:app-state
|
||||
:current-chat-id
|
||||
:keyboard-height
|
||||
:keyboard-max-height
|
||||
:network
|
||||
:network-status
|
||||
:peers-count
|
||||
|
|
Loading…
Reference in New Issue