Enable shell navigation (#16438)

This commit is contained in:
Parvesh Monu 2023-07-12 13:24:50 +05:30 committed by GitHub
parent 224d6c7cad
commit bcb55a1ab3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 323 additions and 266 deletions

View File

@ -1,18 +1,18 @@
import { Easing } from 'react-native-reanimated'; import { Easing } from 'react-native-reanimated';
// Home Stack States // Home Stack States
export const CLOSE_WITH_ANIMATION = 0; export const CLOSE_WITHOUT_ANIMATION = 0;
export const OPEN_WITH_ANIMATION = 1; export const OPEN_WITHOUT_ANIMATION = 1;
export const CLOSE_WITHOUT_ANIMATION = 2; export const CLOSE_WITH_ANIMATION = 2;
export const OPEN_WITHOUT_ANIMATION = 3; export const OPEN_WITH_ANIMATION = 3;
// Floating Screen States // Floating Screen States
export const CLOSE_SCREEN_WITH_SLIDE_ANIMATION = 0; export const CLOSE_SCREEN_WITHOUT_ANIMATION = 0;
export const OPEN_SCREEN_WITH_SLIDE_ANIMATION = 1; export const OPEN_SCREEN_WITHOUT_ANIMATION = 1;
export const CLOSE_SCREEN_WITH_SHELL_ANIMATION = 2; export const CLOSE_SCREEN_WITH_SLIDE_ANIMATION = 2;
export const OPEN_SCREEN_WITH_SHELL_ANIMATION = 3; export const OPEN_SCREEN_WITH_SLIDE_ANIMATION = 3;
export const CLOSE_SCREEN_WITHOUT_ANIMATION = 4; export const CLOSE_SCREEN_WITH_SHELL_ANIMATION = 4;
export const OPEN_SCREEN_WITHOUT_ANIMATION = 5; export const OPEN_SCREEN_WITH_SHELL_ANIMATION = 5;
export const SHELL_ANIMATION_TIME = 200; export const SHELL_ANIMATION_TIME = 200;

View File

@ -31,8 +31,8 @@
(defn- internal-view (defn- internal-view
[{:keys [content theme blur? parent-height]}] [{:keys [content theme blur? parent-height]}]
(let [number-of-skeletons (int (Math/floor (/ parent-height (let [skeleton-height (get-in constants/layout-dimensions [content :height])
(get-in constants/layout-dimensions [content :height])))) number-of-skeletons (int (Math/ceil (/ parent-height skeleton-height)))
color (cond color (cond
blur? colors/white-opa-5 blur? colors/white-opa-5
(= theme :dark) colors/neutral-90 (= theme :dark) colors/neutral-90

View File

@ -834,12 +834,17 @@
:cb #(re-frame/dispatch :cb #(re-frame/dispatch
[::category-states-loaded community-id hashes %])}})) [::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 (rf/defn navigate-to-community
{:events [:communities/navigate-to-community]} {:events [:communities/navigate-to-community]}
[cofx community-id] [cofx community-id]
(rf/merge cofx (rf/merge
(navigation/pop-to-root :shell-stack) cofx
(navigation/navigate-to :community-overview community-id))) {:dispatch [:navigate-to :community-overview community-id]}
(navigation/pop-to-root :shell-stack)))
(rf/defn member-role-updated (rf/defn member-role-updated
{:events [:community.member/role-updated]} {:events [:community.member/role-updated]}

View File

@ -164,4 +164,4 @@
(def default-kdf-iterations 3200) (def default-kdf-iterations 3200)
(def shell-navigation-disabled? true) (def shell-navigation-disabled? false)

View File

@ -3,6 +3,7 @@
[quo2.core :as quo] [quo2.core :as quo]
[react-native.blur :as blur] [react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]
[status-im2.config :as config]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area] [react-native.safe-area :as safe-area]
[status-im2.contexts.chat.composer.style :as style] [status-im2.contexts.chat.composer.style :as style]
@ -48,7 +49,8 @@
[quo/floating-shell-button [quo/floating-shell-button
{:jump-to {:jump-to
{:on-press (fn [] {: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])) (rf/dispatch [:shell/navigate-to-jump-to]))
:customization-color customization-color :customization-color customization-color
:label (i18n/label :t/jump-to) :label (i18n/label :t/jump-to)

View File

@ -190,6 +190,11 @@
(defn init-subs (defn init-subs
[] []
(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])] (let [chat-input (rf/sub [:chats/current-chat-input])]
{:images (seq (rf/sub [:chats/sending-image])) {:images (seq (rf/sub [:chats/sending-image]))
:link-previews? (rf/sub [:chats/link-previews?]) :link-previews? (rf/sub [:chats/link-previews?])
@ -198,7 +203,8 @@
:edit (rf/sub [:chats/edit-message]) :edit (rf/sub [:chats/edit-message])
:input-with-mentions (rf/sub [:chat/input-with-mentions]) :input-with-mentions (rf/sub [:chat/input-with-mentions])
:input-text (:input-text chat-input) :input-text (:input-text chat-input)
:input-content-height (:input-content-height chat-input)})) :input-content-height (:input-content-height chat-input)
:chat-screen-loaded? chat-screen-loaded?})))))
(defn init-animations (defn init-animations
[{:keys [input-text images link-previews? reply audio]} [{:keys [input-text images link-previews? reply audio]}

View File

@ -27,7 +27,7 @@
(defn sheet-component (defn sheet-component
[{:keys [insets window-height blur-height opacity background-y]} props state] [{:keys [insets window-height blur-height opacity background-y]} props state]
(let [subs (utils/init-subs) (let [{:keys [chat-screen-loaded?] :as subs} (utils/init-subs)
content-height (reagent/atom (or (:input-content-height subs) content-height (reagent/atom (or (:input-content-height subs)
constants/input-height)) constants/input-height))
{:keys [keyboard-shown]} (hooks/use-keyboard) {:keys [keyboard-shown]} (hooks/use-keyboard)
@ -67,19 +67,22 @@
(effects/images props state animations subs) (effects/images props state animations subs)
[:<> [:<>
[sub-view/shell-button state animations subs] [sub-view/shell-button state animations subs]
(when chat-screen-loaded?
[mentions/view props state animations max-height cursor-pos [mentions/view props state animations max-height cursor-pos
(:images subs) (:images subs)
(:link-previews? subs) (:link-previews? subs)
(:reply subs) (:reply subs)
(:edit subs)] (:edit subs)])
[gesture/gesture-detector [gesture/gesture-detector
{:gesture (drag-gesture/drag-gesture props state animations subs dimensions keyboard-shown)} {:gesture (drag-gesture/drag-gesture props state animations subs dimensions keyboard-shown)}
[reanimated/view [reanimated/view
{:style (style/sheet-container insets state animations) {:style (style/sheet-container insets state animations)
:on-layout #(handler/layout % state blur-height)} :on-layout #(handler/layout % state blur-height)}
[sub-view/bar] [sub-view/bar]
(when chat-screen-loaded?
[:<>
[reply/view state] [reply/view state]
[edit/view state] [edit/view state]])
[reanimated/touchable-opacity [reanimated/touchable-opacity
{:active-opacity 1 {:active-opacity 1
:on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props))) :on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props)))
@ -113,9 +116,11 @@
:style (style/input-text props state subs max-height) :style (style/input-text props state subs max-height)
:max-length constants/max-text-size :max-length constants/max-text-size
:accessibility-label :chat-message-input}]] :accessibility-label :chat-message-input}]]
(when chat-screen-loaded?
[:<>
[gradients/view props state animations show-bottom-gradient?] [gradients/view props state animations show-bottom-gradient?]
[link-preview/view] [link-preview/view]
[images/images-list]] [images/images-list]])]
[actions/view props state animations window-height insets subs]]]])) [actions/view props state animations window-height insets subs]]]]))
(defn composer (defn composer

View File

@ -216,7 +216,7 @@
[{db :db :as cofx} chat-id animation] [{db :db :as cofx} chat-id animation]
(rf/merge cofx (rf/merge cofx
{:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]} {: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)) (navigation/pop-to-root :shell-stack))
(close-chat false) (close-chat false)
(force-close-chat chat-id) (force-close-chat chat-id)

View File

@ -3,6 +3,7 @@
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.core :as rn] [react-native.core :as rn]
[utils.datetime :as datetime] [utils.datetime :as datetime]
[utils.debounce :as debounce]
[status-im2.common.home.actions.view :as actions] [status-im2.common.home.actions.view :as actions]
[status-im2.contexts.chat.home.chat-list-item.style :as style] [status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.re-frame :as rf] [utils.re-frame :as rf]
@ -17,7 +18,7 @@
[chat-id] [chat-id]
(fn [] (fn []
(rf/dispatch [:dismiss-keyboard]) (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 (defn parsed-text-to-one-line
[parsed-text] [parsed-text]

View File

@ -1,5 +1,6 @@
(ns status-im2.contexts.chat.messages.list.style (ns status-im2.contexts.chat.messages.list.style
(:require [quo2.foundations.colors :as colors] (:require [quo2.foundations.colors :as colors]
[status-im2.config :as config]
[react-native.reanimated :as reanimated])) [react-native.reanimated :as reanimated]))
(defonce ^:const cover-height 168) (defonce ^:const cover-height 168)
@ -11,8 +12,8 @@
[{:keys [top]}] [{:keys [top]}]
{:position :relative {:position :relative
:flex 1 :flex 1
:top (- top) :top (if config/shell-navigation-disabled? (- top) 0)
:margin-bottom (- top)}) :margin-bottom (if config/shell-navigation-disabled? (- top) 0)})
(def list-container (def list-container
{:padding-vertical 16}) {:padding-vertical 16})

View File

@ -109,13 +109,13 @@
:extrapolateRight "clamp"}) :extrapolateRight "clamp"})
(defn loading-view (defn loading-view
[chat-id shell-animation-complete?] [chat-id]
(let [loading-messages? (rf/sub [:chats/loading-messages? chat-id]) (let [loading-messages? (rf/sub [:chats/loading-messages? chat-id])
all-loaded? (rf/sub [:chats/all-loaded? chat-id]) all-loaded? (rf/sub [:chats/all-loaded? chat-id])
messages (rf/sub [:chats/raw-chat-messages-stream chat-id]) messages (rf/sub [:chats/raw-chat-messages-stream chat-id])
loading-first-page? (= (count messages) 0) loading-first-page? (= (count messages) 0)
top-spacing (if loading-first-page? 0 navigation.style/navigation-bar-height)] 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} [rn/view {:padding-top top-spacing}
[quo/skeleton [quo/skeleton
(if loading-first-page? (if loading-first-page?
@ -190,11 +190,10 @@
chat-id]))}]}])) chat-id]))}]}]))
(defn f-list-footer (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 (let [{:keys [chat-id chat-name emoji chat-type
group-chat]} chat group-chat]} chat
all-loaded? (when shell-animation-complete? all-loaded? (rf/sub [:chats/all-loaded? chat-id])
(rf/sub [:chats/all-loaded? chat-id]))
display-name (if (= chat-type constants/one-to-one-chat-type) display-name (if (= chat-type constants/one-to-one-chat-type)
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) (first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
(str emoji " " chat-name)) (str emoji " " chat-name))
@ -234,7 +233,7 @@
[quo/text {:style style/bio} [quo/text {:style style/bio}
bio]) bio])
[actions chat-id cover-bg-color]]]] [actions chat-id cover-bg-color]]]]
[loading-view chat-id shell-animation-complete?]])) [loading-view chat-id]]))
(defn list-footer (defn list-footer
[props] [props]
@ -278,15 +277,10 @@
[{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown?]}] [{:keys [chat insets scroll-y content-height cover-bg-color keyboard-shown?]}]
(let [{window-height :height} (rn/get-window) (let [{window-height :height} (rn/get-window)
{:keys [keyboard-height]} (hooks/use-keyboard) {:keys [keyboard-height]} (hooks/use-keyboard)
shell-animation-complete? (rf/sub [:shell/animation-complete? (:chat-type chat)]) context (rf/sub [:chats/current-chat-message-list-view-context])
context (when shell-animation-complete? messages (rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)])
(rf/sub [:chats/current-chat-message-list-view-context])) recording? (rf/sub [:chats/recording?])
messages (when shell-animation-complete? all-loaded? (rf/sub [:chats/all-loaded? (:chat-id chat)])]
(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)]))]
[rn/view {:style {:flex 1}} [rn/view {:style {:flex 1}}
[rn/flat-list [rn/flat-list
{:key-fn list-key-fn {:key-fn list-key-fn
@ -299,8 +293,7 @@
{:chat chat {:chat chat
:scroll-y scroll-y :scroll-y scroll-y
:cover-bg-color cover-bg-color :cover-bg-color cover-bg-color
:on-layout footer-on-layout :on-layout footer-on-layout}]
:shell-animation-complete? shell-animation-complete?}]
:data messages :data messages
:render-data {:context context :render-data {:context context
:keyboard-shown? keyboard-shown? :keyboard-shown? keyboard-shown?
@ -352,6 +345,18 @@
(reset! messages-view-height layout-height))) (reset! messages-view-height layout-height)))
:scroll-enabled (not recording?)}]])) :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 (defn f-messages-list
[{:keys [chat cover-bg-color header-comp footer-comp]}] [{:keys [chat cover-bg-color header-comp footer-comp]}]
(let [insets (safe-area/get-insets) (let [insets (safe-area/get-insets)
@ -376,8 +381,7 @@
[header-comp [header-comp
{:scroll-y scroll-y}]) {:scroll-y scroll-y}])
[:f> [message-list-content-view
f-messages-list-content
{:chat chat {:chat chat
:insets insets :insets insets
:scroll-y scroll-y :scroll-y scroll-y

View File

@ -4,6 +4,7 @@
[re-frame.db] [re-frame.db]
[react-native.blur :as blur] [react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]
[status-im2.config :as config]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[react-native.platform :as platform] [react-native.platform :as platform]
[status-im2.contexts.chat.messages.navigation.style :as style] [status-im2.contexts.chat.messages.navigation.style :as style]
@ -18,8 +19,8 @@
(let [{:keys [group-chat chat-id chat-name emoji (let [{:keys [group-chat chat-id chat-name emoji
chat-type] chat-type]
:as chat} (rf/sub [:chats/current-chat-chat-view]) :as chat} (rf/sub [:chats/current-chat-chat-view])
shell-animation-complete? (rf/sub [:shell/animation-complete? (:chat-type chat)]) chat-screen-loaded? (rf/sub [:shell/chat-screen-loaded?])
all-loaded? (when shell-animation-complete? all-loaded? (when chat-screen-loaded?
(rf/sub [:chats/all-loaded? (:chat-id chat)])) (rf/sub [:chats/all-loaded? (:chat-id chat)]))
display-name (if (= chat-type constants/one-to-one-chat-type) display-name (if (= chat-type constants/one-to-one-chat-type)
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) (first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
@ -62,13 +63,12 @@
:blur-type (colors/theme-colors :light :dark) :blur-type (colors/theme-colors :light :dark)
:blur-radius (if platform/ios? 20 10) :blur-radius (if platform/ios? 20 10)
:style {:flex 1}}]] :style {:flex 1}}]]
[rn/view
[rn/view {:style style/header-container} [rn/view {:style style/header-container}
[rn/touchable-opacity [rn/touchable-opacity
{:active-opacity 1 {:active-opacity 1
:on-press #(do :on-press #(do
(rf/dispatch [:chat/close]) (when config/shell-navigation-disabled?
(rf/dispatch [:chat/close]))
(rf/dispatch [:navigate-back])) (rf/dispatch [:navigate-back]))
:accessibility-label :back-button :accessibility-label :back-button
:style (style/button-container {:margin-left 20})} :style (style/button-container {:margin-left 20})}
@ -113,4 +113,4 @@
{:chat-id chat-id {:chat-id chat-id
:opacity-animation banner-opacity-animation :opacity-animation banner-opacity-animation
:all-loaded? all-loaded? :all-loaded? all-loaded?
:top-offset style/navigation-bar-height}]]])) :top-offset style/navigation-bar-height}]]))

View File

@ -6,16 +6,9 @@
[status-im2.contexts.chat.messages.navigation.view :as messages.navigation] [status-im2.contexts.chat.messages.navigation.view :as messages.navigation]
[utils.re-frame :as rf])) [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 (defn chat
[] []
(let [{:keys [chat-id (let [{:keys [chat-id
chat-type
contact-request-state contact-request-state
group-chat group-chat
able-to-send-message?] able-to-send-message?]
@ -31,4 +24,4 @@
(if-not able-to-send-message? (if-not able-to-send-message?
[contact-requests.bottom-drawer/view chat-id contact-request-state [contact-requests.bottom-drawer/view chat-id contact-request-state
group-chat] group-chat]
[load-composer insets chat-type]))}])) [:f> composer/composer insets]))}]))

