From 3de7c37d909c1e5fc0155849d940f5f0b4084110 Mon Sep 17 00:00:00 2001 From: andrey Date: Wed, 17 Mar 2021 08:44:36 +0100 Subject: [PATCH] chat input performance improvements Signed-off-by: andrey --- src/quo/components/text_input.cljs | 5 - src/quo/react.cljs | 4 + src/status_im/chat/models.cljs | 13 +- src/status_im/chat/models/input.cljs | 2 +- src/status_im/chat/models/loading.cljs | 5 + src/status_im/chat/models/mentions.cljs | 29 +- src/status_im/db.cljs | 3 +- src/status_im/subs.cljs | 45 ++- .../ui/components/connectivity/view.cljs | 35 +- src/status_im/ui/screens/browser/views.cljs | 2 +- .../ui/screens/chat/audio_message/views.cljs | 20 +- .../ui/screens/chat/components/input.cljs | 346 +++++++++--------- .../ui/screens/chat/components/style.cljs | 37 +- .../ui/screens/chat/message/gap.cljs | 2 +- src/status_im/ui/screens/chat/sheets.cljs | 3 + src/status_im/ui/screens/chat/state.cljs | 6 + .../ui/screens/chat/styles/input/gap.cljs | 2 +- .../ui/screens/chat/toolbar_content.cljs | 12 +- src/status_im/ui/screens/chat/views.cljs | 156 ++++---- src/status_im/ui/screens/home/views.cljs | 49 +-- src/status_im/ui/screens/views.cljs | 19 +- .../ui/screens/wallet/send/views.cljs | 60 ++- src/status_im/utils/logging/core.cljs | 2 - 23 files changed, 442 insertions(+), 415 deletions(-) diff --git a/src/quo/components/text_input.cljs b/src/quo/components/text_input.cljs index c7afc1cd15..63bdf8f269 100644 --- a/src/quo/components/text_input.cljs +++ b/src/quo/components/text_input.cljs @@ -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 diff --git a/src/quo/react.cljs b/src/quo/react.cljs index caf98b52af..d9fb9e7878 100644 --- a/src/quo/react.cljs +++ b/src/quo/react.cljs @@ -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)) diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index 70991918b4..00cc69559f 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -238,12 +238,13 @@ (fx/defn close-chat {:events [:close-chat]} - [{:keys [db] :as cofx} chat-id] - (chat.state/reset-visible-item) - (fx/merge cofx - {:db (dissoc db :current-chat-id)} - (offload-messages chat-id) - (navigation/navigate-back))) + [{: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)))) (fx/defn remove-chat "Removes chat completely from app, producing all necessary effects for that" diff --git a/src/status_im/chat/models/input.cljs b/src/status_im/chat/models/input.cljs index 4df25bd34a..b6e1115a18 100644 --- a/src/status_im/chat/models/input.cljs +++ b/src/status_im/chat/models/input.cljs @@ -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 diff --git a/src/status_im/chat/models/loading.cljs b/src/status_im/chat/models/loading.cljs index 5907e7c133..cf312cc9e2 100644 --- a/src/status_im/chat/models/loading.cljs +++ b/src/status_im/chat/models/loading.cljs @@ -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?]) diff --git a/src/status_im/chat/models/mentions.cljs b/src/status_im/chat/models/mentions.cljs index fcaec1797f..c406c2566f 100644 --- a/src/status_im/chat/models/mentions.cljs +++ b/src/status_im/chat/models/mentions.cljs @@ -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 diff --git a/src/status_im/db.cljs b/src/status_im/db.cljs index 1b79b9b3dd..c392e9eac5 100644 --- a/src/status_im/db.cljs +++ b/src/status_im/db.cljs @@ -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 {} diff --git a/src/status_im/subs.cljs b/src/status_im/subs.cljs index 278c6f3391..366c66b210 100644 --- a/src/status_im/subs.cljs +++ b/src/status_im/subs.cljs @@ -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] diff --git a/src/status_im/ui/components/connectivity/view.cljs b/src/status_im/ui/components/connectivity/view.cljs index 29fc961578..964f46ad8d 100644 --- a/src/status_im/ui/components/connectivity/view.cljs +++ b/src/status_im/ui/components/connectivity/view.cljs @@ -49,26 +49,27 @@ (animation/parallel [(animation/timing blue-bar-left-margin (easing :out 0)) (animation/timing white-bar-left-margin (easing :out 0))])]))))} - [react/view {:style {:width parent-width - :position :absolute - :top -3 - :z-index 3 - :height 3 - :background-color colors/white} - :accessibility-label :loading-indicator} - [react/animated-view {:style (animated-bar-style blue-bar-left-margin - parent-width - colors/blue)}] - [react/animated-view {:style (assoc (animated-bar-style white-bar-left-margin - parent-width - colors/white) - :left (* 0.15 parent-width))}]])) + [react/view + [react/view {:style {:width parent-width + :position :absolute + :top -3 + :z-index 3 + :height 3 + :background-color colors/white} + :accessibility-label :loading-indicator} + [react/animated-view {:style (animated-bar-style blue-bar-left-margin + parent-width + colors/blue)}] + [react/animated-view {:style (assoc (animated-bar-style white-bar-left-margin + parent-width + colors/white) + :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]) diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs index 76623d5a4d..446edac718 100644 --- a/src/status_im/ui/screens/browser/views.cljs +++ b/src/status_im/ui/screens/browser/views.cljs @@ -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? diff --git a/src/status_im/ui/screens/chat/audio_message/views.cljs b/src/status_im/ui/screens/chat/audio_message/views.cljs index aaa5d95c5b..daf6d0ef90 100644 --- a/src/status_im/ui/screens/chat/audio_message/views.cljs +++ b/src/status_im/ui/screens/chat/audio_message/views.cljs @@ -281,14 +281,14 @@ [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 - (= :ready-to-send (:general @state)) - (do - (reset-timer timer) - (animate-buttons false false base-params) - (send-audio-msessage state)) + [input/send-button (fn [] (cond + (= :ready-to-send (:general @state)) + (do + (reset-timer timer) + (animate-buttons false false base-params) + (send-audio-msessage state)) - (#{:recording :recording-paused} (:general @state)) - (stop-recording (merge base-params - {:on-success - #(send-audio-msessage state)}))))}]]]]))) + (#{:recording :recording-paused} (:general @state)) + (stop-recording (merge base-params + {:on-success + #(send-audio-msessage state)}))))]]]]))) diff --git a/src/status_im/ui/screens/chat/components/input.cljs b/src/status_im/ui/screens/chat/components/input.cljs index 962ebed804..3791431c64 100644 --- a/src/status_im/ui/screens/chat/components/input.cljs +++ b/src/status_im/ui/screens/chat/components/input.cljs @@ -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) @@ -81,8 +81,8 @@ (defn on-selection-change [timeout-id last-text-change mentionable-users args] (let [selection (.-selection ^js (.-nativeEvent ^js args)) - start (.-start selection) - end (.-end selection)] + start (.-start selection) + end (.-end selection)] ;; NOTE(rasom): on iOS we do not dispatch this event immediately ;; because it is needed only in case if selection is changed without ;; typing. Timeout might be canceled on `on-change`. @@ -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] - (let [native-event (.-nativeEvent ^js args) - text (.-text ^js native-event) +(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)] + 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]) - timeout-id (atom nil) - last-text-change (atom nil)] +(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) + 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,45 +212,45 @@ :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)} - (for [[idx [type text]] (map-indexed - (fn [idx item] - [idx item]) - input-with-mentions)] - ^{:key (str idx "_" type "_" text)} - [rn/text (when (= type :mention) - {:style {:color "#0DA4C9"}}) - text])])) + :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]) + @(re-frame/subscribe [:chat/input-with-mentions]))] + ^{:key (str idx "_" type "_" 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] (let [ens-name? (not= alias name)] [list-item/list-item - (cond-> {:icon [photos/member-photo public-key] - :size :small - :text-size :small + (cond-> {:icon [photos/member-photo public-key] + :size :small + :text-size :small :title [text/text - {:weight :medium - :ellipsize-mode :tail - :number-of-lines 1 - :size :small} + {:weight :medium + :ellipsize-mode :tail + :number-of-lines 1 + :size :small} (if nickname nickname name) (when nickname [text/text - {:weight :regular - :color :secondary - :ellipsize-mode :tail - :size :small} + {:weight :regular + :color :secondary + :ellipsize-mode :tail + :size :small} " " (when ens-name? "@") name])] - :title-text-weight :medium + :title-text-weight :medium :on-press (fn [] (re-frame/dispatch [:chat.ui/select-mention text-input-ref user]))} @@ -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 - [touchable-icon {:panel :extensions - :accessibility-label :show-extensions-icon - :active active-panel - :set-active set-active-panel}]) - (when show-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 - [touchable-stickers-icon {:panel :stickers - :accessibility-label :show-stickers-icon - :active active-panel - :input-focus input-focus - :set-active set-active-panel}]) - (when show-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 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 image + [touchable-icon {:panel :images + :accessibility-label :show-photo-icon + :active active-panel + :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}])))) + (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 text-input-ref) + :set-active set-active-panel}]) + (when audio + [touchable-audio-icon {:panel :audio + :accessibility-label :show-audio-message-icon + :active active-panel + :input-focus #(input-focus text-input-ref) + :set-active set-active-panel}])]]]])))) diff --git a/src/status_im/ui/screens/chat/components/style.cljs b/src/status_im/ui/screens/chat/components/style.cljs index 63d32decd9..5ee6365864 100644 --- a/src/status_im/ui/screens/chat/components/style.cljs +++ b/src/status_im/ui/screens/chat/components/style.cljs @@ -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] - {:flex-direction :row - :padding-left 4 - :min-height 34 - :left (if invisible -88 0)}) +(defn actions-wrapper [show-send] + (merge + (when show-send + {:width 0 :left -88}) + {:flex-direction :row + :padding-left 4 + :min-height 34})) (defn touchable-icon [] {:padding-horizontal 10 @@ -97,17 +98,12 @@ :margin-horizontal 5}) (defn send-message-container [] - {:background-color (:interactive-01 @colors/theme) - :width 26 - :height 26 - :border-radius 13 - :justify-content :center - :align-items :center}) - -(defn in-input-buttons [] - {:flex-direction :row - :height 34 - :overflow :hidden}) + {:background-color (:interactive-01 @colors/theme) + :width 26 + :height 26 + :border-radius 13 + :justify-content :center + :align-items :center}) (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)}) + :border-top-color (colors/get-color :ui-01)}) \ No newline at end of file diff --git a/src/status_im/ui/screens/chat/message/gap.cljs b/src/status_im/ui/screens/chat/message/gap.cljs index 35f4856e49..7b9720ac9b 100644 --- a/src/status_im/ui/screens/chat/message/gap.cljs +++ b/src/status_im/ui/screens/chat/message/gap.cljs @@ -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)) diff --git a/src/status_im/ui/screens/chat/sheets.cljs b/src/status_im/ui/screens/chat/sheets.cljs index de6f85e96d..0191f773d2 100644 --- a/src/status_im/ui/screens/chat/sheets.cljs +++ b/src/status_im/ui/screens/chat/sheets.cljs @@ -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 diff --git a/src/status_im/ui/screens/chat/state.cljs b/src/status_im/ui/screens/chat/state.cljs index 081641b4f2..3ed3b20039 100644 --- a/src/status_im/ui/screens/chat/state.cljs +++ b/src/status_im/ui/screens/chat/state.cljs @@ -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)) diff --git a/src/status_im/ui/screens/chat/styles/input/gap.cljs b/src/status_im/ui/screens/chat/styles/input/gap.cljs index 95587ae499..8a5a32cc76 100644 --- a/src/status_im/ui/screens/chat/styles/input/gap.cljs +++ b/src/status_im/ui/screens/chat/styles/input/gap.cljs @@ -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 diff --git a/src/status_im/ui/screens/chat/toolbar_content.cljs b/src/status_im/ui/screens/chat/toolbar_content.cljs index 2c232f93bf..de17f6a8c3 100644 --- a/src/status_im/ui/screens/chat/toolbar_content.cljs +++ b/src/status_im/ui/screens/chat/toolbar_content.cljs @@ -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]))} diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index 1dae7db6d6..aa679bc47b 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -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 - {:content (fn [] - [sheets/actions current-chat]) - :height 256}])}]}]) +(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/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,16 +68,15 @@ (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? - [react/touchable-highlight - {:on-press - #(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key]) - :accessibility-label :add-to-contacts-button} - [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}]]]))) + (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]) + :accessibility-label :add-to-contacts-button} + [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}]]])) (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,75 +306,63 @@ :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})})])) (defn chat [] - (let [bottom-space (reagent/atom 0) - panel-space (reagent/atom 52) - active-panel (reagent/atom nil) - position-y (animated/value 0) - pan-state (animated/value 0) + (let [bottom-space (reagent/atom 0) + panel-space (reagent/atom 52) + active-panel (reagent/atom nil) + position-y (animated/value 0) + pan-state (animated/value 0) text-input-ref (quo.react/create-ref) - on-update #(when-not (zero? %) (reset! panel-space %)) - 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) + on-update #(when-not (zero? %) (reset! panel-space %)) + 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 - (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) - :pan-responder pan-responder - :space-keeper space-keeper - :show-input? show-input?}]] + (when chat-id + (if group-chat + [invitation-requests chat-id admins] + [add-contact-bar chat-id])) + ;;MESSAGES LIST + [messages-view {:chat chat + :bottom-space max-bottom-space + :pan-responder pan-responder + :space-keeper space-keeper + :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 - :set-active-panel set-active-panel - :text-input-ref text-input-ref - :on-text-change on-text-change}] + {:chat-id chat-id + :active-panel @active-panel + :set-active-panel set-active-panel + :text-input-ref text-input-ref}] [bottom-sheet @active-panel]])])))) diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 9ba629279e..1be75f41bb 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -152,29 +152,31 @@ [communities.views/community-home-list-item home-item])) (defn communities-and-chats [items loading? search-filter hide-home-tooltip?] - (if loading? - [react/view {:flex 1 :align-items :center :justify-content :center} - [react/activity-indicator {:animating true}]] - (if (and (empty? items) - (empty? search-filter) - hide-home-tooltip? - (not @search-active?)) - [welcome-blank-page] - [list/flat-list - {:key-fn :chat-id - :keyboard-should-persist-taps :always - :data items - :render-fn render-fn - :header [:<> - (when (or (seq items) @search-active? (seq search-filter)) - [search-input-wrapper search-filter items]) - [referral-item/list-item] - (when (and (empty? items) - (or @search-active? (seq search-filter))) - [start-suggestion search-filter])] - :footer (if (and (not hide-home-tooltip?) (not @search-active?)) - [home-tooltip-view] - [react/view {:height 68}])}]))) + [:<> + [connectivity/loading-indicator] + (if loading? + [react/view {:flex 1 :align-items :center :justify-content :center} + [react/activity-indicator {:animating true}]] + (if (and (empty? items) + (empty? search-filter) + hide-home-tooltip? + (not @search-active?)) + [welcome-blank-page] + [list/flat-list + {:key-fn #(or (:chat-id %) (:id %)) + :keyboard-should-persist-taps :always + :data items + :render-fn render-fn + :header [:<> + (when (or (seq items) @search-active? (seq search-filter)) + [search-input-wrapper search-filter items]) + [referral-item/list-item] + (when (and (empty? items) + (or @search-active? (seq search-filter))) + [start-suggestion search-filter])] + :footer (if (and (not hide-home-tooltip?) (not @search-active?)) + [home-tooltip-view] + [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]]) diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 409cad7ff8..855684fcea 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -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 diff --git a/src/status_im/ui/screens/wallet/send/views.cljs b/src/status_im/ui/screens/wallet/send/views.cljs index 092f43936e..3a020fc01c 100644 --- a/src/status_im/ui/screens/wallet/send/views.cljs +++ b/src/status_im/ui/screens/wallet/send/views.cljs @@ -108,39 +108,33 @@ :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)] - [react/view {:style (styles/acc-sheet)} - [header {:small-screen? small-screen? - :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? - [quo/list-header - (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 - {:left - [react/view {:padding-horizontal 8} - [quo/button - {:type :secondary - :on-press #(re-frame/dispatch [:set :commands/select-account nil])} - (i18n/label :t/cancel)]] - :right - [quo/button - {:accessibility-label :select-account-bottom-sheet - :disabled (nil? from) - :on-press #(re-frame/dispatch - [::commands/accept-request-address-for-transaction - (:message-id message) - (:address from)])} - (i18n/label :t/share)]}]]))) +(defn select-account-sheet [{:keys [from message]}] + [react/view {:style (styles/acc-sheet)} + [header {:small-screen? false + :label :t/select-account}] + [react/view {:flex-direction :row :padding-horizontal 24 :align-items :center + :margin-vertical 16}] + [quo/list-header + (i18n/label :t/from)] + [react/view {:flex-direction :row :flex 1 :align-items :center} + [react/view {:flex 1} + [render-account from nil ::commands/set-selected-account]]] + [toolbar/toolbar + {:left + [react/view {:padding-horizontal 8} + [quo/button + {:type :secondary + :on-press #(re-frame/dispatch [:set :commands/select-account nil])} + (i18n/label :t/cancel)]] + :right + [quo/button + {:accessibility-label :select-account-bottom-sheet + :disabled (nil? from) + :on-press #(re-frame/dispatch + [::commands/accept-request-address-for-transaction + (:message-id message) + (:address from)])} + (i18n/label :t/share)]}]]) (defview select-account [] (letsubs [data [:commands/select-account]] diff --git a/src/status_im/utils/logging/core.cljs b/src/status_im/utils/logging/core.cljs index b97787f95a..9fcaaa9bd8 100644 --- a/src/status_im/utils/logging/core.cljs +++ b/src/status_im/utils/logging/core.cljs @@ -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