diff --git a/src/js/worklets/shell/constants.js b/src/js/worklets/shell/constants.js index 66edfacacf..c69f57ce89 100644 --- a/src/js/worklets/shell/constants.js +++ b/src/js/worklets/shell/constants.js @@ -1,18 +1,18 @@ import { Easing } from 'react-native-reanimated'; // Home Stack States -export const CLOSE_WITH_ANIMATION = 0; -export const OPEN_WITH_ANIMATION = 1; -export const CLOSE_WITHOUT_ANIMATION = 2; -export const OPEN_WITHOUT_ANIMATION = 3; +export const CLOSE_WITHOUT_ANIMATION = 0; +export const OPEN_WITHOUT_ANIMATION = 1; +export const CLOSE_WITH_ANIMATION = 2; +export const OPEN_WITH_ANIMATION = 3; // Floating Screen States -export const CLOSE_SCREEN_WITH_SLIDE_ANIMATION = 0; -export const OPEN_SCREEN_WITH_SLIDE_ANIMATION = 1; -export const CLOSE_SCREEN_WITH_SHELL_ANIMATION = 2; -export const OPEN_SCREEN_WITH_SHELL_ANIMATION = 3; -export const CLOSE_SCREEN_WITHOUT_ANIMATION = 4; -export const OPEN_SCREEN_WITHOUT_ANIMATION = 5; +export const CLOSE_SCREEN_WITHOUT_ANIMATION = 0; +export const OPEN_SCREEN_WITHOUT_ANIMATION = 1; +export const CLOSE_SCREEN_WITH_SLIDE_ANIMATION = 2; +export const OPEN_SCREEN_WITH_SLIDE_ANIMATION = 3; +export const CLOSE_SCREEN_WITH_SHELL_ANIMATION = 4; +export const OPEN_SCREEN_WITH_SHELL_ANIMATION = 5; export const SHELL_ANIMATION_TIME = 200; diff --git a/src/quo2/components/loaders/skeleton/view.cljs b/src/quo2/components/loaders/skeleton/view.cljs index f8abdef727..01bfaa86d3 100644 --- a/src/quo2/components/loaders/skeleton/view.cljs +++ b/src/quo2/components/loaders/skeleton/view.cljs @@ -31,8 +31,8 @@ (defn- internal-view [{:keys [content theme blur? parent-height]}] - (let [number-of-skeletons (int (Math/floor (/ parent-height - (get-in constants/layout-dimensions [content :height])))) + (let [skeleton-height (get-in constants/layout-dimensions [content :height]) + number-of-skeletons (int (Math/ceil (/ parent-height skeleton-height))) color (cond blur? colors/white-opa-5 (= theme :dark) colors/neutral-90 diff --git a/src/status_im/communities/core.cljs b/src/status_im/communities/core.cljs index 3603bc6332..a626db41f0 100644 --- a/src/status_im/communities/core.cljs +++ b/src/status_im/communities/core.cljs @@ -834,12 +834,17 @@ :cb #(re-frame/dispatch [::category-states-loaded community-id hashes %])}})) +;; Note - dispatch is used to make sure we are opening community once `pop-to-root` is processed. +;; Don't directly merge effects using `navigation/navigate-to`, because it will work in debug and +;; release, but for e2e `pop-to-root` closes even currently opened community +;; https://github.com/status-im/status-mobile/pull/16438#issuecomment-1623954774 (rf/defn navigate-to-community {:events [:communities/navigate-to-community]} [cofx community-id] - (rf/merge cofx - (navigation/pop-to-root :shell-stack) - (navigation/navigate-to :community-overview community-id))) + (rf/merge + cofx + {:dispatch [:navigate-to :community-overview community-id]} + (navigation/pop-to-root :shell-stack))) (rf/defn member-role-updated {:events [:community.member/role-updated]} diff --git a/src/status_im2/config.cljs b/src/status_im2/config.cljs index 42c193630b..2674e4ea64 100644 --- a/src/status_im2/config.cljs +++ b/src/status_im2/config.cljs @@ -164,4 +164,4 @@ (def default-kdf-iterations 3200) -(def shell-navigation-disabled? true) +(def shell-navigation-disabled? false) diff --git a/src/status_im2/contexts/chat/composer/sub_view.cljs b/src/status_im2/contexts/chat/composer/sub_view.cljs index 3aa129f72f..212fd746f1 100644 --- a/src/status_im2/contexts/chat/composer/sub_view.cljs +++ b/src/status_im2/contexts/chat/composer/sub_view.cljs @@ -3,6 +3,7 @@ [quo2.core :as quo] [react-native.blur :as blur] [react-native.core :as rn] + [status-im2.config :as config] [react-native.reanimated :as reanimated] [react-native.safe-area :as safe-area] [status-im2.contexts.chat.composer.style :as style] @@ -48,7 +49,8 @@ [quo/floating-shell-button {:jump-to {:on-press (fn [] - (rf/dispatch [:chat/close true]) + (when config/shell-navigation-disabled? + (rf/dispatch [:chat/close true])) (rf/dispatch [:shell/navigate-to-jump-to])) :customization-color customization-color :label (i18n/label :t/jump-to) diff --git a/src/status_im2/contexts/chat/composer/utils.cljs b/src/status_im2/contexts/chat/composer/utils.cljs index 683312c5e3..6cf7a98756 100644 --- a/src/status_im2/contexts/chat/composer/utils.cljs +++ b/src/status_im2/contexts/chat/composer/utils.cljs @@ -190,15 +190,21 @@ (defn init-subs [] - (let [chat-input (rf/sub [:chats/current-chat-input])] - {:images (seq (rf/sub [:chats/sending-image])) - :link-previews? (rf/sub [:chats/link-previews?]) - :audio (rf/sub [:chats/sending-audio]) - :reply (rf/sub [:chats/reply-message]) - :edit (rf/sub [:chats/edit-message]) - :input-with-mentions (rf/sub [:chat/input-with-mentions]) - :input-text (:input-text chat-input) - :input-content-height (:input-content-height chat-input)})) + (let [chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?])] + (merge + {:chat-screen-loaded? chat-screen-loaded? + :link-previews? false} + (when chat-screen-loaded? + (let [chat-input (rf/sub [:chats/current-chat-input])] + {:images (seq (rf/sub [:chats/sending-image])) + :link-previews? (rf/sub [:chats/link-previews?]) + :audio (rf/sub [:chats/sending-audio]) + :reply (rf/sub [:chats/reply-message]) + :edit (rf/sub [:chats/edit-message]) + :input-with-mentions (rf/sub [:chat/input-with-mentions]) + :input-text (:input-text chat-input) + :input-content-height (:input-content-height chat-input) + :chat-screen-loaded? chat-screen-loaded?}))))) (defn init-animations [{:keys [input-text images link-previews? reply audio]} diff --git a/src/status_im2/contexts/chat/composer/view.cljs b/src/status_im2/contexts/chat/composer/view.cljs index 38880ce3a1..0ee5b66bb6 100644 --- a/src/status_im2/contexts/chat/composer/view.cljs +++ b/src/status_im2/contexts/chat/composer/view.cljs @@ -27,32 +27,32 @@ (defn sheet-component [{:keys [insets window-height blur-height opacity background-y]} props state] - (let [subs (utils/init-subs) - content-height (reagent/atom (or (:input-content-height subs) - constants/input-height)) - {:keys [keyboard-shown]} (hooks/use-keyboard) - max-height (utils/calc-max-height subs - window-height - @(:kb-height state) - insets) - lines (utils/calc-lines (- @content-height - constants/extra-content-offset)) - max-lines (utils/calc-lines max-height) - animations (utils/init-animations - subs - lines - content-height - max-height - opacity - background-y) - dimensions {:content-height content-height - :max-height max-height - :window-height window-height - :lines lines - :max-lines max-lines} - show-bottom-gradient? (utils/show-bottom-gradient? state dimensions) - cursor-pos (utils/cursor-y-position-relative-to-container props - state)] + (let [{:keys [chat-screen-loaded?] :as subs} (utils/init-subs) + content-height (reagent/atom (or (:input-content-height subs) + constants/input-height)) + {:keys [keyboard-shown]} (hooks/use-keyboard) + max-height (utils/calc-max-height subs + window-height + @(:kb-height state) + insets) + lines (utils/calc-lines (- @content-height + constants/extra-content-offset)) + max-lines (utils/calc-lines max-height) + animations (utils/init-animations + subs + lines + content-height + max-height + opacity + background-y) + dimensions {:content-height content-height + :max-height max-height + :window-height window-height + :lines lines + :max-lines max-lines} + show-bottom-gradient? (utils/show-bottom-gradient? state dimensions) + cursor-pos (utils/cursor-y-position-relative-to-container props + state)] (effects/did-mount props) (effects/initialize props state @@ -67,19 +67,22 @@ (effects/images props state animations subs) [:<> [sub-view/shell-button state animations subs] - [mentions/view props state animations max-height cursor-pos - (:images subs) - (:link-previews? subs) - (:reply subs) - (:edit subs)] + (when chat-screen-loaded? + [mentions/view props state animations max-height cursor-pos + (:images subs) + (:link-previews? subs) + (:reply subs) + (:edit subs)]) [gesture/gesture-detector {:gesture (drag-gesture/drag-gesture props state animations subs dimensions keyboard-shown)} [reanimated/view {:style (style/sheet-container insets state animations) :on-layout #(handler/layout % state blur-height)} [sub-view/bar] - [reply/view state] - [edit/view state] + (when chat-screen-loaded? + [:<> + [reply/view state] + [edit/view state]]) [reanimated/touchable-opacity {:active-opacity 1 :on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props))) @@ -113,9 +116,11 @@ :style (style/input-text props state subs max-height) :max-length constants/max-text-size :accessibility-label :chat-message-input}]] - [gradients/view props state animations show-bottom-gradient?] - [link-preview/view] - [images/images-list]] + (when chat-screen-loaded? + [:<> + [gradients/view props state animations show-bottom-gradient?] + [link-preview/view] + [images/images-list]])] [actions/view props state animations window-height insets subs]]]])) (defn composer diff --git a/src/status_im2/contexts/chat/events.cljs b/src/status_im2/contexts/chat/events.cljs index fbfb398616..1376920a33 100644 --- a/src/status_im2/contexts/chat/events.cljs +++ b/src/status_im2/contexts/chat/events.cljs @@ -216,7 +216,7 @@ [{db :db :as cofx} chat-id animation] (rf/merge cofx {:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]} - (when-not (or (= (:view-id db) :community) (= (:view-id db) :community-overview)) + (when-not (#{:community :community-overview :shell} (:view-id db)) (navigation/pop-to-root :shell-stack)) (close-chat false) (force-close-chat chat-id) diff --git a/src/status_im2/contexts/chat/home/chat_list_item/view.cljs b/src/status_im2/contexts/chat/home/chat_list_item/view.cljs index 528774f556..43370192a8 100644 --- a/src/status_im2/contexts/chat/home/chat_list_item/view.cljs +++ b/src/status_im2/contexts/chat/home/chat_list_item/view.cljs @@ -3,6 +3,7 @@ [quo2.foundations.colors :as colors] [react-native.core :as rn] [utils.datetime :as datetime] + [utils.debounce :as debounce] [status-im2.common.home.actions.view :as actions] [status-im2.contexts.chat.home.chat-list-item.style :as style] [utils.re-frame :as rf] @@ -17,7 +18,7 @@ [chat-id] (fn [] (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:chat/navigate-to-chat chat-id]))) + (debounce/dispatch-and-chill [:chat/navigate-to-chat chat-id] 500))) (defn parsed-text-to-one-line [parsed-text] diff --git a/src/status_im2/contexts/chat/messages/list/style.cljs b/src/status_im2/contexts/chat/messages/list/style.cljs index 0c9b32a9b1..b6ff251981 100644 --- a/src/status_im2/contexts/chat/messages/list/style.cljs +++ b/src/status_im2/contexts/chat/messages/list/style.cljs @@ -1,5 +1,6 @@ (ns status-im2.contexts.chat.messages.list.style (:require [quo2.foundations.colors :as colors] + [status-im2.config :as config] [react-native.reanimated :as reanimated])) (defonce ^:const cover-height 168) @@ -11,8 +12,8 @@ [{:keys [top]}] {:position :relative :flex 1 - :top (- top) - :margin-bottom (- top)}) + :top (if config/shell-navigation-disabled? (- top) 0) + :margin-bottom (if config/shell-navigation-disabled? (- top) 0)}) (def list-container {:padding-vertical 16}) diff --git a/src/status_im2/contexts/chat/messages/list/view.cljs b/src/status_im2/contexts/chat/messages/list/view.cljs index 9a75f1e535..5def843fc5 100644 --- a/src/status_im2/contexts/chat/messages/list/view.cljs +++ b/src/status_im2/contexts/chat/messages/list/view.cljs @@ -109,13 +109,13 @@ :extrapolateRight "clamp"}) (defn loading-view - [chat-id shell-animation-complete?] + [chat-id] (let [loading-messages? (rf/sub [:chats/loading-messages? chat-id]) all-loaded? (rf/sub [:chats/all-loaded? chat-id]) messages (rf/sub [:chats/raw-chat-messages-stream chat-id]) loading-first-page? (= (count messages) 0) top-spacing (if loading-first-page? 0 navigation.style/navigation-bar-height)] - (when (or (not shell-animation-complete?) loading-messages? (not all-loaded?)) + (when (or loading-messages? (not all-loaded?)) [rn/view {:padding-top top-spacing} [quo/skeleton (if loading-first-page? @@ -190,11 +190,10 @@ chat-id]))}]}])) (defn f-list-footer - [{:keys [chat scroll-y cover-bg-color on-layout shell-animation-complete?]}] + [{:keys [chat scroll-y cover-bg-color on-layout]}] (let [{:keys [chat-id chat-name emoji chat-type group-chat]} chat - all-loaded? (when shell-animation-complete? - (rf/sub [:chats/all-loaded? chat-id])) + all-loaded? (rf/sub [:chats/all-loaded? chat-id]) display-name (if (= chat-type constants/one-to-one-chat-type) (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) (str emoji " " chat-name)) @@ -234,7 +233,7 @@ [quo/text {:style style/bio} bio]) [actions chat-id cover-bg-color]]]] - [loading-view chat-id shell-animation-complete?]])) + [loading-view chat-id]])) (defn list-footer [props] @@ -278,15 +277,10 @@ [{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown?]}] (let [{window-height :height} (rn/get-window) {:keys [keyboard-height]} (hooks/use-keyboard) - shell-animation-complete? (rf/sub [:shell/animation-complete? (:chat-type chat)]) - context (when shell-animation-complete? - (rf/sub [:chats/current-chat-message-list-view-context])) - messages (when shell-animation-complete? - (rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)])) - recording? (when shell-animation-complete? - (rf/sub [:chats/recording?])) - all-loaded? (when shell-animation-complete? - (rf/sub [:chats/all-loaded? (:chat-id chat)]))] + context (rf/sub [:chats/current-chat-message-list-view-context]) + messages (rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)]) + recording? (rf/sub [:chats/recording?]) + all-loaded? (rf/sub [:chats/all-loaded? (:chat-id chat)])] [rn/view {:style {:flex 1}} [rn/flat-list {:key-fn list-key-fn @@ -296,11 +290,10 @@ (when (= (:chat-type chat) constants/private-group-chat-type) [list-group-chat-header chat])] :footer [list-footer - {:chat chat - :scroll-y scroll-y - :cover-bg-color cover-bg-color - :on-layout footer-on-layout - :shell-animation-complete? shell-animation-complete?}] + {:chat chat + :scroll-y scroll-y + :cover-bg-color cover-bg-color + :on-layout footer-on-layout}] :data messages :render-data {:context context :keyboard-shown? keyboard-shown? @@ -352,6 +345,18 @@ (reset! messages-view-height layout-height))) :scroll-enabled (not recording?)}]])) +(defn message-list-content-view + [props] + (let [chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?]) + window-height (:height (rn/get-window)) + content-height (- window-height composer.constants/composer-default-height)] + (if chat-screen-loaded? + [:f> f-messages-list-content props] + [rn/view {:style {:flex 1}} + [quo/static-skeleton + {:content :messages + :parent-height content-height}]]))) + (defn f-messages-list [{:keys [chat cover-bg-color header-comp footer-comp]}] (let [insets (safe-area/get-insets) @@ -376,8 +381,7 @@ [header-comp {:scroll-y scroll-y}]) - [:f> - f-messages-list-content + [message-list-content-view {:chat chat :insets insets :scroll-y scroll-y diff --git a/src/status_im2/contexts/chat/messages/navigation/view.cljs b/src/status_im2/contexts/chat/messages/navigation/view.cljs index 597263f46e..e9122a5170 100644 --- a/src/status_im2/contexts/chat/messages/navigation/view.cljs +++ b/src/status_im2/contexts/chat/messages/navigation/view.cljs @@ -4,6 +4,7 @@ [re-frame.db] [react-native.blur :as blur] [react-native.core :as rn] + [status-im2.config :as config] [react-native.reanimated :as reanimated] [react-native.platform :as platform] [status-im2.contexts.chat.messages.navigation.style :as style] @@ -17,41 +18,41 @@ [{:keys [scroll-y]}] (let [{:keys [group-chat chat-id chat-name emoji chat-type] - :as chat} (rf/sub [:chats/current-chat-chat-view]) - shell-animation-complete? (rf/sub [:shell/animation-complete? (:chat-type chat)]) - all-loaded? (when shell-animation-complete? - (rf/sub [:chats/all-loaded? (:chat-id chat)])) - display-name (if (= chat-type constants/one-to-one-chat-type) - (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) - (str emoji " " chat-name)) - online? (rf/sub [:visibility-status-updates/online? chat-id]) - contact (when-not group-chat - (rf/sub [:contacts/contact-by-address chat-id])) - photo-path (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path chat-id])) - opacity-animation (reanimated/interpolate scroll-y - [style/navigation-bar-height - (+ style/navigation-bar-height 30)] - [0 1] - {:extrapolateLeft "clamp" - :extrapolateRight "extend"}) - banner-opacity-animation (reanimated/interpolate scroll-y - [(+ style/navigation-bar-height 150) - (+ style/navigation-bar-height 200)] - [0 1] - {:extrapolateLeft "clamp" - :extrapolateRight "extend"}) - translate-animation (reanimated/interpolate scroll-y - [(+ style/navigation-bar-height 25) - (+ style/navigation-bar-height 100)] - [50 0] - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"}) - title-opacity-animation (reanimated/interpolate scroll-y - [0 50] - [0 1] - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"})] + :as chat} (rf/sub [:chats/current-chat-chat-view]) + chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?]) + all-loaded? (when chat-screen-loaded? + (rf/sub [:chats/all-loaded? (:chat-id chat)])) + display-name (if (= chat-type constants/one-to-one-chat-type) + (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) + (str emoji " " chat-name)) + online? (rf/sub [:visibility-status-updates/online? chat-id]) + contact (when-not group-chat + (rf/sub [:contacts/contact-by-address chat-id])) + photo-path (when-not (empty? (:images contact)) + (rf/sub [:chats/photo-path chat-id])) + opacity-animation (reanimated/interpolate scroll-y + [style/navigation-bar-height + (+ style/navigation-bar-height 30)] + [0 1] + {:extrapolateLeft "clamp" + :extrapolateRight "extend"}) + banner-opacity-animation (reanimated/interpolate scroll-y + [(+ style/navigation-bar-height 150) + (+ style/navigation-bar-height 200)] + [0 1] + {:extrapolateLeft "clamp" + :extrapolateRight "extend"}) + translate-animation (reanimated/interpolate scroll-y + [(+ style/navigation-bar-height 25) + (+ style/navigation-bar-height 100)] + [50 0] + {:extrapolateLeft "clamp" + :extrapolateRight "clamp"}) + title-opacity-animation (reanimated/interpolate scroll-y + [0 50] + [0 1] + {:extrapolateLeft "clamp" + :extrapolateRight "clamp"})] [rn/view {:style style/navigation-view} [reanimated/view {:style (style/animated-background-view all-loaded? opacity-animation)}] @@ -62,55 +63,54 @@ :blur-type (colors/theme-colors :light :dark) :blur-radius (if platform/ios? 20 10) :style {:flex 1}}]] - - [rn/view - [rn/view {:style style/header-container} - [rn/touchable-opacity - {:active-opacity 1 - :on-press #(do - (rf/dispatch [:chat/close]) - (rf/dispatch [:navigate-back])) - :accessibility-label :back-button - :style (style/button-container {:margin-left 20})} - [quo/icon :i/arrow-left - {:size 20 :color (colors/theme-colors colors/black colors/white)}]] - [reanimated/view - {:style (style/animated-header all-loaded? translate-animation title-opacity-animation)} - [rn/view {:style style/header-content-container} - (when-not group-chat - [rn/view {:style style/header-avatar-container} - [quo/user-avatar - {:full-name display-name - :online? online? - :profile-picture photo-path - :size :small}]]) - [rn/view {:style style/header-text-container} - [rn/view {:style {:flex-direction :row}} + [rn/view {:style style/header-container} + [rn/touchable-opacity + {:active-opacity 1 + :on-press #(do + (when config/shell-navigation-disabled? + (rf/dispatch [:chat/close])) + (rf/dispatch [:navigate-back])) + :accessibility-label :back-button + :style (style/button-container {:margin-left 20})} + [quo/icon :i/arrow-left + {:size 20 :color (colors/theme-colors colors/black colors/white)}]] + [reanimated/view + {:style (style/animated-header all-loaded? translate-animation title-opacity-animation)} + [rn/view {:style style/header-content-container} + (when-not group-chat + [rn/view {:style style/header-avatar-container} + [quo/user-avatar + {:full-name display-name + :online? online? + :profile-picture photo-path + :size :small}]]) + [rn/view {:style style/header-text-container} + [rn/view {:style {:flex-direction :row}} + [quo/text + {:weight :semi-bold + :size :paragraph-1 + :number-of-lines 1 + :style (style/header-display-name)} + display-name]] + (when online? [quo/text - {:weight :semi-bold - :size :paragraph-1 - :number-of-lines 1 - :style (style/header-display-name)} - display-name]] - (when online? - [quo/text - {:number-of-lines 1 - :weight :regular - :size :paragraph-2 - :style (style/header-online)} - (i18n/label :t/online)])]]] - [rn/touchable-opacity - {:active-opacity 1 - :style (style/button-container {:margin-right 20}) - :accessibility-label :options-button - :on-press (fn [] - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:show-bottom-sheet - {:content (fn [] [actions/chat-actions chat true])}]))} - [quo/icon :i/options {:size 20 :color (colors/theme-colors colors/black colors/white)}]]] - [:f> - pin.banner/f-banner - {:chat-id chat-id - :opacity-animation banner-opacity-animation - :all-loaded? all-loaded? - :top-offset style/navigation-bar-height}]]])) + {:number-of-lines 1 + :weight :regular + :size :paragraph-2 + :style (style/header-online)} + (i18n/label :t/online)])]]] + [rn/touchable-opacity + {:active-opacity 1 + :style (style/button-container {:margin-right 20}) + :accessibility-label :options-button + :on-press (fn [] + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch [:show-bottom-sheet + {:content (fn [] [actions/chat-actions chat true])}]))} + [quo/icon :i/options {:size 20 :color (colors/theme-colors colors/black colors/white)}]]] + [:f> + pin.banner/f-banner + {:chat-id chat-id + :opacity-animation banner-opacity-animation + :all-loaded? all-loaded? + :top-offset style/navigation-bar-height}]])) diff --git a/src/status_im2/contexts/chat/messages/view.cljs b/src/status_im2/contexts/chat/messages/view.cljs index 551368e88c..5f7de0e1c6 100644 --- a/src/status_im2/contexts/chat/messages/view.cljs +++ b/src/status_im2/contexts/chat/messages/view.cljs @@ -6,16 +6,9 @@ [status-im2.contexts.chat.messages.navigation.view :as messages.navigation] [utils.re-frame :as rf])) -(defn load-composer - [insets chat-type] - (let [shell-animation-complete? (rf/sub [:shell/animation-complete? chat-type])] - (when shell-animation-complete? - [:f> composer/composer insets]))) - (defn chat [] (let [{:keys [chat-id - chat-type contact-request-state group-chat able-to-send-message?] @@ -31,4 +24,4 @@ (if-not able-to-send-message? [contact-requests.bottom-drawer/view chat-id contact-request-state group-chat] - [load-composer insets chat-type]))}])) + [:f> composer/composer insets]))}])) diff --git a/src/status_im2/contexts/communities/home/view.cljs b/src/status_im2/contexts/communities/home/view.cljs index 57ad8b58fd..584cae9584 100644 --- a/src/status_im2/contexts/communities/home/view.cljs +++ b/src/status_im2/contexts/communities/home/view.cljs @@ -2,6 +2,7 @@ (:require [quo2.core :as quo] [quo2.foundations.colors :as colors] [quo2.theme :as theme] + [utils.debounce :as debounce] [react-native.blur :as blur] [react-native.core :as rn] [react-native.platform :as platform] @@ -20,7 +21,7 @@ item (merge item unviewed-counts)] [quo/communities-membership-list-item {:style {:padding-horizontal 18} - :on-press #(rf/dispatch [:navigate-to :community-overview id]) + :on-press #(debounce/dispatch-and-chill [:navigate-to :community-overview id] 500) :on-long-press #(rf/dispatch [:show-bottom-sheet {:content (fn [] diff --git a/src/status_im2/contexts/shell/jump_to/animation.cljs b/src/status_im2/contexts/shell/jump_to/animation.cljs index 6ffb9e994c..a065e0fb68 100644 --- a/src/status_im2/contexts/shell/jump_to/animation.cljs +++ b/src/status_im2/contexts/shell/jump_to/animation.cljs @@ -1,11 +1,12 @@ (ns status-im2.contexts.shell.jump-to.animation (:require [utils.re-frame :as rf] + [react-native.platform :as platform] [react-native.reanimated :as reanimated] [status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.constants :as shell.constants])) -;; Home stack +;;;; Home stack (defn open-home-stack [stack-id animate?] (let [home-stack-state-value (utils/calculate-home-stack-state-value stack-id animate?)] @@ -43,7 +44,13 @@ (utils/change-shell-status-bar-style) (when animate? (utils/update-view-id (or stack-id :shell))))) -;; Floating Screen +;;;; Floating Screen + +;; Dispatch Delay - Animation time for the opening of a screen is 200 ms, +;; But starting and completion of animation sometimes takes a little extra time, +;; according to the performance of the device. And if before the animation is +;; complete we start other tasks like rendering messages or opening of the home screen +;; in the background then the animation breaks. So we are adding a small delay for that dispatch. (defn animate-floating-screen [screen-id {:keys [id animation community-id hidden-screen?]}] (when (not= animation (get @state/floating-screens-state screen-id)) @@ -52,17 +59,29 @@ (get-in @state/shared-values-atom [screen-id :screen-state]) animation) (reset! state/floating-screens-state - (assoc @state/floating-screens-state screen-id animation))) - (js/setTimeout - (fn [floating-screen-open?] - (if floating-screen-open? - ;; Events realted to opening of a screen - (rf/dispatch [:shell/floating-screen-opened screen-id - id community-id hidden-screen?]) - ;; Events realted to closing of a screen - (rf/dispatch [:shell/floating-screen-closed screen-id]))) - shell.constants/shell-animation-time - (utils/floating-screen-open? screen-id))) + (assoc @state/floating-screens-state screen-id animation)) + (let [floating-screen-open? (utils/floating-screen-open? screen-id) + animation-time (if (#{shell.constants/open-screen-without-animation + shell.constants/close-screen-without-animation} + animation) + 0 + shell.constants/shell-animation-time) + dispatch-delay (cond + (not floating-screen-open?) 0 + js/goog.DEBUG 100 + platform/android? 75 + :else 50) + dispatch-time (+ animation-time dispatch-delay)] + (js/setTimeout + (fn [floating-screen-open?] + (if floating-screen-open? + ;; Events realted to opening of a screen + (rf/dispatch [:shell/floating-screen-opened screen-id + id community-id hidden-screen?]) + ;; Events realted to closing of a screen + (rf/dispatch [:shell/floating-screen-closed screen-id]))) + dispatch-time + floating-screen-open?)))) (defn set-floating-screen-position [left top card-type] diff --git a/src/status_im2/contexts/shell/jump_to/components/floating_screens/style.cljs b/src/status_im2/contexts/shell/jump_to/components/floating_screens/style.cljs index fc63aaaa9a..232c75bf0e 100644 --- a/src/status_im2/contexts/shell/jump_to/components/floating_screens/style.cljs +++ b/src/status_im2/contexts/shell/jump_to/components/floating_screens/style.cljs @@ -1,9 +1,11 @@ (ns status-im2.contexts.shell.jump-to.components.floating-screens.style (:require [quo2.foundations.colors :as colors] - [react-native.reanimated :as reanimated])) + [react-native.reanimated :as reanimated] + [status-im2.contexts.shell.jump-to.constants :as shell.constants])) (defn screen - [{:keys [screen-left screen-top screen-width screen-height screen-border-radius screen-z-index]}] + [{:keys [screen-left screen-top screen-width screen-height screen-border-radius screen-z-index]} + screen-id] (reanimated/apply-animations-to-style {:left screen-left :top screen-top @@ -13,9 +15,16 @@ :z-index screen-z-index} {:background-color (colors/theme-colors colors/white colors/neutral-95) :overflow :hidden - :position :absolute})) + ;; KeyboardAvoidingView which is used for chat screen composer, + ;; not working when we use :absolute layout. One fix is to add + ;; KeyboardAvoidingView :behaviour height in android, which is also + ;; recommended in the documentation. It fixes KeyboardAvoidingView but + ;; the pushing of views by the keyboard is not smooth & while animating it creates a weird jump. + :position (if (= screen-id shell.constants/chat-screen) :relative :absolute) + :flex -1})) (defn screen-container [{:keys [width height]}] {:width width + :flex -1 :height height}) diff --git a/src/status_im2/contexts/shell/jump_to/components/floating_screens/view.cljs b/src/status_im2/contexts/shell/jump_to/components/floating_screens/view.cljs index f9d3896214..649d77ead3 100644 --- a/src/status_im2/contexts/shell/jump_to/components/floating_screens/view.cljs +++ b/src/status_im2/contexts/shell/jump_to/components/floating_screens/view.cljs @@ -1,13 +1,11 @@ (ns status-im2.contexts.shell.jump-to.components.floating-screens.view (:require [utils.re-frame :as rf] [react-native.core :as rn] - [react-native.gesture :as gesture] [react-native.reanimated :as reanimated] [status-im2.contexts.chat.messages.view :as chat] [status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.animation :as animation] - [status-im2.contexts.shell.jump-to.gesture :as shell.gesture] [status-im2.contexts.shell.jump-to.constants :as shell.constants] [status-im2.contexts.communities.overview.view :as communities.overview] [status-im2.contexts.shell.jump-to.components.floating-screens.style :as style])) @@ -17,20 +15,20 @@ shell.constants/chat-screen chat/chat}) (defn f-screen - [screen-id {:keys [id animation] :as screen-param}] + [screen-id {:keys [id animation clock] :as screen-param}] ;; First render screen, then animate (smoother animation) (rn/use-effect (fn [] (animation/animate-floating-screen screen-id screen-param)) - [animation id]) + [animation id clock]) [reanimated/view - {:style (style/screen (get @state/shared-values-atom screen-id))} - [gesture/gesture-detector - {:gesture (shell.gesture/floating-screen-gesture screen-id)} - [rn/view - {:style (style/screen-container (utils/dimensions)) - :key id} - [(get screens-map screen-id) id]]]]) + {:style (style/screen (get @state/shared-values-atom screen-id) screen-id)} + [rn/view + {:style (style/screen-container (utils/dimensions)) + :accessibility-label (str screen-id "-floating-screen") + :accessible true + :key id} + [(get screens-map screen-id) id]]]) ;; Currently chat screen and events both depends on current-chat-id, once we remove ;; use of current-chat-id from view then we can keep last chat loaded, for fast navigation diff --git a/src/status_im2/contexts/shell/jump_to/constants.cljs b/src/status_im2/contexts/shell/jump_to/constants.cljs index c95a1c0afc..b6472c87c5 100644 --- a/src/status_im2/contexts/shell/jump_to/constants.cljs +++ b/src/status_im2/contexts/shell/jump_to/constants.cljs @@ -33,10 +33,10 @@ :browser-stack :browser-stack-z-index}) ;; Home stack states -(def ^:const close-with-animation 0) -(def ^:const open-with-animation 1) -(def ^:const close-without-animation 2) -(def ^:const open-without-animation 3) +(def ^:const close-without-animation 0) +(def ^:const open-without-animation 1) +(def ^:const close-with-animation 2) +(def ^:const open-with-animation 3) ;; Switcher Cards (def ^:const empty-card 0) @@ -54,15 +54,17 @@ (def ^:const community-screen :community-overview) (def ^:const chat-screen :chat) +(def ^:const floating-screens [chat-screen community-screen]) + ;; Floating Screen states -(def ^:const close-screen-with-slide-animation 0) -(def ^:const open-screen-with-slide-animation 1) -(def ^:const close-screen-with-shell-animation 2) -(def ^:const open-screen-with-shell-animation 3) -(def ^:const close-screen-without-animation 4) -(def ^:const open-screen-without-animation 5) +(def ^:const close-screen-without-animation 0) +(def ^:const open-screen-without-animation 1) +(def ^:const close-screen-with-slide-animation 2) +(def ^:const open-screen-with-slide-animation 3) +(def ^:const close-screen-with-shell-animation 4) +(def ^:const open-screen-with-shell-animation 5) ;; Floating Screen gesture -(def ^:const gesture-width 20) +(def ^:const gesture-width 30) (def ^:const gesture-fling-right-velocity 2000) (def ^:const gesture-fling-left-velocity -1000) diff --git a/src/status_im2/contexts/shell/jump_to/events.cljs b/src/status_im2/contexts/shell/jump_to/events.cljs index d36105e400..479f805b63 100644 --- a/src/status_im2/contexts/shell/jump_to/events.cljs +++ b/src/status_im2/contexts/shell/jump_to/events.cljs @@ -28,10 +28,14 @@ (some-> ^js @state/jump-to-list-ref (.scrollToOffset #js {:y 0 :animated false}))))) +;; Note - pop-to-root resets currently opened screens to `close-screen-without-animation`. +;; This might take some time. So don't directly merge the effect of `pop-to-root` and +;; `navigate-to` for the floating screen. Because it might close even the currently opened screen. +;; https://github.com/status-im/status-mobile/pull/16438#issuecomment-1623954774 (re-frame/reg-fx :shell/pop-to-root-fx (fn [] - (reset! state/floating-screens-state {}))) + (shell.utils/reset-floating-screens))) (re-frame/reg-fx :shell/reset-state @@ -156,7 +160,7 @@ (rf/defn shell-navigate-to {:events [:shell/navigate-to]} - [{:keys [db]} go-to-view-id screen-params animation hidden-screen?] + [{:keys [db now]} go-to-view-id screen-params animation hidden-screen?] (if (shell.utils/shell-navigation? go-to-view-id) (let [current-view-id (:view-id db) community-id (get-in db [:chats screen-params :community-id])] @@ -166,6 +170,7 @@ {:id screen-params :community-id community-id :hidden-screen? hidden-screen? + :clock now :animation (or animation (case current-view-id :shell shell.constants/open-screen-with-shell-animation @@ -190,20 +195,22 @@ (rf/defn shell-navigate-back {:events [:shell/navigate-back]} - [{:keys [db]}] + [{:keys [db]} animation] (let [chat-screen-open? (shell.utils/floating-screen-open? shell.constants/chat-screen) community-screen-open? (shell.utils/floating-screen-open? shell.constants/community-screen) current-chat-id (:current-chat-id db) + current-view-id (:view-id db) community-id (when current-chat-id (get-in db [:chats current-chat-id :community-id]))] (if (and (not @navigation.state/curr-modal) + (shell.utils/shell-navigation? current-view-id) (or chat-screen-open? community-screen-open?)) {:db (assoc-in db [:shell/floating-screens (if chat-screen-open? shell.constants/chat-screen shell.constants/community-screen) :animation] - shell.constants/close-screen-with-slide-animation) + (or animation shell.constants/close-screen-with-slide-animation)) :dispatch-n (cond-> [[:set-view-id (cond (and chat-screen-open? community-screen-open?) @@ -220,19 +227,23 @@ {:events [:shell/floating-screen-opened]} [{:keys [db]} screen-id id community-id hidden-screen?] (merge - {:db (assoc-in db [:shell/loaded-screens screen-id] true) - :shell/change-tab-fx (if (or (= screen-id shell.constants/community-screen) - community-id) - :communities-stack - :chats-stack)} - (when community-id - ;; When opening community chat, open community screen in background - {:dispatch [:shell/navigate-to shell.constants/community-screen - community-id shell.constants/open-screen-without-animation true]}) - ;; Only update switcher cards for top screen + {:db (assoc-in db [:shell/loaded-screens screen-id] true) + :dispatch-later + (cond-> [] + community-id + ;; When opening community chat, open community screen in background + (conj {:ms 50 + :dispatch [:shell/navigate-to shell.constants/community-screen + community-id shell.constants/open-screen-without-animation true]}) + ;; Only update switcher cards for top screen + (not hidden-screen?) + (conj {:ms (* 2 shell.constants/shell-animation-time) + :dispatch [:shell/add-switcher-card screen-id id]}))} (when-not hidden-screen? - {:dispatch-later [{:ms (* 2 shell.constants/shell-animation-time) - :dispatch [:shell/add-switcher-card screen-id id]}]}))) + {:shell/change-tab-fx (if (or (= screen-id shell.constants/community-screen) + community-id) + :communities-stack + :chats-stack)}))) (rf/defn floating-screen-closed {:events [:shell/floating-screen-closed]} diff --git a/src/status_im2/contexts/shell/jump_to/gesture.cljs b/src/status_im2/contexts/shell/jump_to/gesture.cljs index 90de689b2f..180df942cd 100644 --- a/src/status_im2/contexts/shell/jump_to/gesture.cljs +++ b/src/status_im2/contexts/shell/jump_to/gesture.cljs @@ -1,26 +1,16 @@ (ns status-im2.contexts.shell.jump-to.gesture (:require [utils.re-frame :as rf] [react-native.gesture :as gesture] - [react-native.reanimated :as reanimated] [utils.worklets.shell :as worklets.shell] [status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.constants :as constants])) -(defn screen-closed-callback - [screen-id] - (fn [animation-time] - (js/setTimeout - (fn [] - (reanimated/set-shared-value - (get-in @state/shared-values-atom [screen-id :screen-state]) - constants/close-screen-without-animation) - (reset! state/floating-screens-state - (assoc @state/floating-screens-state - screen-id - constants/close-screen-without-animation)) - (rf/dispatch [:shell/floating-screen-closed screen-id])) - (or animation-time constants/shell-animation-time)))) +(defn on-screen-closed + [animation-time] + (js/setTimeout + #(rf/dispatch [:shell/navigate-back constants/close-screen-without-animation]) + (or animation-time constants/shell-animation-time))) (defn floating-screen-gesture [screen-id] @@ -39,5 +29,5 @@ :screen-width width :left-velocity constants/gesture-fling-left-velocity :right-velocity constants/gesture-fling-right-velocity - :screen-closed-callback (screen-closed-callback screen-id)}))))) + :screen-closed-callback on-screen-closed}))))) diff --git a/src/status_im2/contexts/shell/jump_to/utils.cljs b/src/status_im2/contexts/shell/jump_to/utils.cljs index 1da3337f2a..68afd1812c 100644 --- a/src/status_im2/contexts/shell/jump_to/utils.cljs +++ b/src/status_im2/contexts/shell/jump_to/utils.cljs @@ -5,8 +5,9 @@ [quo2.foundations.colors :as colors] [react-native.platform :as platform] [react-native.safe-area :as safe-area] - [status-im2.contexts.shell.jump-to.state :as state] + [react-native.reanimated :as reanimated] [status-im.async-storage.core :as async-storage] + [status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.constants :as shell.constants])) ;;;; Helper Functions @@ -85,6 +86,15 @@ (reset! state/load-wallet-stack? (= selected-stack-id :wallet-stack)) (reset! state/load-browser-stack? (= selected-stack-id :browser-stack)))) +(defn reset-floating-screens + [] + (reset! state/floating-screens-state {}) + (when @state/shared-values-atom + (doseq [screen-id (seq shell.constants/floating-screens)] + (reanimated/set-shared-value + (:screen-state (get @state/shared-values-atom screen-id)) + shell.constants/close-screen-without-animation)))) + ;;; Floating screen (defn floating-screen-open? [screen-id] diff --git a/src/status_im2/navigation/events.cljs b/src/status_im2/navigation/events.cljs index 7b96d02973..fffd5164a6 100644 --- a/src/status_im2/navigation/events.cljs +++ b/src/status_im2/navigation/events.cljs @@ -1,5 +1,6 @@ (ns status-im2.navigation.events (:require [utils.re-frame :as rf] + [status-im2.contexts.shell.jump-to.state :as shell.state] [status-im2.contexts.shell.jump-to.utils :as shell.utils] [status-im2.contexts.shell.jump-to.events :as shell.events])) @@ -42,7 +43,7 @@ (rf/defn navigate-back {:events [:navigate-back]} [cofx] - (shell.events/shell-navigate-back cofx)) + (shell.events/shell-navigate-back cofx nil)) (rf/defn navigate-back-within-stack {:events [:navigate-back-within-stack]} @@ -58,7 +59,10 @@ {:events [:pop-to-root]} [{:keys [db]} tab] {:pop-to-root-fx tab - :db (dissoc db :shell/floating-screens) + :db (-> db + (dissoc :shell/floating-screens) + (dissoc :shell/loaded-screens) + (assoc :view-id (or @shell.state/selected-stack-id :shell))) :shell/pop-to-root-fx nil}) (rf/defn init-root diff --git a/src/status_im2/subs/communities.cljs b/src/status_im2/subs/communities.cljs index bb22e9dd43..6447708b17 100644 --- a/src/status_im2/subs/communities.cljs +++ b/src/status_im2/subs/communities.cljs @@ -100,7 +100,7 @@ ;; and their data remained in app-db. ;; Result map has form: {:joined [id1, id2] :pending [id3, id5] :opened [id4]}" (fn [[view-id communities requests]] - (if (= view-id :communities-stack) + (if (or (empty? @memo-communities-stack-items) (= view-id :communities-stack)) (let [grouped-communities (reduce (fn [acc community] (let [joined? (:joined community) community-id (:id community) diff --git a/src/status_im2/subs/home.cljs b/src/status_im2/subs/home.cljs index ce6521434e..aab2b9f1bb 100644 --- a/src/status_im2/subs/home.cljs +++ b/src/status_im2/subs/home.cljs @@ -9,7 +9,7 @@ :<- [:view-id] :<- [:home-items-show-number] (fn [[chats view-id home-items-show-number]] - (if (= view-id :chats-stack) + (if (or (empty? @memo-chats-stack-items) (= view-id :chats-stack)) (let [res (take home-items-show-number chats)] (reset! memo-chats-stack-items res) res) diff --git a/src/status_im2/subs/shell.cljs b/src/status_im2/subs/shell.cljs index 083bd26444..20e2b644f2 100644 --- a/src/status_im2/subs/shell.cljs +++ b/src/status_im2/subs/shell.cljs @@ -4,7 +4,6 @@ [utils.datetime :as datetime] [status-im2.config :as config] [status-im2.constants :as constants] - [react-native.platform :as platform] [status-im2.common.resources :as resources] [status-im.multiaccounts.core :as multiaccounts] [status-im2.contexts.shell.jump-to.constants :as shell.constants])) @@ -125,7 +124,7 @@ :<- [:shell/switcher-cards] :<- [:view-id] (fn [[stacks view-id]] - (if (= view-id :shell) + (if (or (empty? @memo-shell-cards) (= view-id :shell)) (let [sorted-shell-cards (sort-by :clock > (map val stacks))] (reset! memo-shell-cards sorted-shell-cards) sorted-shell-cards) @@ -226,11 +225,8 @@ (get screens screen-id))) (re-frame/reg-sub - :shell/animation-complete? + :shell/chat-screen-loaded? :<- [:shell/loaded-screens] - (fn [screens [_ chat-type]] + (fn [screens] (or config/shell-navigation-disabled? - platform/ios? - (cond-> (get screens shell.constants/chat-screen) - (= chat-type constants/community-chat-type) - (and (get screens shell.constants/community-screen)))))) + (get screens shell.constants/chat-screen))))