View File

@ -2,6 +2,7 @@
(:require [quo2.core :as quo] (:require [quo2.core :as quo]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[quo2.theme :as theme] [quo2.theme :as theme]
[utils.debounce :as debounce]
[react-native.blur :as blur] [react-native.blur :as blur]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.platform :as platform] [react-native.platform :as platform]
@ -20,7 +21,7 @@
item (merge item unviewed-counts)] item (merge item unviewed-counts)]
[quo/communities-membership-list-item [quo/communities-membership-list-item
{:style {:padding-horizontal 18} {: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 :on-long-press #(rf/dispatch
[:show-bottom-sheet [:show-bottom-sheet
{:content (fn [] {:content (fn []

View File

@ -1,11 +1,12 @@
(ns status-im2.contexts.shell.jump-to.animation (ns status-im2.contexts.shell.jump-to.animation
(:require [utils.re-frame :as rf] (:require [utils.re-frame :as rf]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.utils :as utils]
[status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.state :as state]
[status-im2.contexts.shell.jump-to.constants :as shell.constants])) [status-im2.contexts.shell.jump-to.constants :as shell.constants]))
;; Home stack ;;;; Home stack
(defn open-home-stack (defn open-home-stack
[stack-id animate?] [stack-id animate?]
(let [home-stack-state-value (utils/calculate-home-stack-state-value 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) (utils/change-shell-status-bar-style)
(when animate? (utils/update-view-id (or stack-id :shell))))) (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 (defn animate-floating-screen
[screen-id {:keys [id animation community-id hidden-screen?]}] [screen-id {:keys [id animation community-id hidden-screen?]}]
(when (not= animation (get @state/floating-screens-state screen-id)) (when (not= animation (get @state/floating-screens-state screen-id))
@ -52,7 +59,19 @@
(get-in @state/shared-values-atom [screen-id :screen-state]) (get-in @state/shared-values-atom [screen-id :screen-state])
animation) animation)
(reset! state/floating-screens-state (reset! state/floating-screens-state
(assoc @state/floating-screens-state screen-id animation))) (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 (js/setTimeout
(fn [floating-screen-open?] (fn [floating-screen-open?]
(if floating-screen-open? (if floating-screen-open?
@ -61,8 +80,8 @@
id community-id hidden-screen?]) id community-id hidden-screen?])
;; Events realted to closing of a screen ;; Events realted to closing of a screen
(rf/dispatch [:shell/floating-screen-closed screen-id]))) (rf/dispatch [:shell/floating-screen-closed screen-id])))
shell.constants/shell-animation-time dispatch-time
(utils/floating-screen-open? screen-id))) floating-screen-open?))))
(defn set-floating-screen-position (defn set-floating-screen-position
[left top card-type] [left top card-type]

View File

@ -1,9 +1,11 @@
(ns status-im2.contexts.shell.jump-to.components.floating-screens.style (ns status-im2.contexts.shell.jump-to.components.floating-screens.style
(:require [quo2.foundations.colors :as colors] (: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 (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 (reanimated/apply-animations-to-style
{:left screen-left {:left screen-left
:top screen-top :top screen-top
@ -13,9 +15,16 @@
:z-index screen-z-index} :z-index screen-z-index}
{:background-color (colors/theme-colors colors/white colors/neutral-95) {:background-color (colors/theme-colors colors/white colors/neutral-95)
:overflow :hidden :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 (defn screen-container
[{:keys [width height]}] [{:keys [width height]}]
{:width width {:width width
:flex -1
:height height}) :height height})

View File

@ -1,13 +1,11 @@
(ns status-im2.contexts.shell.jump-to.components.floating-screens.view (ns status-im2.contexts.shell.jump-to.components.floating-screens.view
(:require [utils.re-frame :as rf] (:require [utils.re-frame :as rf]
[react-native.core :as rn] [react-native.core :as rn]
[react-native.gesture :as gesture]
[react-native.reanimated :as reanimated] [react-native.reanimated :as reanimated]
[status-im2.contexts.chat.messages.view :as chat] [status-im2.contexts.chat.messages.view :as chat]
[status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.state :as state]
[status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.utils :as utils]
[status-im2.contexts.shell.jump-to.animation :as animation] [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.shell.jump-to.constants :as shell.constants]
[status-im2.contexts.communities.overview.view :as communities.overview] [status-im2.contexts.communities.overview.view :as communities.overview]
[status-im2.contexts.shell.jump-to.components.floating-screens.style :as style])) [status-im2.contexts.shell.jump-to.components.floating-screens.style :as style]))
@ -17,20 +15,20 @@
shell.constants/chat-screen chat/chat}) shell.constants/chat-screen chat/chat})
(defn f-screen (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) ;; First render screen, then animate (smoother animation)
(rn/use-effect (rn/use-effect
(fn [] (fn []
(animation/animate-floating-screen screen-id screen-param)) (animation/animate-floating-screen screen-id screen-param))
[animation id]) [animation id clock])
[reanimated/view [reanimated/view
{:style (style/screen (get @state/shared-values-atom screen-id))} {:style (style/screen (get @state/shared-values-atom screen-id) screen-id)}
[gesture/gesture-detector
{:gesture (shell.gesture/floating-screen-gesture screen-id)}
[rn/view [rn/view
{:style (style/screen-container (utils/dimensions)) {:style (style/screen-container (utils/dimensions))
:accessibility-label (str screen-id "-floating-screen")
:accessible true
:key id} :key id}
[(get screens-map screen-id) id]]]]) [(get screens-map screen-id) id]]])
;; Currently chat screen and events both depends on current-chat-id, once we remove ;; 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 ;; use of current-chat-id from view then we can keep last chat loaded, for fast navigation

View File

@ -33,10 +33,10 @@
:browser-stack :browser-stack-z-index}) :browser-stack :browser-stack-z-index})
;; Home stack states ;; Home stack states
(def ^:const close-with-animation 0) (def ^:const close-without-animation 0)
(def ^:const open-with-animation 1) (def ^:const open-without-animation 1)
(def ^:const close-without-animation 2) (def ^:const close-with-animation 2)
(def ^:const open-without-animation 3) (def ^:const open-with-animation 3)
;; Switcher Cards ;; Switcher Cards
(def ^:const empty-card 0) (def ^:const empty-card 0)
@ -54,15 +54,17 @@
(def ^:const community-screen :community-overview) (def ^:const community-screen :community-overview)
(def ^:const chat-screen :chat) (def ^:const chat-screen :chat)
(def ^:const floating-screens [chat-screen community-screen])
;; Floating Screen states ;; Floating Screen states
(def ^:const close-screen-with-slide-animation 0) (def ^:const close-screen-without-animation 0)
(def ^:const open-screen-with-slide-animation 1) (def ^:const open-screen-without-animation 1)
(def ^:const close-screen-with-shell-animation 2) (def ^:const close-screen-with-slide-animation 2)
(def ^:const open-screen-with-shell-animation 3) (def ^:const open-screen-with-slide-animation 3)
(def ^:const close-screen-without-animation 4) (def ^:const close-screen-with-shell-animation 4)
(def ^:const open-screen-without-animation 5) (def ^:const open-screen-with-shell-animation 5)
;; Floating Screen gesture ;; Floating Screen gesture
(def ^:const gesture-width 20) (def ^:const gesture-width 30)
(def ^:const gesture-fling-right-velocity 2000) (def ^:const gesture-fling-right-velocity 2000)
(def ^:const gesture-fling-left-velocity -1000) (def ^:const gesture-fling-left-velocity -1000)

View File

@ -28,10 +28,14 @@
(some-> ^js @state/jump-to-list-ref (some-> ^js @state/jump-to-list-ref
(.scrollToOffset #js {:y 0 :animated false}))))) (.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 (re-frame/reg-fx
:shell/pop-to-root-fx :shell/pop-to-root-fx
(fn [] (fn []
(reset! state/floating-screens-state {}))) (shell.utils/reset-floating-screens)))
(re-frame/reg-fx (re-frame/reg-fx
:shell/reset-state :shell/reset-state
@ -156,7 +160,7 @@
(rf/defn shell-navigate-to (rf/defn shell-navigate-to
{:events [: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) (if (shell.utils/shell-navigation? go-to-view-id)
(let [current-view-id (:view-id db) (let [current-view-id (:view-id db)
community-id (get-in db [:chats screen-params :community-id])] community-id (get-in db [:chats screen-params :community-id])]
@ -166,6 +170,7 @@
{:id screen-params {:id screen-params
:community-id community-id :community-id community-id
:hidden-screen? hidden-screen? :hidden-screen? hidden-screen?
:clock now
:animation (or animation :animation (or animation
(case current-view-id (case current-view-id
:shell shell.constants/open-screen-with-shell-animation :shell shell.constants/open-screen-with-shell-animation
@ -190,20 +195,22 @@
(rf/defn shell-navigate-back (rf/defn shell-navigate-back
{:events [: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) (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) community-screen-open? (shell.utils/floating-screen-open? shell.constants/community-screen)
current-chat-id (:current-chat-id db) current-chat-id (:current-chat-id db)
current-view-id (:view-id db)
community-id (when current-chat-id community-id (when current-chat-id
(get-in db [:chats current-chat-id :community-id]))] (get-in db [:chats current-chat-id :community-id]))]
(if (and (not @navigation.state/curr-modal) (if (and (not @navigation.state/curr-modal)
(shell.utils/shell-navigation? current-view-id)
(or chat-screen-open? community-screen-open?)) (or chat-screen-open? community-screen-open?))
{:db (assoc-in {:db (assoc-in
db db
[:shell/floating-screens [:shell/floating-screens
(if chat-screen-open? shell.constants/chat-screen shell.constants/community-screen) (if chat-screen-open? shell.constants/chat-screen shell.constants/community-screen)
:animation] :animation]
shell.constants/close-screen-with-slide-animation) (or animation shell.constants/close-screen-with-slide-animation))
:dispatch-n (cond-> [[:set-view-id :dispatch-n (cond-> [[:set-view-id
(cond (cond
(and chat-screen-open? community-screen-open?) (and chat-screen-open? community-screen-open?)
@ -221,18 +228,22 @@
[{:keys [db]} screen-id id community-id hidden-screen?] [{:keys [db]} screen-id id community-id hidden-screen?]
(merge (merge
{:db (assoc-in db [:shell/loaded-screens screen-id] true) {:db (assoc-in db [:shell/loaded-screens screen-id] true)
:shell/change-tab-fx (if (or (= screen-id shell.constants/community-screen) :dispatch-later
community-id) (cond-> []
:communities-stack community-id
:chats-stack)}
(when community-id
;; When opening community chat, open community screen in background ;; When opening community chat, open community screen in background
{:dispatch [:shell/navigate-to shell.constants/community-screen (conj {:ms 50
:dispatch [:shell/navigate-to shell.constants/community-screen
community-id shell.constants/open-screen-without-animation true]}) community-id shell.constants/open-screen-without-animation true]})
;; Only update switcher cards for top screen ;; 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? (when-not hidden-screen?
{:dispatch-later [{:ms (* 2 shell.constants/shell-animation-time) {:shell/change-tab-fx (if (or (= screen-id shell.constants/community-screen)
:dispatch [:shell/add-switcher-card screen-id id]}]}))) community-id)
:communities-stack
:chats-stack)})))
(rf/defn floating-screen-closed (rf/defn floating-screen-closed
{:events [:shell/floating-screen-closed]} {:events [:shell/floating-screen-closed]}

View File

@ -1,26 +1,16 @@
(ns status-im2.contexts.shell.jump-to.gesture (ns status-im2.contexts.shell.jump-to.gesture
(:require [utils.re-frame :as rf] (:require [utils.re-frame :as rf]
[react-native.gesture :as gesture] [react-native.gesture :as gesture]
[react-native.reanimated :as reanimated]
[utils.worklets.shell :as worklets.shell] [utils.worklets.shell :as worklets.shell]
[status-im2.contexts.shell.jump-to.utils :as utils] [status-im2.contexts.shell.jump-to.utils :as utils]
[status-im2.contexts.shell.jump-to.state :as state] [status-im2.contexts.shell.jump-to.state :as state]
[status-im2.contexts.shell.jump-to.constants :as constants])) [status-im2.contexts.shell.jump-to.constants :as constants]))
(defn screen-closed-callback (defn on-screen-closed
[screen-id] [animation-time]
(fn [animation-time]
(js/setTimeout (js/setTimeout
(fn [] #(rf/dispatch [:shell/navigate-back constants/close-screen-without-animation])
(reanimated/set-shared-value (or animation-time constants/shell-animation-time)))
(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 floating-screen-gesture (defn floating-screen-gesture
[screen-id] [screen-id]
@ -39,5 +29,5 @@
:screen-width width :screen-width width
:left-velocity constants/gesture-fling-left-velocity :left-velocity constants/gesture-fling-left-velocity
:right-velocity constants/gesture-fling-right-velocity :right-velocity constants/gesture-fling-right-velocity
:screen-closed-callback (screen-closed-callback screen-id)}))))) :screen-closed-callback on-screen-closed})))))

View File

@ -5,8 +5,9 @@
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[react-native.platform :as platform] [react-native.platform :as platform]
[react-native.safe-area :as safe-area] [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-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])) [status-im2.contexts.shell.jump-to.constants :as shell.constants]))
;;;; Helper Functions ;;;; Helper Functions
@ -85,6 +86,15 @@
(reset! state/load-wallet-stack? (= selected-stack-id :wallet-stack)) (reset! state/load-wallet-stack? (= selected-stack-id :wallet-stack))
(reset! state/load-browser-stack? (= selected-stack-id :browser-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 ;;; Floating screen
(defn floating-screen-open? (defn floating-screen-open?
[screen-id] [screen-id]

View File

@ -1,5 +1,6 @@
(ns status-im2.navigation.events (ns status-im2.navigation.events
(:require [utils.re-frame :as rf] (: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.utils :as shell.utils]
[status-im2.contexts.shell.jump-to.events :as shell.events])) [status-im2.contexts.shell.jump-to.events :as shell.events]))
@ -42,7 +43,7 @@
(rf/defn navigate-back (rf/defn navigate-back
{:events [:navigate-back]} {:events [:navigate-back]}
[cofx] [cofx]
(shell.events/shell-navigate-back cofx)) (shell.events/shell-navigate-back cofx nil))
(rf/defn navigate-back-within-stack (rf/defn navigate-back-within-stack
{:events [:navigate-back-within-stack]} {:events [:navigate-back-within-stack]}
@ -58,7 +59,10 @@
{:events [:pop-to-root]} {:events [:pop-to-root]}
[{:keys [db]} tab] [{:keys [db]} tab]
{:pop-to-root-fx 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}) :shell/pop-to-root-fx nil})
(rf/defn init-root (rf/defn init-root

View File

@ -100,7 +100,7 @@
;; and their data remained in app-db. ;; and their data remained in app-db.
;; Result map has form: {:joined [id1, id2] :pending [id3, id5] :opened [id4]}" ;; Result map has form: {:joined [id1, id2] :pending [id3, id5] :opened [id4]}"
(fn [[view-id communities requests]] (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 [grouped-communities (reduce (fn [acc community]
(let [joined? (:joined community) (let [joined? (:joined community)
community-id (:id community) community-id (:id community)

View File

@ -9,7 +9,7 @@
:<- [:view-id] :<- [:view-id]
:<- [:home-items-show-number] :<- [:home-items-show-number]
(fn [[chats 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)] (let [res (take home-items-show-number chats)]
(reset! memo-chats-stack-items res) (reset! memo-chats-stack-items res)
res) res)

View File

@ -4,7 +4,6 @@
[utils.datetime :as datetime] [utils.datetime :as datetime]
[status-im2.config :as config] [status-im2.config :as config]
[status-im2.constants :as constants] [status-im2.constants :as constants]
[react-native.platform :as platform]
[status-im2.common.resources :as resources] [status-im2.common.resources :as resources]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im2.contexts.shell.jump-to.constants :as shell.constants])) [status-im2.contexts.shell.jump-to.constants :as shell.constants]))
@ -125,7 +124,7 @@
:<- [:shell/switcher-cards] :<- [:shell/switcher-cards]
:<- [:view-id] :<- [:view-id]
(fn [[stacks 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))] (let [sorted-shell-cards (sort-by :clock > (map val stacks))]
(reset! memo-shell-cards sorted-shell-cards) (reset! memo-shell-cards sorted-shell-cards)
sorted-shell-cards) sorted-shell-cards)
@ -226,11 +225,8 @@
(get screens screen-id))) (get screens screen-id)))
(re-frame/reg-sub (re-frame/reg-sub
:shell/animation-complete? :shell/chat-screen-loaded?
:<- [:shell/loaded-screens] :<- [:shell/loaded-screens]
(fn [screens [_ chat-type]] (fn [screens]
(or config/shell-navigation-disabled? (or config/shell-navigation-disabled?
platform/ios? (get screens shell.constants/chat-screen))))
(cond-> (get screens shell.constants/chat-screen)
(= chat-type constants/community-chat-type)
(and (get screens shell.constants/community-screen))))))