From d4897de205ffc56ef54955dc86ead154098f3034 Mon Sep 17 00:00:00 2001 From: Parvesh Monu Date: Wed, 30 Nov 2022 21:46:01 +0530 Subject: [PATCH] partially implement shell jump-to navigation (#14410) --- nix/mobile/android/release.nix | 2 +- resources/images/icons2/12x12/group@2x.png | Bin 0 -> 469 bytes resources/images/icons2/12x12/group@3x.png | Bin 0 -> 758 bytes resources/images/icons2/20x20/group@2x.png | Bin 0 -> 924 bytes resources/images/icons2/20x20/group@3x.png | Bin 0 -> 1456 bytes resources/images/ui/switcher@2x.png | Bin 6913 -> 0 bytes resources/images/ui/switcher@3x.png | Bin 12259 -> 0 bytes src/js/shell_worklets.js | 186 +++++++++++++++++ src/js/worklet_factory.js | 105 ---------- src/mocks/js_dependencies.cljs | 3 + src/quo2/components/avatars/group_avatar.cljs | 4 +- .../navigation/floating_shell_button.cljs | 58 +++--- src/status_im/chat/models.cljs | 14 +- src/status_im/communities/core.cljs | 7 + src/status_im/events.cljs | 1 + src/status_im/multiaccounts/logout/core.cljs | 2 +- src/status_im/react_native/resources.cljs | 1 - .../ui/screens/communities/community.cljs | 12 +- src/status_im/ui/screens/home/views.cljs | 5 +- .../ui/screens/profile/user/views.cljs | 7 - .../ui2/screens/chat/composer/view.cljs | 2 +- .../ui2/screens/chat/messages/message.cljs | 6 +- src/status_im/ui2/screens/chat/view.cljs | 13 +- .../contexts/communities/home/view.cljs | 2 +- .../navigation/floating_shell_button.cljs | 3 +- .../quo_preview/switcher/switcher_cards.cljs | 34 +-- src/status_im2/contexts/shell/animation.cljs | 196 +++++++++++------- .../contexts/shell/bottom_tabs.cljs | 59 ++---- .../contexts/shell/cards/style.cljs | 67 +++--- src/status_im2/contexts/shell/cards/view.cljs | 133 +++++++----- src/status_im2/contexts/shell/constants.cljs | 20 ++ src/status_im2/contexts/shell/events.cljs | 90 ++++++++ src/status_im2/contexts/shell/home_stack.cljs | 15 +- src/status_im2/contexts/shell/view.cljs | 104 +++++++--- src/status_im2/navigation/events.cljs | 30 +-- src/status_im2/subs/general.cljs | 15 -- src/status_im2/subs/root.cljs | 3 +- src/status_im2/subs/shell.cljs | 99 +++++++++ 38 files changed, 844 insertions(+), 454 deletions(-) create mode 100644 resources/images/icons2/12x12/group@2x.png create mode 100644 resources/images/icons2/12x12/group@3x.png create mode 100644 resources/images/icons2/20x20/group@2x.png create mode 100644 resources/images/icons2/20x20/group@3x.png delete mode 100644 resources/images/ui/switcher@2x.png delete mode 100644 resources/images/ui/switcher@3x.png create mode 100644 src/js/shell_worklets.js create mode 100644 src/status_im2/contexts/shell/events.cljs create mode 100644 src/status_im2/subs/shell.cljs diff --git a/nix/mobile/android/release.nix b/nix/mobile/android/release.nix index 35d327e861..392eada1e3 100644 --- a/nix/mobile/android/release.nix +++ b/nix/mobile/android/release.nix @@ -46,7 +46,7 @@ in stdenv.mkDerivation rec { root = path; include = [ "package.json" "yarn.lock" "metro.config.js" "babel.config.js" - "resources/.*" "translations/.*" "src/js/worklet_factory.js" + "resources/.*" "translations/.*" "src/js/.*" "modules/react-native-status/android.*" "android/.*" envFileName "VERSION" "status-go-version.json" "react-native.config.js" ]; diff --git a/resources/images/icons2/12x12/group@2x.png b/resources/images/icons2/12x12/group@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..834569a502c2ed0294fdb7d42b59abfa72ace0da GIT binary patch literal 469 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 KMNUMnLSTX&b)gdg literal 0 HcmV?d00001 diff --git a/resources/images/ui/switcher@2x.png b/resources/images/ui/switcher@2x.png deleted file mode 100644 index 7db491b62770db29eb78a6895f38c4786d0bbc8e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6913 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 diff --git a/resources/images/ui/switcher@3x.png b/resources/images/ui/switcher@3x.png deleted file mode 100644 index dc105dbc21122eaf212e654836c75f40ca36f6e6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12259 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 diff --git a/src/js/shell_worklets.js b/src/js/shell_worklets.js new file mode 100644 index 0000000000..5d0fb06baf --- /dev/null +++ b/src/js/shell_worklets.js @@ -0,0 +1,186 @@ +import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated'; + +// Shell Worklets + +// Home Stack States +const CLOSE_WITH_ANIMATION = 0; +const OPEN_WITH_ANIMATION = 1; +const CLOSE_WITHOUT_ANIMATION = 3; +const OPEN_WITHOUT_ANIMATION = 4; + +// Derived Values +export function stackOpacity (stackId, selectedStackId) { + return useDerivedValue( + function () { + 'worklet' + return selectedStackId.value == stackId ? 1 : 0; + } + ); +} + +export function stackPointer (stackId, selectedStackId) { + return useDerivedValue( + function () { + 'worklet' + return selectedStackId.value == stackId ? "auto" : "none"; + } + ); +} + +export function bottomTabIconColor (stackId, selectedStackId, homeStackState, + passThrough, selectedTabColor, defaultColor, + passThroughColor) { + return useDerivedValue( + function () { + 'worklet' + var homeStackStateValue = homeStackState.value; + if (selectedStackId.value == stackId && + (homeStackStateValue == OPEN_WITH_ANIMATION || + homeStackStateValue == OPEN_WITHOUT_ANIMATION)){ + return selectedTabColor; + } + else if (passThrough.value){ + return passThroughColor; + } + else { + return defaultColor; + } + } + ); +} + +export function bottomTabsHeight(homeStackState, height, extendedHeight) { + return useDerivedValue( + function () { + 'worklet' + switch (homeStackState.value) { + case OPEN_WITH_ANIMATION: + return withTiming(extendedHeight, defaultDurationAndEasing); + break; + case CLOSE_WITH_ANIMATION: + return withTiming(height, defaultDurationAndEasing); + break; + case OPEN_WITHOUT_ANIMATION: + return extendedHeight; + break; + case CLOSE_WITHOUT_ANIMATION: + return height; + break; + } + } + ) +} + + +// Home Stack + +const shellAnimationTime = 200; + +const defaultDurationAndEasing = { + duration: shellAnimationTime, + easing: Easing.bezier(0, 0, 1, 1), +} + +export function homeStackOpacity (homeStackState) { + return useDerivedValue( + function () { + 'worklet' + switch (homeStackState.value) { + case OPEN_WITH_ANIMATION: + return withTiming(1, defaultDurationAndEasing); + break; + case CLOSE_WITH_ANIMATION: + return withTiming(0, defaultDurationAndEasing); + break; + case OPEN_WITHOUT_ANIMATION: + return 1; + break; + case CLOSE_WITHOUT_ANIMATION: + return 0; + break; + } + } + ); +} + +export function homeStackTop (homeStackState, top) { + return useDerivedValue( + function () { + 'worklet' + switch (homeStackState.value) { + case OPEN_WITH_ANIMATION: + return withTiming(0, defaultDurationAndEasing); + break; + case CLOSE_WITH_ANIMATION: + return withTiming(top, defaultDurationAndEasing); + break; + case OPEN_WITHOUT_ANIMATION: + return 0; + break; + case CLOSE_WITHOUT_ANIMATION: + return top; + break; + } + } + ); +} + +export function homeStackLeft (selectedStackId, animateHomeStackLeft, homeStackState, left) { + return useDerivedValue( + function () { + 'worklet' + if (animateHomeStackLeft.value) { + var leftValue = left[selectedStackId.value]; + switch (homeStackState.value) { + case OPEN_WITH_ANIMATION: + return withSequence(withTiming(leftValue, {duration: 0}), withTiming(0, defaultDurationAndEasing)) + break; + case CLOSE_WITH_ANIMATION: + return withTiming(leftValue, defaultDurationAndEasing); + break; + case OPEN_WITHOUT_ANIMATION: + return 0; + break; + case CLOSE_WITHOUT_ANIMATION: + return leftValue; + break; + } + } else { + return 0; + } + } + ); +} + +export function homeStackPointer (homeStackState) { + return useDerivedValue( + function () { + 'worklet' + var homeStackStateValue = homeStackState.value; + return (homeStackStateValue == OPEN_WITH_ANIMATION || + homeStackStateValue == OPEN_WITHOUT_ANIMATION) ? "auto" : "none"; + } + ); +} + +export function homeStackScale (homeStackState, minimizeScale) { + return useDerivedValue( + function () { + 'worklet' + switch (homeStackState.value) { + case OPEN_WITH_ANIMATION: + return withTiming(1, defaultDurationAndEasing); + break; + case CLOSE_WITH_ANIMATION: + return withTiming(minimizeScale, defaultDurationAndEasing); + break; + case OPEN_WITHOUT_ANIMATION: + return 1; + break; + case CLOSE_WITHOUT_ANIMATION: + return minimizeScale; + break; + } + } + ); +} diff --git a/src/js/worklet_factory.js b/src/js/worklet_factory.js index fadc3d4f7b..9886191fd8 100644 --- a/src/js/worklet_factory.js +++ b/src/js/worklet_factory.js @@ -1,5 +1,3 @@ -import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated'; - // Generic Worklets export function applyAnimationsToStyle(animations, style) { @@ -29,106 +27,3 @@ export function applyAnimationsToStyle(animations, style) { return Object.assign(animatedStyle, style); }; }; - -// Switcher Worklets - -export function stackOpacity (stackId, selectedStackId) { - return useDerivedValue( - function () { - 'worklet' - return selectedStackId.value == stackId ? 1 : 0; - } - ); -} - -export function stackPointer (stackId, selectedStackId) { - return useDerivedValue( - function () { - 'worklet' - return selectedStackId.value == stackId ? "auto" : "none"; - } - ); -} - -export function bottomTabIconColor (stackId, selectedStackId, homeStackOpen, - passThrough, selectedTabColor, defaultColor, - passThroughColor) { - return useDerivedValue( - function () { - 'worklet' - if (selectedStackId.value == stackId && homeStackOpen.value){ - return selectedTabColor; - } - else if (passThrough.value){ - return passThroughColor; - } - else { - return defaultColor; - } - } - ); -} - - -// Home Stack - -const shellAnimationTime = 200; - -const defaultDurationAndEasing = { - duration: shellAnimationTime, - easing: Easing.bezier(0, 0, 1, 1), -} - -export function homeStackOpacity (homeStackOpen) { - return useDerivedValue( - function () { - 'worklet' - return withTiming(homeStackOpen.value ? 1 : 0, defaultDurationAndEasing); - } - ); -} - -export function homeStackTop (homeStackOpen, top) { - return useDerivedValue( - function () { - 'worklet' - return withTiming(homeStackOpen.value ? 0 : top, defaultDurationAndEasing); - } - ); -} - -export function homeStackLeft (selectedStackId, animateHomeStackLeft, homeStackOpen, left) { - return useDerivedValue( - function () { - 'worklet' - if (animateHomeStackLeft.value) { - var leftValue = left[selectedStackId.value]; - if (homeStackOpen.value) { - return withSequence(withTiming(leftValue, {duration: 0}), withTiming(0, defaultDurationAndEasing)) - } else { - return withTiming(leftValue, defaultDurationAndEasing); - } - } else { - return 0; - } - } - ); -} - -export function homeStackPointer (homeStackOpen) { - return useDerivedValue( - function () { - 'worklet' - return homeStackOpen.value ? "auto" : "none"; - } - ); -} - -export function homeStackScale (homeStackOpen, minimizeScale) { - return useDerivedValue( - function () { - 'worklet' - return withTiming(homeStackOpen.value ? 1 : minimizeScale, defaultDurationAndEasing); - } - ); -} diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index edf7c5c98c..a97a571362 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -282,6 +282,8 @@ (def worklet-factory #js {:applyAnimationsToStyle (fn [])}) +(def shell-worklets #js {}) + ;; Update i18n_resources.cljs (defn mock [module] (case module @@ -328,6 +330,7 @@ "@react-native-async-storage/async-storage" async-storage "react-native-svg" react-native-svg "../src/js/worklet_factory.js" worklet-factory + "../src/js/shell_worklets.js" shell-worklets "./fleets.js" default-fleets "./chats.js" default-chats "@walletconnect/client" wallet-connect-client diff --git a/src/quo2/components/avatars/group_avatar.cljs b/src/quo2/components/avatars/group_avatar.cljs index 6b773ad48f..d5fab5ac39 100644 --- a/src/quo2/components/avatars/group_avatar.cljs +++ b/src/quo2/components/avatars/group_avatar.cljs @@ -21,6 +21,6 @@ :align-items :center :justify-content :center :border-radius (/ container-size 2) - :background-color (colors/theme-alpha color 0.5 0.6)} - [icon/icon :i/group {:size icon-size ; TODO: group icon sizes 12 and 20 (small and large) are missing + :background-color (colors/custom-color-by-theme color 50 60)} + [icon/icon :i/group {:size icon-size :color colors/white-opa-70}]]))) diff --git a/src/quo2/components/navigation/floating_shell_button.cljs b/src/quo2/components/navigation/floating_shell_button.cljs index 6000744262..00f8a3ca0f 100644 --- a/src/quo2/components/navigation/floating_shell_button.cljs +++ b/src/quo2/components/navigation/floating_shell_button.cljs @@ -14,31 +14,35 @@ :customization-color customization-color}])) (defn floating-shell-button - "[floating-shell-button dynamic-buttons style] - dynamic-buttons - {:button-type {:on-press on-press :count count}}" - [dynamic-buttons style opacity-anim pointer-anim] - [:f> - (fn [] - (let [original-style (merge {:flex-direction :row - :margin-horizontal 12} style) - animated-style (reanimated/apply-animations-to-style - {:opacity opacity-anim - :pointer-events pointer-anim} - original-style)] - [reanimated/view {:style animated-style} - ;; Left Section - [rn/view {:style {:flex 1}} - [dynamic-button-view :search dynamic-buttons {:position :absolute - :right 8}]] - ;; Mid Section (jump-to) - [dynamic-button-view :jump-to dynamic-buttons nil] + "[floating-shell-button dynamic-buttons style opacity-anim pointer-anim] + dynamic-buttons {:button-type {:on-press on-press :count count}} + style override style + opacity-anim reanimated value (optional)" + ([dynamic-button style] + (floating-shell-button dynamic-button style nil)) + ([dynamic-buttons style opacity-anim] + [:f> + (fn [] + (let [original-style (merge {:flex-direction :row + :margin-horizontal 12 + :pointer-events :box-none} style) + animated-style (reanimated/apply-animations-to-style + (if opacity-anim + {:opacity opacity-anim} {}) + original-style)] + [reanimated/view {:style animated-style} + ;; Left Section + [rn/view {:style {:flex 1}} + [dynamic-button-view :search dynamic-buttons {:position :absolute + :right 8}]] + ;; Mid Section (jump-to) + [dynamic-button-view :jump-to dynamic-buttons nil] ;; Right Section - [rn/view {:style {:flex 1}} - [rn/view {:style {:position :absolute - :flex-direction :row - :right 0}} - [dynamic-button-view :mention dynamic-buttons {:margin-left 8}] - [dynamic-button-view :notification-down dynamic-buttons {:margin-left 8}] - [dynamic-button-view :notification-up dynamic-buttons {:margin-left 8}] - [dynamic-button-view :bottom dynamic-buttons {:margin-left 8}]]]]))]) + [rn/view {:style {:flex 1}} + [rn/view {:style {:position :absolute + :flex-direction :row + :right 0}} + [dynamic-button-view :mention dynamic-buttons {:margin-left 8}] + [dynamic-button-view :notification-down dynamic-buttons {:margin-left 8}] + [dynamic-button-view :notification-up dynamic-buttons {:margin-left 8}] + [dynamic-button-view :bottom dynamic-buttons {:margin-left 8}]]]]))])) diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index fea2b28d80..15856c5a67 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -265,12 +265,18 @@ (fx/defn navigate-to-chat-nav2 "Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data" {:events [:chat.ui/navigate-to-chat-nav2]} - [{db :db :as cofx} chat-id from-switcher?] + [{db :db :as cofx} chat-id from-shell?] (fx/merge cofx - {:db (assoc db :current-chat-id chat-id)} - (offload-messages chat-id) + {:dispatch [:navigate-to-nav2 :chat chat-id from-shell?]} + (when-not (= (:view-id db) :community) + (navigation/pop-to-root-tab :shell-stack)) + (close-chat) + (force-close-chat chat-id) + (fn [{:keys [db]}] + {:db (assoc db :current-chat-id chat-id)}) (preload-chat-data chat-id) - (navigation/navigate-to-nav2 :chat chat-id nil from-switcher?))) + #(when (group-chat? cofx chat-id) + (loading/load-chat % chat-id)))) (fx/defn handle-clear-history-response {:events [::history-cleared]} diff --git a/src/status_im/communities/core.cljs b/src/status_im/communities/core.cljs index 44803d4f65..94dcc29462 100644 --- a/src/status_im/communities/core.cljs +++ b/src/status_im/communities/core.cljs @@ -672,3 +672,10 @@ {::async-storage/get {:keys keys :cb #(re-frame/dispatch [::category-states-loaded community-id hashes %])}})) + +(fx/defn navigate-to-community + {:events [:communities/navigate-to-community]} + [cofx community-id] + (fx/merge cofx + (navigation/pop-to-root-tab :shell-stack) + (navigation/navigate-to-nav2 :community community-id true))) diff --git a/src/status_im/events.cljs b/src/status_im/events.cljs index d7f4230f0b..43e45e8e16 100644 --- a/src/status_im/events.cljs +++ b/src/status_im/events.cljs @@ -58,6 +58,7 @@ status-im.wallet-connect-legacy.core status-im.network.net-info status-im.visibility-status-popover.core + status-im2.contexts.shell.events [status-im.multiaccounts.model :as multiaccounts.model])) (re-frame/reg-fx diff --git a/src/status_im/multiaccounts/logout/core.cljs b/src/status_im/multiaccounts/logout/core.cljs index d3ad7ad351..882dd1b2e5 100644 --- a/src/status_im/multiaccounts/logout/core.cljs +++ b/src/status_im/multiaccounts/logout/core.cljs @@ -17,7 +17,7 @@ {:init-root-fx :progress :chat.ui/clear-inputs nil :chat.ui/clear-inputs-old nil - :new-ui/reset-bottom-tabs nil + :shell/reset-bottom-tabs nil :hide-popover nil ::logout nil ::multiaccounts/webview-debug-changed false diff --git a/src/status_im/react_native/resources.cljs b/src/status_im/react_native/resources.cljs index 5f4d1ca51c..47a79c0188 100644 --- a/src/status_im/react_native/resources.cljs +++ b/src/status_im/react_native/resources.cljs @@ -47,7 +47,6 @@ :collectible-dark (js/require "../resources/images/ui/collectible-dark.png") :hand-wave (js/require "../resources/images/ui/hand-wave.png") :graph (js/require "../resources/images/ui/graph.png") - :switcher (js/require "../resources/images/ui/switcher.png") :discover (js/require "../resources/images/ui/discover.png") :community-cover (js/require "../resources/images/ui/community-cover.png") :lifestyle (js/require "../resources/images/ui/lifestyle.png") diff --git a/src/status_im/ui/screens/communities/community.cljs b/src/status_im/ui/screens/communities/community.cljs index 343f8d1978..48355fd7a5 100644 --- a/src/status_im/ui/screens/communities/community.cljs +++ b/src/status_im/ui/screens/communities/community.cljs @@ -22,6 +22,7 @@ [status-im.ui.components.accordion :as accordion] [status-im.ui.components.list.views :as list] [status-im.ui.components.react :as react] + [quo2.components.navigation.floating-shell-button :as floating-shell-button] [quo.core :as quo] [quo.design-system.colors :as colors])) @@ -155,7 +156,7 @@ (assoc home-item :public? true) {:on-press (fn [] (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:chat.ui/navigate-to-chat chat-id]) + (rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id]) (rf/dispatch [:search/home-filter-changed nil]) (rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id])) :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet @@ -244,7 +245,7 @@ (i18n/label :t/fetch-community))]]])) (defn community [] - (let [{:keys [community-id from-chat]} (rf/sub [:get-screen-params])] + (let [{:keys [community-id from-chat]} (rf/sub [:get-screen-params :community])] (fn [] (let [{:keys [id chats name images members permissions color joined can-request-access? can-join? requested-to-join-at admin] @@ -301,5 +302,10 @@ {:show-border? true :center [quo/button {:on-press #(rf/dispatch [:communities/join id]) :type :secondary} - (i18n/label :t/follow)]}]))] + (i18n/label :t/follow)]}])) + [floating-shell-button/floating-shell-button + {:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to]) + :label (i18n/label :t/jump-to)}} + {:position :absolute + :bottom 70}]] [unknown-community community-id]))))) diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 01db525adc..2376f38880 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -12,7 +12,6 @@ [status-im.ui.screens.home.views.inner-item :as inner-item] [quo.design-system.colors :as colors] [quo.core :as quo] - [quo.platform :as platform] [status-im.add-new.core :as new-chat] [status-im.ui.components.search-input.view :as search-input] [status-im.add-new.db :as db] @@ -131,7 +130,7 @@ home-item {:on-press (fn [] (re-frame/dispatch [:dismiss-keyboard]) - (if (and config/new-ui-enabled? platform/android?) + (if config/new-ui-enabled? (re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id]) (re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])) (re-frame/dispatch [:search/home-filter-changed nil]) @@ -148,7 +147,7 @@ home-item {:on-press (fn [] (re-frame/dispatch [:dismiss-keyboard]) - (if (and config/new-ui-enabled? platform/android?) + (if config/new-ui-enabled? (re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id]) (re-frame/dispatch [:chat.ui/navigate-to-chat chat-id])) (re-frame/dispatch [:search/home-filter-changed nil]) diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 0c49ea92d9..24fa0034a6 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -110,13 +110,6 @@ :accessory (when mnemonic [components.common/counter {:size 22} 1]) :on-press #(re-frame/dispatch [:navigate-to :privacy-and-security])}] - (when config/quo-preview-enabled? - [quo/list-item - {:icon :main-icons/appearance - :title "Quo Preview" - :accessibility-label :appearance-settings-button - :chevron true - :on-press #(re-frame/dispatch [:navigate-to :quo-preview])}]) (when config/quo-preview-enabled? [quo/list-item {:icon :main-icons/appearance diff --git a/src/status_im/ui2/screens/chat/composer/view.cljs b/src/status_im/ui2/screens/chat/composer/view.cljs index 17a66d43a9..f1eb36c72f 100644 --- a/src/status_im/ui2/screens/chat/composer/view.cljs +++ b/src/status_im/ui2/screens/chat/composer/view.cljs @@ -170,7 +170,7 @@ (re-frame/dispatch [:dismiss-keyboard])) edit) [reanimated/view {:style (reanimated/apply-animations-to-style {:height shared-height} - {})} + {:z-index 2})} ;;INPUT MESSAGE bottom sheet [gesture/gesture-detector {:gesture bottom-sheet-gesture} [reanimated/view {:style (reanimated/apply-animations-to-style diff --git a/src/status_im/ui2/screens/chat/messages/message.cljs b/src/status_im/ui2/screens/chat/messages/message.cljs index c7b6ee255c..0ca6c51bcd 100644 --- a/src/status_im/ui2/screens/chat/messages/message.cljs +++ b/src/status_im/ui2/screens/chat/messages/message.cljs @@ -274,9 +274,9 @@ name] [rn/text description]]] [rn/view (style/community-view-button) - [rn/touchable-opacity {:on-press #(re-frame/dispatch [:navigate-to - :community - {:community-id (:id community)}])} + [rn/touchable-opacity {:on-press #(re-frame/dispatch + [:communities/navigate-to-community + {:community-id (:id community)}])} [rn/text {:style {:text-align :center :color quo.colors/blue}} (i18n/label :t/view)]]]]))) diff --git a/src/status_im/ui2/screens/chat/view.cljs b/src/status_im/ui2/screens/chat/view.cljs index d5745c01c3..4f145e8bca 100644 --- a/src/status_im/ui2/screens/chat/view.cljs +++ b/src/status_im/ui2/screens/chat/view.cljs @@ -5,6 +5,8 @@ [status-im.ui2.screens.chat.composer.view :as composer] [status-im.utils.debounce :as debounce] [quo.react-native :as rn] + [re-frame.core :as re-frame] + [status-im.i18n.i18n :as i18n] [quo2.components.buttons.button :as quo2.button] [quo2.foundations.colors :as colors] [status-im.ui.components.react :as react] @@ -14,6 +16,7 @@ [status-im.ui.components.icons.icons :as icons] [status-im.ui2.screens.chat.messages.pinned-message :as pinned-message] [re-frame.db] + [quo2.components.navigation.floating-shell-button :as floating-shell-button] [status-im.ui2.screens.chat.messages.message :as message])) (defn topbar-content [] @@ -77,10 +80,16 @@ [messages/messages-view {:chat chat :mutual-contact-requests-enabled? mutual-contact-requests-enabled? - :show-input? show-input?}] + :show-input? show-input? + :bottom-space 15}] ;;INPUT COMPOSER (when show-input? - [composer/composer chat-id])])) + [composer/composer chat-id]) + [floating-shell-button/floating-shell-button + {:jump-to {:on-press #(re-frame/dispatch [:shell/navigate-to-jump-to]) + :label (i18n/label :t/jump-to)}} + {:position :absolute + :bottom 117}]])) (defn chat [] (reagent/create-class diff --git a/src/status_im2/contexts/communities/home/view.cljs b/src/status_im2/contexts/communities/home/view.cljs index ed3e71c453..ff6fa6a7c7 100644 --- a/src/status_im2/contexts/communities/home/view.cljs +++ b/src/status_im2/contexts/communities/home/view.cljs @@ -14,7 +14,7 @@ {:on-press (fn [] (rf/dispatch [:communities/load-category-states id]) (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:navigate-to :community {:community-id id}])) + (rf/dispatch [:navigate-to-nav2 :community {:community-id id}])) :on-long-press #(rf/dispatch [:bottom-sheet/show-sheet {:content (fn [] [home.actions/actions community-item])}])} diff --git a/src/status_im2/contexts/quo_preview/navigation/floating_shell_button.cljs b/src/status_im2/contexts/quo_preview/navigation/floating_shell_button.cljs index a5c0308eb0..4e5766aca1 100644 --- a/src/status_im2/contexts/quo_preview/navigation/floating_shell_button.cljs +++ b/src/status_im2/contexts/quo_preview/navigation/floating_shell_button.cljs @@ -52,8 +52,7 @@ [rn/view {:padding-vertical 60 :align-items :center} [quo2/floating-shell-button (mock-data @state) - nil (reanimated/use-shared-value 1) - (reanimated/use-shared-value "auto")]]]])])) + nil (reanimated/use-shared-value 1)]]]])])) (defn preview-floating-shell-button [] [rn/view {:background-color (colors/theme-colors colors/white colors/neutral-90) diff --git a/src/status_im2/contexts/quo_preview/switcher/switcher_cards.cljs b/src/status_im2/contexts/quo_preview/switcher/switcher_cards.cljs index 462573fd14..e419167be6 100644 --- a/src/status_im2/contexts/quo_preview/switcher/switcher_cards.cljs +++ b/src/status_im2/contexts/quo_preview/switcher/switcher_cards.cljs @@ -1,6 +1,7 @@ (ns status-im2.contexts.quo-preview.switcher.switcher-cards (:require [react-native.core :as rn] [reagent.core :as reagent] + [status-im2.contexts.shell.constants :as constants] [status-im2.contexts.quo-preview.preview :as preview] [quo2.foundations.colors :as colors] [status-im.react-native.resources :as resources] @@ -9,21 +10,21 @@ (def descriptor [{:label "Type" :key :type :type :select - :options [{:key :communities-discover + :options [{:key constants/communities-discover :value "Communities Discover"} - {:key :messaging + {:key constants/one-to-one-chat-card :value "Messaging"} - {:key :group-messaging + {:key constants/private-group-chat-card :value "Group Messaging"} - {:key :community-card + {:key constants/community-card :value "Community Card"} - {:key :browser-card + {:key constants/browser-card :value "Browser Card"} - {:key :wallet-card + {:key constants/wallet-card :value "Wallet Card"} - {:key :wallet-collectible + {:key constants/wallet-collectible :value "Wallet Collectible"} - {:key :wallet-graph + {:key constants/wallet-graph :value "Wallet Graph"}]} {:label "Title" :key :title @@ -105,23 +106,24 @@ :community-info {:type :kicked} (:audio :community :link :code) nil)) -(defn get-mock-data [data] +(defn get-mock-data [{:keys [type] :as data}] (merge data - {:banner (when (:banner? data) banner) + {:type type + :banner (when (:banner? data) banner) :content {:new-notifications? (:new-notifications? data) :notification-indicator (:notification-indicator data) :counter-label (:counter-label data) :content-type (:content-type data) :data (get-mock-content data)}} - (case (:type data) - :messaging {:avatar-params {:full-name (:title data)}} - :group-messaging {} - :community-card {:avatar-params community-avatar} + (case type + constants/one-to-one-chat-card {:avatar-params {:full-name (:title data)}} + constants/private-group-chat-card {} + constants/community-card {:avatar-params community-avatar} {}))) (defn cool-preview [] - (let [state (reagent/atom {:type :group-messaging + (let [state (reagent/atom {:type constants/private-group-chat-card :title "Alisher Yakupov" :customization-color :turquoise :new-notifications? true @@ -137,7 +139,7 @@ [preview/customizer state descriptor] [rn/view {:padding-vertical 60 :align-items :center} - [switcher-cards/card (:type @state) (get-mock-data @state)]]]]))) + [switcher-cards/card (get-mock-data @state)]]]]))) (defn preview-switcher-cards [] [rn/view {:background-color colors/neutral-100 diff --git a/src/status_im2/contexts/shell/animation.cljs b/src/status_im2/contexts/shell/animation.cljs index 8f61738644..a52d7023a5 100644 --- a/src/status_im2/contexts/shell/animation.cljs +++ b/src/status_im2/contexts/shell/animation.cljs @@ -1,5 +1,6 @@ (ns status-im2.contexts.shell.animation - (:require [re-frame.core :as re-frame] + (:require [reagent.core :as reagent] + [re-frame.core :as re-frame] [react-native.reanimated :as reanimated] [quo2.foundations.colors :as colors] [status-im2.contexts.shell.constants :as constants] @@ -7,20 +8,43 @@ ;;TODO remove when not used anymore [status-im.async-storage.core :as async-storage])) -;;;; Bottom Tabs & Home Stack Animations - +;; Atoms (def selected-stack-id (atom nil)) -(def home-stack-open? (atom false)) -(def pass-through? (atom false)) +(def home-stack-state (atom constants/close-with-animation)) +(def pass-through? (atom false)) ;; TODO - Use dynamic pass-through for transparent bottom tabs +(def shared-values-atom (atom nil)) -(def bottom-nav-tab-width 90) +;; Reagent atoms used for lazily loading home screen tabs +(def load-communities-stack? (reagent/atom false)) +(def load-chats-stack? (reagent/atom false)) +(def load-wallet-stack? (reagent/atom false)) +(def load-browser-stack? (reagent/atom false)) + +;; Helper Functions +(defn home-stack-open? [] + (let [state @home-stack-state] + (or (= state constants/open-with-animation) + (= state constants/open-without-animation)))) + +(defn load-stack [stack-id] + (case stack-id + :communities-stack (reset! load-communities-stack? true) + :chats-stack (reset! load-chats-stack? true) + :wallet-stack (reset! load-wallet-stack? true) + :browser-stack (reset! load-browser-stack? true) + "")) (defn selected-stack-id-loaded [stack-id] (reset! selected-stack-id stack-id) - (reset! home-stack-open? (some? stack-id))) + (reset! + home-stack-state + (if (some? stack-id) + constants/open-with-animation + constants/close-with-animation))) (defn calculate-home-stack-position [] (let [{:keys [width height]} (constants/dimensions) + bottom-nav-tab-width 90 minimize-scale (/ bottom-nav-tab-width width) empty-space-half-scale (/ (- 1 minimize-scale) 2) left-margin (/ (- width (* 4 bottom-nav-tab-width)) 2) @@ -36,81 +60,105 @@ :top (+ top-empty-space (constants/bottom-tabs-container-height)) :scale minimize-scale})) -(defn get-shared-values [] +(def shell-worklets (js/require "../src/js/shell_worklets.js")) + +;; Shared Values +(defn calculate-shared-values [] (let [selected-stack-id-sv (reanimated/use-shared-value ;; passing keywords or nil is not working with reanimated (name (or @selected-stack-id :communities-stack))) pass-through-sv (reanimated/use-shared-value @pass-through?) - home-stack-open-sv (reanimated/use-shared-value @home-stack-open?) - animate-home-stack-left (reanimated/use-shared-value (not @home-stack-open?)) + home-stack-state-sv (reanimated/use-shared-value @home-stack-state) + animate-home-stack-left (reanimated/use-shared-value (not (home-stack-open?))) home-stack-position (calculate-home-stack-position)] - (reduce - (fn [acc id] - (let [tabs-icon-color-keyword (get constants/tabs-icon-color-keywords id) - stack-opacity-keyword (get constants/stacks-opacity-keywords id) - stack-pointer-keyword (get constants/stacks-pointer-keywords id)] - (assoc - acc - stack-opacity-keyword (.stackOpacity - ^js reanimated/worklet-factory - (name id) selected-stack-id-sv) - stack-pointer-keyword (.stackPointer - ^js reanimated/worklet-factory - (name id) selected-stack-id-sv) - tabs-icon-color-keyword (.bottomTabIconColor - ^js reanimated/worklet-factory - (name id) selected-stack-id-sv home-stack-open-sv - pass-through-sv colors/white colors/neutral-50 - colors/white-opa-40)))) - {:selected-stack-id selected-stack-id-sv - :pass-through? pass-through-sv - :home-stack-open? home-stack-open-sv - :animate-home-stack-left animate-home-stack-left - :home-stack-left (.homeStackLeft - ^js reanimated/worklet-factory - selected-stack-id-sv animate-home-stack-left home-stack-open-sv - (clj->js (:left home-stack-position))) - :home-stack-top (.homeStackTop - ^js reanimated/worklet-factory - home-stack-open-sv (:top home-stack-position)) - :home-stack-opacity (.homeStackOpacity - ^js reanimated/worklet-factory home-stack-open-sv) - :home-stack-pointer (.homeStackPointer - ^js reanimated/worklet-factory home-stack-open-sv) - :home-stack-scale (.homeStackScale - ^js reanimated/worklet-factory home-stack-open-sv - (:scale home-stack-position))} - constants/stacks-ids))) + (reset! shared-values-atom + (reduce + (fn [acc id] + (let [tabs-icon-color-keyword (get constants/tabs-icon-color-keywords id) + stack-opacity-keyword (get constants/stacks-opacity-keywords id) + stack-pointer-keyword (get constants/stacks-pointer-keywords id)] + (assoc + acc + stack-opacity-keyword (.stackOpacity + ^js shell-worklets + (name id) selected-stack-id-sv) + stack-pointer-keyword (.stackPointer + ^js shell-worklets + (name id) selected-stack-id-sv) + tabs-icon-color-keyword (.bottomTabIconColor + ^js shell-worklets + (name id) selected-stack-id-sv home-stack-state-sv + pass-through-sv colors/white colors/neutral-50 + colors/white-opa-40)))) + {:selected-stack-id selected-stack-id-sv + :pass-through? pass-through-sv + :home-stack-state home-stack-state-sv + :animate-home-stack-left animate-home-stack-left + :home-stack-left (.homeStackLeft + ^js shell-worklets + selected-stack-id-sv animate-home-stack-left + home-stack-state-sv + (clj->js (:left home-stack-position))) + :home-stack-top (.homeStackTop + ^js shell-worklets + home-stack-state-sv (:top home-stack-position)) + :home-stack-opacity (.homeStackOpacity + ^js shell-worklets home-stack-state-sv) + :home-stack-pointer (.homeStackPointer + ^js shell-worklets home-stack-state-sv) + :home-stack-scale (.homeStackScale + ^js shell-worklets home-stack-state-sv + (:scale home-stack-position)) + :bottom-tabs-height (.bottomTabsHeight + ^js shell-worklets home-stack-state-sv + (constants/bottom-tabs-container-height) + (constants/bottom-tabs-extended-container-height))} + constants/stacks-ids))) + @shared-values-atom) -;; Animation +;; Animations -(defn open-home-stack [shared-values stack-id] - (reanimated/set-shared-value (:selected-stack-id shared-values) (name stack-id)) - (reanimated/set-shared-value (:home-stack-open? shared-values) true) - (when-not (colors/dark?) - (js/setTimeout - #(re-frame/dispatch [:change-root-status-bar-style :dark]) - constants/shell-animation-time)) - (reset! home-stack-open? true) +(defn open-home-stack [stack-id animate?] + (let [home-stack-state-value (if animate? + constants/open-with-animation + constants/open-without-animation)] + (reanimated/set-shared-value + (:selected-stack-id @shared-values-atom) (name stack-id)) + (reanimated/set-shared-value + (:home-stack-state @shared-values-atom) home-stack-state-value) + (when-not (colors/dark?) + (js/setTimeout + #(re-frame/dispatch [:change-root-status-bar-style :dark]) + constants/shell-animation-time)) + (reset! home-stack-state home-stack-state-value) + (reset! selected-stack-id stack-id) + (async-storage/set-item! :selected-stack-id stack-id))) + +(defn change-tab [stack-id] + (reanimated/set-shared-value (:animate-home-stack-left @shared-values-atom) false) + (reanimated/set-shared-value (:selected-stack-id @shared-values-atom) (name stack-id)) (reset! selected-stack-id stack-id) (async-storage/set-item! :selected-stack-id stack-id)) -(defn change-tab [shared-values stack-id] - (reanimated/set-shared-value (:animate-home-stack-left shared-values) false) - (reanimated/set-shared-value (:selected-stack-id shared-values) (name stack-id)) - (reset! selected-stack-id stack-id) - (async-storage/set-item! :selected-stack-id stack-id)) +(defn bottom-tab-on-press [stack-id] + (when-not (= stack-id @selected-stack-id) + (let [stack-load-delay (if (home-stack-open?) + 0 constants/shell-animation-time)] + (if (home-stack-open?) + (change-tab stack-id) + (open-home-stack stack-id true)) + (js/setTimeout #(load-stack stack-id) stack-load-delay)))) -(defn bottom-tab-on-press [shared-values stack-id] - (if @home-stack-open? - (change-tab shared-values stack-id) - (open-home-stack shared-values stack-id))) - -(defn close-home-stack [shared-values] - (reanimated/set-shared-value (:animate-home-stack-left shared-values) true) - (reanimated/set-shared-value (:home-stack-open? shared-values) false) - (when-not (colors/dark?) - (re-frame/dispatch [:change-root-status-bar-style :light])) - (reset! home-stack-open? false) - (reset! selected-stack-id nil) - (async-storage/set-item! :selected-stack-id nil)) +(defn close-home-stack [animate?] + (let [home-stack-state-value (if animate? + constants/close-with-animation + constants/close-without-animation)] + (reanimated/set-shared-value + (:animate-home-stack-left @shared-values-atom) true) + (reanimated/set-shared-value + (:home-stack-state @shared-values-atom) home-stack-state-value) + (when-not (colors/dark?) + (re-frame/dispatch [:change-root-status-bar-style :light])) + (reset! home-stack-state home-stack-state-value) + (reset! selected-stack-id nil) + (async-storage/set-item! :selected-stack-id nil))) diff --git a/src/status_im2/contexts/shell/bottom_tabs.cljs b/src/status_im2/contexts/shell/bottom_tabs.cljs index e10e944c3e..0e631bb384 100644 --- a/src/status_im2/contexts/shell/bottom_tabs.cljs +++ b/src/status_im2/contexts/shell/bottom_tabs.cljs @@ -1,41 +1,11 @@ (ns status-im2.contexts.shell.bottom-tabs - (:require [reagent.core :as reagent] - [re-frame.core :as re-frame] - [react-native.core :as rn] + (:require [react-native.core :as rn] + [react-native.reanimated :as reanimated] [status-im2.contexts.shell.style :as styles] [status-im2.contexts.shell.constants :as constants] [status-im2.contexts.shell.animation :as animation] [quo2.components.navigation.bottom-nav-tab :as bottom-nav-tab])) -;; Reagent atoms used for lazily loading home screen tabs -(def load-communities-tab? (reagent/atom false)) -(def load-chats-tab? (reagent/atom false)) -(def load-wallet-tab? (reagent/atom false)) -(def load-browser-tab? (reagent/atom false)) - -(defn load-selected-stack [stack-id] - (case stack-id - :communities-stack (reset! load-communities-tab? true) - :chats-stack (reset! load-chats-tab? true) - :wallet-stack (reset! load-wallet-tab? true) - :browser-stack (reset! load-browser-tab? true) - "")) - -(re-frame/reg-fx - :new-ui/reset-bottom-tabs - (fn [] - (let [selected-stack-id @animation/selected-stack-id] - (reset! load-communities-tab? (= selected-stack-id :communities-stack)) - (reset! load-chats-tab? (= selected-stack-id :chats-stack)) - (reset! load-wallet-tab? (= selected-stack-id :wallet-stack)) - (reset! load-browser-tab? (= selected-stack-id :browser-stack))))) - -(defn bottom-tab-on-press [shared-values stack-id] - (when-not (= stack-id @animation/selected-stack-id) - (let [stack-load-delay (if @animation/home-stack-open? 0 constants/shell-animation-time)] - (animation/bottom-tab-on-press shared-values stack-id) - (js/setTimeout #(load-selected-stack stack-id) stack-load-delay)))) - (defn bottom-tab [icon stack-id shared-values] [bottom-nav-tab/bottom-nav-tab {:test-ID stack-id @@ -43,14 +13,21 @@ :icon-color-anim (get shared-values (get constants/tabs-icon-color-keywords stack-id)) - :on-press #(bottom-tab-on-press shared-values stack-id) + :on-press #(animation/bottom-tab-on-press stack-id) :accessibility-label (str (name stack-id) "-tab")}]) -(defn bottom-tabs [shared-values] - (load-selected-stack @animation/selected-stack-id) - [rn/view {:style (styles/bottom-tabs-container false)} - [rn/view {:style (styles/bottom-tabs)} - [bottom-tab :i/communities :communities-stack shared-values] - [bottom-tab :i/messages :chats-stack shared-values] - [bottom-tab :i/wallet :wallet-stack shared-values] - [bottom-tab :i/browser :browser-stack shared-values]]]) +(defn bottom-tabs [] + [:f> + (fn [] + (let [shared-values @animation/shared-values-atom + original-style (styles/bottom-tabs-container @animation/pass-through?) + animated-style (reanimated/apply-animations-to-style + {:height (:bottom-tabs-height shared-values)} + original-style)] + (animation/load-stack @animation/selected-stack-id) + [reanimated/view {:style animated-style} + [rn/view {:style (styles/bottom-tabs)} + [bottom-tab :i/communities :communities-stack shared-values] + [bottom-tab :i/messages :chats-stack shared-values] + [bottom-tab :i/wallet :wallet-stack shared-values] + [bottom-tab :i/browser :browser-stack shared-values]]]))]) diff --git a/src/status_im2/contexts/shell/cards/style.cljs b/src/status_im2/contexts/shell/cards/style.cljs index 6975c09abd..6dedcc6840 100644 --- a/src/status_im2/contexts/shell/cards/style.cljs +++ b/src/status_im2/contexts/shell/cards/style.cljs @@ -16,7 +16,7 @@ :border-radius 16 :background-color (colors/alpha background-color 0.4)}) -(defn secondary-container [] +(def secondary-container {:width 160 :height 120 :border-radius 16 @@ -24,29 +24,29 @@ :position :absolute :background-color (:secondary-container-bg-color colors-map)}) -(defn title [] +(def title {:position :absolute :top 28 :margin-horizontal 12 :color (:title-color colors-map)}) -(defn title-props [] +(def title-props {:size :paragraph-1 :weight :semi-bold :number-of-lines 1 :ellipsize-mode :tail - :style (title)}) + :style title}) -(defn subtitle [] +(def subtitle {:position :absolute :top 50 :margin-horizontal 12 :color (:subtitle-color colors-map)}) -(defn subtitle-props [] +(def subtitle-props {:size :paragraph-2 :weight :medium - :style (subtitle)}) + :style subtitle}) (defn content-container [new-notifications?] {:position :absolute @@ -56,7 +56,7 @@ :margin-left 12 :margin-right (if new-notifications? 8 12)}) -(defn notification-container [] +(def notification-container {:position :absolute :width 20 :height 20 @@ -65,17 +65,17 @@ :justify-content :center :align-items :center}) -(defn last-message-text [] +(def last-message-text {:color (:last-message-text-color colors-map)}) -(defn last-message-text-props [] +(def last-message-text-props {:size :paragraph-2 :weight :regular :number-of-lines 1 :ellipsize-mode :tail - :style (last-message-text)}) + :style last-message-text}) -(defn close-button [] +(def close-button {:position :absolute :right 8 :top 8 @@ -88,14 +88,19 @@ :icon true :on-press on-press :override-theme :dark - :style (close-button)}) + :style close-button}) -(defn avatar-container [] - {:width 48 - :height 48 - :left 12 - :top 12 - :position :absolute}) +(def avatar-container + {:width 48 + :height 48 + :left 12 + :top 12 + :border-radius 26 + :border-width 26 + :border-color colors/neutral-95 + :justify-content :center + :align-items :center + :position :absolute}) (defn unread-dot [background-color] {:width 8 @@ -105,27 +110,33 @@ ;; Supporting Components -(defn sticker [] +(def sticker {:width 24 :height 24}) -(defn gif [] +(def gif {:width 24 :height 24 :border-radius 8}) -(defn community-avatar [] - {:width 48 - :height 48 - :border-radius 24}) +(defn community-avatar [customization-color] + {:width 48 + :height 48 + :border-radius 24 + ;; TODO - Update to fall back community avatar once designs are available + :justify-content :center + :align-items :center + :background-color (colors/custom-color + (or customization-color :primary) + 60)}) -(defn community-channel [] +(def community-channel {:margin-left 8 :color (:community-channel colors-map)}) -(defn community-channel-props [] +(def community-channel-props {:size :paragraph-2 :weight :medium :number-of-lines 1 :ellipsize-mode :tail - :style (community-channel)}) + :style community-channel}) diff --git a/src/status_im2/contexts/shell/cards/view.cljs b/src/status_im2/contexts/shell/cards/view.cljs index 399cfc03f6..284284501e 100644 --- a/src/status_im2/contexts/shell/cards/view.cljs +++ b/src/status_im2/contexts/shell/cards/view.cljs @@ -1,44 +1,40 @@ (ns status-im2.contexts.shell.cards.view - (:require [i18n.i18n :as i18n] + (:require [quo2.core :as quo] + [i18n.i18n :as i18n] [react-native.core :as rn] - [react-native.fast-image :as fast-image] + [clojure.string :as string] [quo2.foundations.colors :as colors] - [quo2.components.markdown.text :as text] - [quo2.components.buttons.button :as button] - [quo2.components.counter.counter :as counter] - [quo2.components.tags.status-tags :as status-tags] - [quo2.components.avatars.user-avatar :as user-avatar] - [quo2.components.avatars.group-avatar :as group-avatar] - [quo2.components.list-items.preview-list :as preview-list] - [quo2.components.avatars.channel-avatar :as channel-avatar] - [status-im2.contexts.shell.cards.style :as style])) + [react-native.fast-image :as fast-image] + [status-im2.contexts.shell.cards.style :as style] + [status-im2.contexts.shell.constants :as constants])) (defn content-container [{:keys [content-type data new-notifications? color-50]}] [rn/view {:style (style/content-container new-notifications?)} + ;; TODO - Use status-im.constants for content type (case content-type - :text [text/text (style/last-message-text-props) data] - :photo [preview-list/preview-list {:type :photo - :more-than-99-label (i18n/label :counter-99-plus) - :size 24 - :override-theme :dark} data] + :text [quo/text style/last-message-text-props data] + :photo [quo/preview-list {:type :photo + :more-than-99-label (i18n/label :counter-99-plus) + :size 24 + :override-theme :dark} data] :sticker [fast-image/fast-image {:source (:source data) - :style (style/sticker)}] + :style style/sticker}] :gif [fast-image/fast-image {:source (:source data) - :style (style/gif)}] + :style style/gif}] :channel [rn/view {:style {:flex-direction :row :align-items :center}} - [channel-avatar/channel-avatar + [quo/channel-avatar {:emoji (:emoji data) :emoji-background-color (colors/alpha color-50 0.1)}] - [text/text (style/community-channel-props) (:channel-name data)]] + [quo/text style/community-channel-props (:channel-name data)]] :community-info (case (:type data) - :pending [status-tags/status-tag - {:status :pending + :pending [quo/status-tag + {:status {:type :pending} :label (i18n/label :t/pending) :size :small :override-theme :dark}] - :kicked [status-tags/status-tag - {:status :negative + :kicked [quo/status-tag + {:status {:type :negative} :size :small :override-theme :dark :label (i18n/label :t/kicked)}] @@ -47,11 +43,11 @@ [:<>])]) (defn notification-container [{:keys [notification-indicator counter-label color-60]}] - [rn/view {:style (style/notification-container)} + [rn/view {:style style/notification-container} (if (= notification-indicator :counter) - [counter/counter {:outline false - :override-text-color colors/white - :override-bg-color color-60} counter-label] + [quo/counter {:outline false + :override-text-color colors/white + :override-bg-color color-60} counter-label] [rn/view {:style (style/unread-dot color-60)}])]) (defn bottom-container [{:keys [new-notifications?] :as content}] @@ -62,16 +58,29 @@ (defn avatar [avatar-params type customization-color] (case type - :messaging [user-avatar/user-avatar - (merge {:ring? false - :size :medium - :status-indicator? false} - avatar-params)] - :group-messaging [group-avatar/group-avatar {:color customization-color - :size :large - :override-theme :dark}] - :community-card [fast-image/fast-image {:source (:source avatar-params) - :style (style/community-avatar)}])) + constants/one-to-one-chat-card + [quo/user-avatar + (merge {:ring? false + :size :medium + :status-indicator? false} + avatar-params)] + + constants/private-group-chat-card + [quo/group-avatar {:color customization-color + :size :large + :override-theme :dark}] + + constants/community-card + (if (:source avatar-params) + [fast-image/fast-image + {:source (:source avatar-params) + :style (style/community-avatar customization-color)}] + ;; TODO - Update to fall back community avatar once designs are available + [rn/view {:style (style/community-avatar customization-color)} + [quo/text {:weight :semi-bold + :size :heading-2 + :style {:color colors/white-opa-70}} + (string/upper-case (first (:name avatar-params)))]]))) (defn subtitle [{:keys [content-type data]}] (case content-type @@ -84,7 +93,8 @@ :link (i18n/label :t/external-link) :code (i18n/label :t/code-snippet) :channel (i18n/label :t/community-channel) - :community-info (i18n/label :t/community))) + :community-info (i18n/label :t/community) + (i18n/label :t/community))) ;; Screens Card (defn screens-card [{:keys [avatar-params title type customization-color @@ -96,14 +106,14 @@ (when banner [rn/image {:source (:source banner) :style {:width 160}}]) - [rn/view {:style (style/secondary-container)} - [text/text (style/title-props) title] - [text/text (style/subtitle-props) (subtitle content)] + [rn/view {:style style/secondary-container} + [quo/text style/title-props title] + [quo/text style/subtitle-props (subtitle content)] [bottom-container (merge {:color-50 color-50 :color-60 color-60} content)]] - (when avatar - [rn/view {:style (style/avatar-container)} + (when avatar-params + [rn/view {:style style/avatar-container} [avatar avatar-params type customization-color]]) - [button/button (style/close-button-props on-close) :i/close]]])) + [quo/button (style/close-button-props on-close) :i/close]]])) ;; browser Card (defn browser-card [_] @@ -123,13 +133,28 @@ (defn communities-discover [_] [:<>]) -(defn card [type data] +(defn card [{:keys [type] :as data}] (case type - :communities-discover [communities-discover data] ;; Home Card - :messaging [screens-card data] ;; Screens Card - :group-messaging [screens-card data] ;; Screens Card - :community-card [screens-card data] ;; Screens Card - :browser-card [browser-card data] ;; Browser Card - :wallet-card [wallet-card data] ;; Wallet Card - :wallet-collectible [wallet-collectible data] ;; Wallet Card - :wallet-graph [wallet-graph data])) ;; Wallet Card + constants/one-to-one-chat-card ;; Screens Card + [screens-card data] + + constants/private-group-chat-card ;; Screens Card + [screens-card data] + + constants/community-card ;; Screens Card + [screens-card data] + + constants/browser-card ;; Browser Card + [browser-card data] + + constants/wallet-card ;; Wallet Card + [wallet-card data] + + constants/wallet-collectible ;; Wallet Card + [wallet-collectible data] + + constants/wallet-graph ;; Wallet Card + [wallet-graph data] + + constants/communities-discover ;; Home Card + [communities-discover data])) diff --git a/src/status_im2/contexts/shell/constants.cljs b/src/status_im2/contexts/shell/constants.cljs index 1ecffea652..514c76a4b1 100644 --- a/src/status_im2/contexts/shell/constants.cljs +++ b/src/status_im2/contexts/shell/constants.cljs @@ -8,6 +8,9 @@ (defn bottom-tabs-container-height [] (if platform/android? 57 82)) +(defn bottom-tabs-extended-container-height [] + (if platform/android? 90 120)) + (defn status-bar-offset [] (if platform/android? (.-currentHeight ^js rn/status-bar) 0)) @@ -39,3 +42,20 @@ :chats-stack :chats-tab-icon-opacity :wallet-stack :wallet-tab-icon-opacity :browser-stack :browser-tab-icon-opacity}) + +;; Home stack states + +(def ^:const close-with-animation 0) +(def ^:const open-with-animation 1) +(def ^:const close-without-animation 3) +(def ^:const open-without-animation 4) + +;; Switcher Cards +(def ^:const one-to-one-chat-card 0) +(def ^:const private-group-chat-card 1) +(def ^:const community-card 2) +(def ^:const browser-card 3) +(def ^:const wallet-card 4) +(def ^:const wallet-collectible 5) +(def ^:const wallet-graph 6) +(def ^:const communities-discover 7) diff --git a/src/status_im2/contexts/shell/events.cljs b/src/status_im2/contexts/shell/events.cljs new file mode 100644 index 0000000000..c92f215ee4 --- /dev/null +++ b/src/status_im2/contexts/shell/events.cljs @@ -0,0 +1,90 @@ +(ns status-im2.contexts.shell.events + (:require [utils.re-frame :as rf] + [re-frame.core :as re-frame] + [status-im2.navigation.events :as navigation] + [status-im.constants :as constants] + [status-im2.contexts.shell.animation :as animation] + [status-im2.contexts.shell.constants :as shell.constants])) + +;; Effects + +(re-frame/reg-fx + :shell/navigate-to-jump-to-fx + (fn [] + (animation/close-home-stack false))) + +(re-frame/reg-fx + :shell/navigate-from-shell-fx + (fn [stack-id] + (js/setTimeout #(animation/bottom-tab-on-press stack-id) 500))) + +(re-frame/reg-fx + :shell/reset-bottom-tabs + (fn [] + (let [selected-stack-id @animation/selected-stack-id] + (reset! animation/load-communities-stack? (= selected-stack-id :communities-stack)) + (reset! animation/load-chats-stack? (= selected-stack-id :chats-stack)) + (reset! animation/load-wallet-stack? (= selected-stack-id :wallet-stack)) + (reset! animation/load-browser-stack? (= selected-stack-id :browser-stack))))) + +;; Events + +(rf/defn add-switcher-card + {:events [:shell/add-switcher-card]} + [{:keys [db now] :as cofx} view-id id] + (case view-id + :chat + (let [chat (get-in db [:chats id])] + (case (:chat-type chat) + constants/one-to-one-chat-type + {:shell/navigate-from-shell-fx :chats-stack + :db (assoc-in + db [:shell/switcher-cards id] + {:type shell.constants/one-to-one-chat-card + :id id + :clock now})} + + constants/private-group-chat-type + {:shell/navigate-from-shell-fx :chats-stack + :db (assoc-in + db [:shell/switcher-cards id] + {:type shell.constants/private-group-chat-card + :id id + :clock now})} + + constants/community-chat-type + {:shell/navigate-from-shell-fx :communities-stack + :db (assoc-in + db [:shell/switcher-cards (:community-id chat)] + {:type shell.constants/community-card + :id (:community-id chat) + :clock now + :content {:content-type :channel + :data {:emoji (:emoji chat) + :channel-id (:chat-id chat) + :channel-name (:chat-name chat)}}})} + + nil)) + + :community + {:shell/navigate-from-shell-fx :communities-stack + :db (assoc-in + db [:shell/switcher-cards (:community-id id)] + {:type shell.constants/community-card + :id (:community-id id) + :clock now})} + + nil)) + +(rf/defn close-switcher-card + {:events [:shell/close-switcher-card]} + [{:keys [db]} id] + {:db (update-in db [:shell/switcher-cards] dissoc id)}) + +(rf/defn navigate-to-jump-to + {:events [:shell/navigate-to-jump-to]} + [cofx] + (rf/merge + cofx + {:shell/navigate-to-jump-to-fx nil} + (navigation/pop-to-root-tab :shell-stack))) diff --git a/src/status_im2/contexts/shell/home_stack.cljs b/src/status_im2/contexts/shell/home_stack.cljs index 67be1f5c60..edd9fc5559 100644 --- a/src/status_im2/contexts/shell/home_stack.cljs +++ b/src/status_im2/contexts/shell/home_stack.cljs @@ -2,8 +2,8 @@ (:require [react-native.reanimated :as reanimated] [react-native.core :as rn] [status-im2.contexts.shell.style :as styles] + [status-im2.contexts.shell.animation :as animation] [status-im2.contexts.shell.constants :as constants] - [status-im2.contexts.shell.bottom-tabs :as bottom-tabs] [status-im2.contexts.communities.home.view :as communities] [status-im2.contexts.chat.home.view :as chat] @@ -14,10 +14,10 @@ (defn load-stack? [stack-id] (case stack-id - :communities-stack @bottom-tabs/load-communities-tab? - :chats-stack @bottom-tabs/load-chats-tab? - :browser-stack @bottom-tabs/load-browser-tab? - :wallet-stack @bottom-tabs/load-wallet-tab?)) + :communities-stack @animation/load-communities-stack? + :chats-stack @animation/load-chats-stack? + :browser-stack @animation/load-browser-stack? + :wallet-stack @animation/load-wallet-stack?)) (defn stack-view [stack-id shared-values] (when (load-stack? stack-id) @@ -39,12 +39,13 @@ :wallet-stack [wallet.accounts/accounts-overview] :browser-stack [profile.user/my-profile])])])) -(defn home-stack [shared-values] +(defn home-stack [] [safe-area/consumer (fn [insets] [:f> (fn [] - (let [home-stack-original-style (styles/home-stack) + (let [shared-values @animation/shared-values-atom + home-stack-original-style (styles/home-stack) home-stack-animated-style (reanimated/apply-animations-to-style {:top (:home-stack-top shared-values) :left (:home-stack-left shared-values) diff --git a/src/status_im2/contexts/shell/view.cljs b/src/status_im2/contexts/shell/view.cljs index 5006abc808..de2d6e1c9e 100644 --- a/src/status_im2/contexts/shell/view.cljs +++ b/src/status_im2/contexts/shell/view.cljs @@ -1,17 +1,20 @@ (ns status-im2.contexts.shell.view - (:require [i18n.i18n :as i18n] + (:require [quo2.core :as quo] + [i18n.i18n :as i18n] + [utils.re-frame :as rf] [react-native.core :as rn] - [react-native.safe-area :as safe-area] - [quo2.core :as quo] [quo2.foundations.colors :as colors] + [react-native.safe-area :as safe-area] + [status-im2.common.home.view :as common.home] [status-im2.contexts.shell.constants :as constants] [status-im2.contexts.shell.animation :as animation] [status-im2.contexts.shell.home-stack :as home-stack] [status-im2.contexts.shell.bottom-tabs :as bottom-tabs] - [status-im2.common.home.view :as common.home])) - -;;TODO move styles to style namespace + [status-im2.contexts.shell.cards.view :as switcher-cards])) +;; TODO +;; 1 : Update Placeholder screen as per new designs +;; 2 : Move styles to style namespace (defn placeholder [] [rn/view {:style {:position :absolute :top 0 @@ -38,38 +41,77 @@ :color colors/white}} (i18n/label :t/shell-placeholder-subtitle)]]) +(defn jump-to-text [] + [quo/text {:size :heading-1 + :weight :semi-bold + :style {:color colors/white + :margin-top (+ 68 (.-currentHeight ^js rn/status-bar)) + :margin-bottom 20 + :margin-left 20}} + (i18n/label :t/jump-to)]) + +(defn render-card [{:keys [id type content] :as card}] + (let [card-data (case type + constants/one-to-one-chat-card + (rf/sub [:shell/one-to-one-chat-card id]) + + constants/private-group-chat-card + (rf/sub [:shell/private-group-chat-card id]) + + constants/community-card + (if content + (rf/sub [:shell/community-channel-card + id (get-in content [:data :channel-id]) + content]) + (rf/sub [:shell/community-card id])))] + [switcher-cards/card (merge card card-data)])) + +(defn jump-to-list [switcher-cards shell-margin] + (if (seq switcher-cards) + [rn/flat-list + {:data switcher-cards + :render-fn render-card + :key-fn :id + :header (jump-to-text) + :num-columns 2 + :column-wrapper-style {:margin-horizontal shell-margin + :justify-content :space-between + :margin-bottom 16} + :style {:top 0 + :left 0 + :right 0 + :bottom -1 + :position :absolute}}] + [placeholder])) + (defn shell [] - [safe-area/consumer - (fn [insets] - [rn/view {:style {:top 0 - :left 0 - :right 0 - :bottom -1 - :position :absolute - :background-color colors/neutral-100}} - [common.home/top-nav {:type :shell - :style {:margin-top (:top insets)}}] - [placeholder] - [rn/scroll-view {:style {:padding-horizontal 20 - :flex-direction :row}} - [quo/text {:size :heading-1 - :weight :semi-bold - :style {:color colors/white - :margin-top 12}} - (i18n/label :t/jump-to)]]])]) + (let [switcher-cards (rf/sub [:shell/sorted-switcher-cards]) + width (rf/sub [:dimensions/window-width]) + shell-margin (/ (- width 320) 3)] ;; 320 - two cards width + [safe-area/consumer + (fn [insets] + [rn/view {:style {:top 0 + :left 0 + :right 0 + :bottom -1 + :position :absolute + :background-color colors/neutral-100}} + [common.home/top-nav {:type :shell + :style {:margin-top (:top insets) + :z-index 2}}] + [jump-to-list switcher-cards shell-margin]])])) (defn shell-stack [] [:f> (fn [] - (let [shared-values (animation/get-shared-values)] + (let [shared-values (animation/calculate-shared-values)] [:<> [shell] - [bottom-tabs/bottom-tabs shared-values] - [home-stack/home-stack shared-values] + [bottom-tabs/bottom-tabs] + [home-stack/home-stack] [quo/floating-shell-button - {:jump-to {:on-press #(animation/close-home-stack shared-values) - :label (i18n/label :t/jump-to)}} + {:jump-to {:on-press #(animation/close-home-stack true) + :label (i18n/label :t/jump-to)}} {:position :absolute :bottom (+ (constants/bottom-tabs-container-height) 7)} ;; bottom offset is 12 = 7 + 5(padding on button) - (:home-stack-opacity shared-values) - (:home-stack-pointer shared-values)]]))]) + (:home-stack-opacity shared-values)]]))]) diff --git a/src/status_im2/navigation/events.cljs b/src/status_im2/navigation/events.cljs index e2eced61a5..561f1b7c01 100644 --- a/src/status_im2/navigation/events.cljs +++ b/src/status_im2/navigation/events.cljs @@ -104,34 +104,16 @@ (rf/defn reload-new-ui {:events [:reload-new-ui]} [_] - {:new-ui/reset-bottom-tabs nil + {:shell/reset-bottom-tabs nil :dispatch [:init-root :shell-stack]}) -(defn navigate-from-shell-stack [go-to-view-id id db now] - {:navigate-to-fx go-to-view-id - :db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id - :id id - :clock now})}) - -(defn navigate-from-switcher [go-to-view-id id db from-home? now] - (merge (if from-home? - {:navigate-to-fx go-to-view-id} - {:set-stack-root-fx [go-to-view-id id]}) - {:db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id - :id id - :clock now})})) - (rf/defn navigate-to-nav2 {:events [:navigate-to-nav2]} - [{:keys [db now]} go-to-view-id id _ from-switcher?] - (let [view-id (:view-id db) - from-home? (= view-id :chat-stack)] - (if from-switcher? - (navigate-from-switcher go-to-view-id id db from-home? now) - (if from-home? - (navigate-from-shell-stack go-to-view-id id db now) - ;; TODO(parvesh) - new stacks created from other screens should be stacked on current stack, instead of creating new entry - (navigate-from-shell-stack go-to-view-id id db now))))) + [cofx view-id screen-params from-shell?] + (rf/merge + cofx + {:dispatch [:shell/add-switcher-card view-id screen-params from-shell?]} + (navigate-to-cofx view-id screen-params))) (rf/defn change-root-status-bar-style {:events [:change-root-status-bar-style]} diff --git a/src/status_im2/subs/general.cljs b/src/status_im2/subs/general.cljs index 434df97750..a316ad48ad 100644 --- a/src/status_im2/subs/general.cljs +++ b/src/status_im2/subs/general.cljs @@ -286,21 +286,6 @@ (fn [{:keys [mnemonic]}] (if mnemonic 1 0))) -;; NAVIGATION2 - -(re-frame/reg-sub - :navigation2/switcher-cards - :<- [:navigation2/navigation2-stacks] - (fn [stacks [_ toggle-switcher-screen]] - (sort-by :clock > - (reduce (fn [acc stack-vector] - (let [{:keys [type clock id]} (get stack-vector 1)] - (conj acc {:type type - :clock clock - :id id - :toggle-switcher-screen toggle-switcher-screen}))) - '() stacks)))) - (re-frame/reg-sub :mobile-network/syncing-allowed? :<- [:network/type] diff --git a/src/status_im2/subs/root.cljs b/src/status_im2/subs/root.cljs index e25617da8e..a9cfed6da0 100644 --- a/src/status_im2/subs/root.cljs +++ b/src/status_im2/subs/root.cljs @@ -18,6 +18,7 @@ status-im2.subs.pairing status-im2.subs.search status-im2.subs.stickers + status-im2.subs.shell status-im2.subs.wallet.signing status-im2.subs.wallet.transactions status-im2.subs.wallet.wallet)) @@ -64,7 +65,7 @@ (reg-root-key-sub :home-items-show-number :home-items-show-number) (reg-root-key-sub :waku/v2-peer-stats :peer-stats) (reg-root-key-sub :visibility-status-updates :visibility-status-updates) -(reg-root-key-sub :navigation2/navigation2-stacks :navigation2/navigation2-stacks) +(reg-root-key-sub :shell/switcher-cards :shell/switcher-cards) ;;NOTE this one is not related to ethereum network ;; it is about cellular network/ wifi network diff --git a/src/status_im2/subs/shell.cljs b/src/status_im2/subs/shell.cljs new file mode 100644 index 0000000000..0b4063920e --- /dev/null +++ b/src/status_im2/subs/shell.cljs @@ -0,0 +1,99 @@ +(ns status-im2.subs.shell + (:require [re-frame.core :as re-frame] + [status-im.constants :as status-constants] + [status-im.react-native.resources :as resources])) + +(defn get-card-content [chat] + (let [last-message (:last-message chat)] + (case (:content-type last-message) + status-constants/content-type-text + {:content-type :text + :data (get-in last-message [:content :text])} + + {:content-type :text + :data "Todo: Implement"}))) + +(defn one-to-one-chat-card [contact names chat id] + (let [images (:images contact) + profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))] + {:title (first names) + :avatar-params {:full-name (last names) + :profile-picture (when profile-picture + (str profile-picture "&addRing=0"))} + :customization-color (or (:customization-color contact) :primary) + :on-close #(re-frame/dispatch [:shell/close-switcher-card id]) + :on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 id true]) + :content (get-card-content chat)})) + +(defn private-group-chat-card [chat id] + {:title (:chat-name chat) + :avatar-params {} + :customization-color (or (:customization-color chat) :primary) + :on-close #(re-frame/dispatch [:shell/close-switcher-card id]) + :on-press #(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 id true]) + :content (get-card-content chat)}) + +(defn community-card [community id content] + (let [images (:images community) + profile-picture (if (= id status-constants/status-community-id) + (resources/get-image :status-logo) + (when images + {:uri (:uri (or (:thumbnail images) + (:large images) + (first images)))}))] + {:title (:name community) + :avatar-params (if profile-picture + {:source profile-picture} + {:name (:name community)}) + :customization-color (or (:customization-color community) :primary) + :on-close #(re-frame/dispatch [:shell/close-switcher-card id]) + :on-press #(re-frame/dispatch [:navigate-to-nav2 :community + {:community-id id} true]) + :content (or content {:content-type :community-info + :data {:type :permission}})})) + +(defn community-channel-card [community community-id _ channel-id content] + (merge + (community-card community community-id content) + {:on-press (fn [] + (re-frame/dispatch [:navigate-to :community {:community-id community-id}]) + (js/setTimeout + #(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 channel-id true]) + 100))})) + +(re-frame/reg-sub + :shell/sorted-switcher-cards + :<- [:shell/switcher-cards] + (fn [stacks] + (sort-by :clock > (map val stacks)))) + +(re-frame/reg-sub + :shell/one-to-one-chat-card + (fn [[_ id] _] + [(re-frame/subscribe [:contacts/contact-by-identity id]) + (re-frame/subscribe [:contacts/contact-two-names-by-identity id]) + (re-frame/subscribe [:chats/chat id])]) + (fn [[contact names chat] [_ id]] + (one-to-one-chat-card contact names chat id))) + +(re-frame/reg-sub + :shell/private-group-chat-card + (fn [[_ id] _] + [(re-frame/subscribe [:chats/chat id])]) + (fn [[chat] [_ id]] + (private-group-chat-card chat id))) + +(re-frame/reg-sub + :shell/community-card + (fn [[_ id] _] + [(re-frame/subscribe [:communities/community id])]) + (fn [[community] [_ id]] + (community-card community id nil))) + +(re-frame/reg-sub + :shell/community-channel-card + (fn [[_ community-id channel-id _] _] + [(re-frame/subscribe [:communities/community community-id]) + (re-frame/subscribe [:chats/chat channel-id])]) + (fn [[community channel] [_ community-id channel-id content]] + (community-channel-card community community-id channel channel-id content)))