Shell navigation and animations
This commit is contained in:
parent
fbe4b0a36c
commit
bcc20c7458
|
@ -1,186 +0,0 @@
|
|||
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 stackZIndex (stackId, selectedStackId) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
return selectedStackId.value == stackId ? 10 : 9;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import { useDerivedValue, withTiming } from 'react-native-reanimated';
|
||||
import * as constants from './constants';
|
||||
|
||||
export function bottomTabIconColor(stackId, selectedStackId, homeStackState,
|
||||
passThrough, selectedTabColor, defaultColor,
|
||||
passThroughColor) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
var homeStackStateValue = homeStackState.value;
|
||||
if (selectedStackId.value == stackId &&
|
||||
(homeStackStateValue == constants.OPEN_WITH_ANIMATION ||
|
||||
homeStackStateValue == constants.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 constants.OPEN_WITH_ANIMATION:
|
||||
return withTiming(extendedHeight, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.CLOSE_WITH_ANIMATION:
|
||||
return withTiming(height, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.OPEN_WITHOUT_ANIMATION:
|
||||
return extendedHeight;
|
||||
break;
|
||||
case constants.CLOSE_WITHOUT_ANIMATION:
|
||||
return height;
|
||||
break;
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
import { Easing } from 'react-native-reanimated';
|
||||
|
||||
// Home Stack States
|
||||
export const CLOSE_WITH_ANIMATION = 0;
|
||||
export const OPEN_WITH_ANIMATION = 1;
|
||||
export const CLOSE_WITHOUT_ANIMATION = 2;
|
||||
export const OPEN_WITHOUT_ANIMATION = 3;
|
||||
|
||||
// Floating Screen States
|
||||
export const CLOSE_SCREEN_WITH_SLIDE_ANIMATION = 0;
|
||||
export const OPEN_SCREEN_WITH_SLIDE_ANIMATION = 1;
|
||||
export const CLOSE_SCREEN_WITH_SHELL_ANIMATION = 2;
|
||||
export const OPEN_SCREEN_WITH_SHELL_ANIMATION = 3;
|
||||
export const CLOSE_SCREEN_WITHOUT_ANIMATION = 4;
|
||||
export const OPEN_SCREEN_WITHOUT_ANIMATION = 5;
|
||||
|
||||
export const SHELL_ANIMATION_TIME = 200;
|
||||
|
||||
export const LINEAR_EASING = {
|
||||
duration: SHELL_ANIMATION_TIME,
|
||||
easing: Easing.bezier(0, 0, 1, 1),
|
||||
}
|
||||
|
||||
export const EASE_OUT_EASING = {
|
||||
duration: SHELL_ANIMATION_TIME,
|
||||
easing: Easing.bezier(0, 0, 0.58, 1),
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated';
|
||||
import * as constants from './constants';
|
||||
|
||||
// Derived Values
|
||||
export function screenLeft (screenState, screenWidth, switcherCardLeftPosition) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (screenState.value) {
|
||||
case constants.CLOSE_SCREEN_WITH_SLIDE_ANIMATION:
|
||||
return withTiming(screenWidth, constants.EASE_OUT_EASING);
|
||||
case constants.OPEN_SCREEN_WITH_SLIDE_ANIMATION:
|
||||
return withTiming(0, constants.EASE_OUT_EASING);
|
||||
case constants.CLOSE_SCREEN_WITHOUT_ANIMATION:
|
||||
return screenWidth;
|
||||
case constants.OPEN_SCREEN_WITHOUT_ANIMATION:
|
||||
// Note - don't use return 0; its not working in ios
|
||||
// https://github.com/software-mansion/react-native-reanimated/issues/3296#issuecomment-1573900172
|
||||
return withSequence(withTiming(-1, {duration: 0}), withTiming(0, {duration: 0}));
|
||||
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(switcherCardLeftPosition, constants.EASE_OUT_EASING);
|
||||
case constants.OPEN_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(0, constants.EASE_OUT_EASING);
|
||||
default:
|
||||
return screenWidth;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function screenTop (screenState, switcherCardTopPosition) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (screenState.value) {
|
||||
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(switcherCardTopPosition, constants.EASE_OUT_EASING);
|
||||
case constants.OPEN_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(0, constants.EASE_OUT_EASING);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function screenWidth (screenState, screenWidth, switcherCardSize) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (screenState.value) {
|
||||
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(switcherCardSize, constants.EASE_OUT_EASING);
|
||||
case constants.OPEN_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withSequence(withTiming(switcherCardSize, {duration: 0}), withTiming(screenWidth, constants.EASE_OUT_EASING));
|
||||
default:
|
||||
return screenWidth;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function screenHeight (screenState, screenHeight, switcherCardSize) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (screenState.value) {
|
||||
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withTiming(switcherCardSize, constants.EASE_OUT_EASING);
|
||||
case constants.OPEN_SCREEN_WITH_SHELL_ANIMATION:
|
||||
return withSequence(withTiming(switcherCardSize, {duration: 0}), withTiming(screenHeight, constants.EASE_OUT_EASING));
|
||||
default:
|
||||
return screenHeight;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function screenZIndex (screenState) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (screenState.value) {
|
||||
case constants.CLOSE_SCREEN_WITH_SHELL_ANIMATION:
|
||||
case constants.CLOSE_SCREEN_WITH_SLIDE_ANIMATION:
|
||||
return withDelay(constants.SHELL_ANIMATION_TIME, withTiming(-1, {duration: 0}));
|
||||
case constants.CLOSE_SCREEN_WITHOUT_ANIMATION:
|
||||
return -1;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
import { useDerivedValue, withTiming, withSequence } from 'react-native-reanimated';
|
||||
import * as constants from './constants';
|
||||
|
||||
// Derived values for each stack (communities, chat, wallet, browser)
|
||||
export function stackOpacity (stackId, selectedStackId) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
return selectedStackId.value == stackId ? 1 : 0;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function stackZIndex (stackId, selectedStackId) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
return selectedStackId.value == stackId ? 10 : 9;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Derived values for home stack (container)
|
||||
export function homeStackOpacity (homeStackState) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (homeStackState.value) {
|
||||
case constants.OPEN_WITH_ANIMATION:
|
||||
return withTiming(1, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.CLOSE_WITH_ANIMATION:
|
||||
return withTiming(0, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.OPEN_WITHOUT_ANIMATION:
|
||||
return 1;
|
||||
break;
|
||||
case constants.CLOSE_WITHOUT_ANIMATION:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function homeStackTop (homeStackState, top) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (homeStackState.value) {
|
||||
case constants.OPEN_WITH_ANIMATION:
|
||||
return withTiming(0, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.CLOSE_WITH_ANIMATION:
|
||||
return withTiming(top, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.OPEN_WITHOUT_ANIMATION:
|
||||
return 0;
|
||||
break;
|
||||
case constants.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 constants.OPEN_WITH_ANIMATION:
|
||||
return withSequence(withTiming(leftValue, {duration: 0}), withTiming(0, constants.LINEAR_EASING))
|
||||
break;
|
||||
case constants.CLOSE_WITH_ANIMATION:
|
||||
return withTiming(leftValue, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.OPEN_WITHOUT_ANIMATION:
|
||||
return 0;
|
||||
break;
|
||||
case constants.CLOSE_WITHOUT_ANIMATION:
|
||||
return leftValue;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function homeStackPointer (homeStackState) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
var homeStackStateValue = homeStackState.value;
|
||||
return (homeStackStateValue == constants.OPEN_WITH_ANIMATION ||
|
||||
homeStackStateValue == constants.OPEN_WITHOUT_ANIMATION) ? "auto" : "none";
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
export function homeStackScale (homeStackState, minimizeScale) {
|
||||
return useDerivedValue(
|
||||
function () {
|
||||
'worklet'
|
||||
switch (homeStackState.value) {
|
||||
case constants.OPEN_WITH_ANIMATION:
|
||||
return withTiming(1, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.CLOSE_WITH_ANIMATION:
|
||||
return withTiming(minimizeScale, constants.LINEAR_EASING);
|
||||
break;
|
||||
case constants.OPEN_WITHOUT_ANIMATION:
|
||||
return 1;
|
||||
break;
|
||||
case constants.CLOSE_WITHOUT_ANIMATION:
|
||||
return minimizeScale;
|
||||
break;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
|
@ -405,7 +405,9 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
|||
"react-native-svg" react-native-svg
|
||||
"react-native-orientation-locker" react-native-orientation-locker
|
||||
"../src/js/worklets/core.js" worklet-factory
|
||||
"../src/js/worklets/shell.js" #js {}
|
||||
"../src/js/worklets/shell/bottom_tabs.js" #js {}
|
||||
"../src/js/worklets/shell/home_stack.js" #js {}
|
||||
"../src/js/worklets/shell/floating_screen.js" #js {}
|
||||
"../src/js/worklets/bottom_sheet.js" #js {}
|
||||
"../src/js/worklets/record_audio.js" #js {}
|
||||
"../src/js/worklets/scroll_view.js" #js {}
|
||||
|
|
|
@ -296,7 +296,7 @@
|
|||
(vals (get-in db [:communities community-id :chats])))]
|
||||
(when (and id
|
||||
(not= (:current-chat-id db) (str community-id id)))
|
||||
(chat.events/navigate-to-chat cofx (str community-id id)))))
|
||||
(chat.events/navigate-to-chat cofx (str community-id id) nil))))
|
||||
|
||||
(rf/defn fetch
|
||||
[_]
|
||||
|
|
|
@ -232,11 +232,6 @@
|
|||
[{:keys [db]} k v]
|
||||
{:db (assoc db k v)})
|
||||
|
||||
(rf/defn set-view-id
|
||||
{:events [:set-view-id]}
|
||||
[{:keys [db]} view-id]
|
||||
{:db (assoc db :view-id view-id)})
|
||||
|
||||
;;TODO :replace by named events
|
||||
(rf/defn set-once-event
|
||||
{:events [:set-once]}
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
{:events [:navigate-chat-updated]}
|
||||
[cofx chat-id]
|
||||
(when (get-in cofx [:db :chats chat-id])
|
||||
(chat.events/navigate-to-chat cofx chat-id)))
|
||||
(chat.events/navigate-to-chat cofx chat-id nil)))
|
||||
|
||||
(rf/defn handle-chat-removed
|
||||
{:events [:chat-removed]}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[status-im2.setup.hot-reload :as hot-reload]
|
||||
[status-im2.common.theme.core :as theme]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.contexts.shell.animation :as shell.animation]
|
||||
[status-im2.contexts.shell.utils :as shell.utils]
|
||||
[status-im.contact.db :as contact.db]))
|
||||
|
||||
;; validate that the given mnemonic was generated from Status Dictionary
|
||||
|
@ -135,7 +135,7 @@
|
|||
[:light :dark colors/white])]
|
||||
(theme/set-theme theme)
|
||||
(re-frame/dispatch [:change-shell-status-bar-style
|
||||
(if (shell.animation/home-stack-open?) status-bar-theme :light)])
|
||||
(if (shell.utils/home-stack-open?) status-bar-theme :light)])
|
||||
(when reload-ui?
|
||||
(rf/dispatch [:dissmiss-all-overlays])
|
||||
(hot-reload/reload)
|
||||
|
|
|
@ -42,9 +42,10 @@
|
|||
[status-im2.contexts.chat.messages.link-preview.events :as link-preview]
|
||||
[status-im2.contexts.contacts.events :as contacts]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.common.log :as logging]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im2.contexts.shell.animation :as shell.animation]
|
||||
[status-im2.contexts.shell.utils :as shell.utils]
|
||||
[utils.security.core :as security]))
|
||||
|
||||
(re-frame/reg-fx
|
||||
|
@ -458,7 +459,8 @@
|
|||
:key-uid
|
||||
(fn [stored-key-uid]
|
||||
(when (= stored-key-uid key-uid)
|
||||
(re-frame/dispatch [:chat/navigate-to-chat chat-id])))))))))
|
||||
(re-frame/dispatch [:chat/navigate-to-chat chat-id
|
||||
shell.constants/open-screen-without-animation])))))))))
|
||||
|
||||
(rf/defn check-last-chat
|
||||
{:events [::check-last-chat]}
|
||||
|
@ -552,7 +554,7 @@
|
|||
tos-accepted? (get db :tos/accepted?)
|
||||
{:networks/keys [current-network networks]} db
|
||||
network-id (str (get-in networks [current-network :config :NetworkId]))]
|
||||
(shell.animation/change-selected-stack-id :communities-stack true)
|
||||
(shell.utils/change-selected-stack-id :communities-stack true nil)
|
||||
(rf/merge cofx
|
||||
{:db (-> db
|
||||
(dissoc :multiaccounts/login)
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
(rf/merge cofx
|
||||
{:set-root :progress
|
||||
:chat.ui/clear-inputs nil
|
||||
:shell/reset-bottom-tabs nil
|
||||
:shell/reset-state nil
|
||||
:hide-popover nil
|
||||
::logout nil
|
||||
::multiaccounts/webview-debug-changed false
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
(defn calculate-button-height-and-dispatch-popover
|
||||
[]
|
||||
(.measure
|
||||
^js
|
||||
@button-ref
|
||||
(fn [_ _ _ _ _ page-y]
|
||||
(dispatch-popover page-y))))
|
||||
|
|
|
@ -168,16 +168,7 @@
|
|||
(when-let [chat-id (:current-chat-id db)]
|
||||
(chat.state/reset-visible-item)
|
||||
(rf/merge cofx
|
||||
(merge
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(let [community-id (get-in db [:chats chat-id :community-id])]
|
||||
;; When navigating back from community chat to community, update switcher card
|
||||
;; A close chat event is also called while opening any chat.
|
||||
;; That might lead to duplicate :dispatch keys in fx/merge, that's why dispatch-n is
|
||||
;; used here.
|
||||
(when (and community-id (not navigate-to-shell?))
|
||||
{:dispatch-n [[:shell/add-switcher-card
|
||||
:community-overview community-id]]})))
|
||||
{:db (dissoc db :current-chat-id)}
|
||||
(link-preview/reset-all)
|
||||
(delete-for-me/sync-all)
|
||||
(delete-message/send-all)
|
||||
|
@ -206,9 +197,9 @@
|
|||
(rf/defn navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
{:events [:chat/navigate-to-chat]}
|
||||
[{db :db :as cofx} chat-id]
|
||||
[{db :db :as cofx} chat-id animation]
|
||||
(rf/merge cofx
|
||||
{:dispatch [:navigate-to :chat chat-id]}
|
||||
{:dispatch [(if animation :shell/navigate-to :navigate-to) :chat chat-id animation]}
|
||||
(when-not (or (= (:view-id db) :community) (= (:view-id db) :community-overview))
|
||||
(navigation/pop-to-root :shell-stack))
|
||||
(close-chat false)
|
||||
|
|
|
@ -87,5 +87,5 @@
|
|||
(let [chat-id "test_chat"
|
||||
db {:pagination-info {chat-id {:all-loaded? true}}}]
|
||||
(testing "Pagination info should be reset on navigation"
|
||||
(let [res (chat/navigate-to-chat {:db db} chat-id)]
|
||||
(let [res (chat/navigate-to-chat {:db db} chat-id nil)]
|
||||
(is (nil? (get-in res [:db :pagination-info chat-id :all-loaded?])))))))
|
||||
|
|
|
@ -110,13 +110,13 @@
|
|||
:extrapolateRight "clamp"})
|
||||
|
||||
(defn loading-view
|
||||
[chat-id]
|
||||
[chat-id shell-animation-complete?]
|
||||
(let [loading-messages? (rf/sub [:chats/loading-messages? chat-id])
|
||||
all-loaded? (rf/sub [:chats/all-loaded? chat-id])
|
||||
messages (rf/sub [:chats/raw-chat-messages-stream chat-id])
|
||||
loading-first-page? (= (count messages) 0)
|
||||
top-spacing (if loading-first-page? 0 navigation.style/navigation-bar-height)]
|
||||
(when (or loading-messages? (not all-loaded?))
|
||||
(when (or (not shell-animation-complete?) loading-messages? (not all-loaded?))
|
||||
[rn/view {:padding-top top-spacing}
|
||||
[quo/skeleton
|
||||
(if loading-first-page?
|
||||
|
@ -174,7 +174,7 @@
|
|||
(assoc :scale-y -1)))
|
||||
|
||||
(defn f-list-footer
|
||||
[{:keys [chat scroll-y cover-bg-color on-layout]}]
|
||||
[{:keys [chat scroll-y cover-bg-color on-layout shell-animation-complete?]}]
|
||||
(let [{:keys [chat-id chat-name emoji chat-type
|
||||
group-chat]} chat
|
||||
all-loaded? (rf/sub [:chats/all-loaded? chat-id])
|
||||
|
@ -217,7 +217,7 @@
|
|||
(when bio
|
||||
[quo/text {:style style/bio}
|
||||
bio])]]]
|
||||
[loading-view chat-id]]))
|
||||
[loading-view chat-id shell-animation-complete?]]))
|
||||
|
||||
(defn list-footer
|
||||
[props]
|
||||
|
@ -258,10 +258,15 @@
|
|||
|
||||
(defn messages-list-content
|
||||
[{:keys [chat insets scroll-y cover-bg-color keyboard-shown?]}]
|
||||
(let [context (rf/sub [:chats/current-chat-message-list-view-context])
|
||||
messages (rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)])
|
||||
recording? (rf/sub [:chats/recording?])
|
||||
all-loaded? (rf/sub [:chats/all-loaded? (:chat-id chat)])]
|
||||
(let [shell-animation-complete? (rf/sub [:shell/animation-complete? (:chat-type chat)])
|
||||
context (when shell-animation-complete?
|
||||
(rf/sub [:chats/current-chat-message-list-view-context]))
|
||||
messages (when shell-animation-complete?
|
||||
(rf/sub [:chats/raw-chat-messages-stream (:chat-id chat)]))
|
||||
recording? (when shell-animation-complete?
|
||||
(rf/sub [:chats/recording?]))
|
||||
all-loaded? (when shell-animation-complete?
|
||||
(rf/sub [:chats/all-loaded? (:chat-id chat)]))]
|
||||
[rn/view {:style {:flex 1}}
|
||||
[rn/flat-list
|
||||
{:key-fn list-key-fn
|
||||
|
@ -271,10 +276,11 @@
|
|||
[list-group-chat-header chat])
|
||||
[list-header insets]]
|
||||
:footer [list-footer
|
||||
{:chat chat
|
||||
:scroll-y scroll-y
|
||||
:cover-bg-color cover-bg-color
|
||||
:on-layout footer-on-layout}]
|
||||
{:chat chat
|
||||
:scroll-y scroll-y
|
||||
:cover-bg-color cover-bg-color
|
||||
:on-layout footer-on-layout
|
||||
:shell-animation-complete? shell-animation-complete?}]
|
||||
:data messages
|
||||
:render-data {:context context
|
||||
:keyboard-shown? keyboard-shown?}
|
||||
|
@ -323,7 +329,8 @@
|
|||
[keyboard-shown keyboard-height])
|
||||
[rn/keyboard-avoiding-view
|
||||
{:style (style/keyboard-avoiding-container insets)
|
||||
:keyboard-vertical-offset (- (:bottom insets))}
|
||||
:keyboard-vertical-offset (- (:bottom insets))
|
||||
:behavior :height}
|
||||
|
||||
(when header-comp
|
||||
[header-comp {:scroll-y scroll-y}])
|
||||
|
|
|
@ -1,29 +1,23 @@
|
|||
(ns status-im2.contexts.chat.messages.view
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[re-frame.db]
|
||||
[react-native.core :as rn]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.contexts.chat.composer.view :as composer]
|
||||
[status-im2.contexts.chat.messages.contact-requests.bottom-drawer :as
|
||||
contact-requests.bottom-drawer]
|
||||
[status-im2.contexts.chat.messages.list.view :as messages.list]
|
||||
[status-im2.contexts.chat.messages.navigation.view :as messages.navigation]
|
||||
[status-im2.navigation.state :as navigation.state]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn navigate-back-handler
|
||||
[]
|
||||
(when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat))
|
||||
(rn/hw-back-remove-listener navigate-back-handler)
|
||||
(rf/dispatch [:chat/close])
|
||||
(rf/dispatch [:navigate-back])
|
||||
;; If true is not returned back button event will bubble up,
|
||||
;; and will call system back button action
|
||||
true))
|
||||
(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-render
|
||||
(defn chat
|
||||
[]
|
||||
(let [{:keys [chat-id
|
||||
chat-type
|
||||
contact-request-state
|
||||
group-chat
|
||||
able-to-send-message?]
|
||||
|
@ -35,14 +29,6 @@
|
|||
[messages.navigation/navigation-view {:scroll-y scroll-y}])
|
||||
:footer-comp (fn [{:keys [insets]}]
|
||||
(if-not able-to-send-message?
|
||||
[contact-requests.bottom-drawer/view chat-id contact-request-state group-chat]
|
||||
[:f> composer/composer insets]))}]))
|
||||
|
||||
(defn chat
|
||||
[]
|
||||
(reagent/create-class
|
||||
{:component-did-mount (fn []
|
||||
(rn/hw-back-remove-listener navigate-back-handler)
|
||||
(rn/hw-back-add-listener navigate-back-handler))
|
||||
:component-will-unmount (fn [] (rn/hw-back-remove-listener navigate-back-handler))
|
||||
:reagent-render chat-render}))
|
||||
[contact-requests.bottom-drawer/view chat-id contact-request-state
|
||||
group-chat]
|
||||
[load-composer insets chat-type]))}]))
|
||||
|
|
|
@ -303,53 +303,54 @@
|
|||
category)))))
|
||||
|
||||
(defn community-card-page-view
|
||||
[{:keys [name images id]}]
|
||||
[]
|
||||
(let [categories-heights (reagent/atom {})
|
||||
first-channel-height (reagent/atom 0)
|
||||
scroll-height (reagent/atom 0)
|
||||
cover {:uri (get-in images [:banner :uri])}
|
||||
logo {:uri (get-in images [:thumbnail :uri])}]
|
||||
(fn [community pending?]
|
||||
[scroll-page/scroll-page
|
||||
{:cover-image cover
|
||||
:logo logo
|
||||
:page-nav-right-section-buttons (page-nav-right-section-buttons id)
|
||||
:name name
|
||||
:on-scroll #(reset! scroll-height %)
|
||||
:navigate-back? true
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)
|
||||
:height (if platform/ios?
|
||||
100
|
||||
148)}
|
||||
scroll-height (reagent/atom 0)]
|
||||
(fn [id]
|
||||
(let [{:keys [name images id] :as community}
|
||||
(rf/sub [:communities/community id])
|
||||
pending? (rf/sub [:communities/my-pending-request-to-join id])
|
||||
cover {:uri (get-in images [:banner :uri])}
|
||||
logo {:uri (get-in images [:thumbnail :uri])}]
|
||||
[scroll-page/scroll-page
|
||||
{:cover-image cover
|
||||
:logo logo
|
||||
:page-nav-right-section-buttons (page-nav-right-section-buttons id)
|
||||
:name name
|
||||
:on-scroll #(reset! scroll-height %)
|
||||
:navigate-back? true
|
||||
:background-color (colors/theme-colors
|
||||
colors/white
|
||||
colors/neutral-90)
|
||||
:height (if platform/ios?
|
||||
100
|
||||
148)}
|
||||
|
||||
[sticky-category-header
|
||||
{:enabled (> @scroll-height @first-channel-height)
|
||||
:label (pick-first-category-by-height
|
||||
@scroll-height
|
||||
@first-channel-height
|
||||
@categories-heights)}]
|
||||
[sticky-category-header
|
||||
{:enabled (> @scroll-height @first-channel-height)
|
||||
:label (pick-first-category-by-height
|
||||
@scroll-height
|
||||
@first-channel-height
|
||||
@categories-heights)}]
|
||||
|
||||
[community-content
|
||||
community
|
||||
pending?
|
||||
{:on-category-layout (partial add-category-height categories-heights)
|
||||
:on-first-channel-height-changed
|
||||
;; Here we set the height of the component
|
||||
;; and we filter out the categories, as some might have been removed
|
||||
(fn [height categories]
|
||||
(swap! categories-heights select-keys categories)
|
||||
(reset! first-channel-height height))}]])))
|
||||
[community-content
|
||||
community
|
||||
pending?
|
||||
{:on-category-layout (partial add-category-height categories-heights)
|
||||
:on-first-channel-height-changed
|
||||
;; Here we set the height of the component
|
||||
;; and we filter out the categories, as some might have been removed
|
||||
(fn [height categories]
|
||||
(swap! categories-heights select-keys categories)
|
||||
(reset! first-channel-height height))}]]))))
|
||||
|
||||
(defn overview
|
||||
[]
|
||||
(let [id (rf/sub [:get-screen-params :community-overview])
|
||||
community (rf/sub [:communities/community id])
|
||||
pending? (rf/sub [:communities/my-pending-request-to-join id])]
|
||||
[id]
|
||||
(let [id (or id (rf/sub [:get-screen-params :community-overview]))]
|
||||
[rn/view
|
||||
{:style style/community-overview-container}
|
||||
[community-card-page-view community pending?]
|
||||
[community-card-page-view id]
|
||||
[floating-shell-button/floating-shell-button
|
||||
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
|
||||
:label (i18n/label :t/jump-to)}}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
[oops.core :refer [oget]]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im2.contexts.shell.animation :as shell.animation]
|
||||
[status-im2.contexts.shell.state :as shell.state]
|
||||
[status-im2.contexts.onboarding.common.carousel.view :as carousel]
|
||||
[status-im2.contexts.onboarding.common.background.style :as style]
|
||||
[react-native.reanimated :as reanimated]
|
||||
|
@ -50,8 +50,8 @@
|
|||
;; but actual values differ in some pixels, so arbitrary 5 pixels is allowed
|
||||
(when (and (> height width)
|
||||
(>= (+ height 5) (or window-height 0))
|
||||
(not= height @shell.animation/screen-height))
|
||||
(reset! shell.animation/screen-height height)
|
||||
(not= height @shell.state/screen-height))
|
||||
(reset! shell.state/screen-height height)
|
||||
(async-storage/set-item! :screen-height height))))
|
||||
|
||||
(defn f-view
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[status-im2.contexts.onboarding.common.background.view :as background]
|
||||
[status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
|
||||
[status-im2.contexts.onboarding.enable-notifications.style :as style]
|
||||
[status-im2.contexts.shell.animation :as shell.animation]))
|
||||
[status-im2.contexts.shell.utils :as shell.utils]))
|
||||
|
||||
(defn page-title
|
||||
[]
|
||||
|
@ -28,7 +28,7 @@
|
|||
[rn/view {:style (style/buttons insets)}
|
||||
[quo/button
|
||||
{:on-press (fn []
|
||||
(shell.animation/change-selected-stack-id :communities-stack true)
|
||||
(shell.utils/change-selected-stack-id :communities-stack true nil)
|
||||
(rf/dispatch [::notifications/switch true platform/ios?])
|
||||
(rf/dispatch [:init-root :welcome]))
|
||||
:type :primary
|
||||
|
@ -38,7 +38,7 @@
|
|||
(i18n/label :t/intro-wizard-title6)]
|
||||
[quo/button
|
||||
{:on-press (fn []
|
||||
(shell.animation/change-selected-stack-id :communities-stack true)
|
||||
(shell.utils/change-selected-stack-id :communities-stack true nil)
|
||||
(rf/dispatch [:init-root :welcome]))
|
||||
:accessibility-label :enable-notifications-later-button
|
||||
:override-background-color colors/white-opa-5
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[status-im2.constants :as constants]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]
|
||||
[status-im2.contexts.shell.cards.view :as switcher-cards]
|
||||
[status-im2.contexts.shell.components.switcher-cards.view :as switcher-cards]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
(def descriptor
|
||||
|
|
|
@ -1,177 +1,86 @@
|
|||
(ns status-im2.contexts.shell.animation
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[utils.re-frame :as rf]
|
||||
(:require [utils.re-frame :as rf]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.async-storage.core :as async-storage] ;;TODO remove when not used anymore
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[utils.worklets.shell :as worklets.shell]))
|
||||
|
||||
;; Atoms
|
||||
(def selected-stack-id (atom nil))
|
||||
(def screen-height (atom nil))
|
||||
(def home-stack-state (atom shell.constants/close-with-animation))
|
||||
(def shared-values-atom (atom nil))
|
||||
|
||||
;; 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 shell.constants/open-with-animation)
|
||||
(= state shell.constants/open-without-animation))))
|
||||
|
||||
(defn calculate-home-stack-state-value
|
||||
[stack-id & animate?]
|
||||
(if animate?
|
||||
(if (some? stack-id)
|
||||
shell.constants/open-with-animation
|
||||
shell.constants/close-with-animation)
|
||||
(if (some? stack-id)
|
||||
shell.constants/open-without-animation
|
||||
shell.constants/close-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 change-selected-stack-id
|
||||
[stack-id & [store? home-stack-state-value]]
|
||||
(let [home-stack-state-value (or home-stack-state-value
|
||||
(calculate-home-stack-state-value stack-id))]
|
||||
(reset! selected-stack-id stack-id)
|
||||
(reset! home-stack-state home-stack-state-value)
|
||||
(rf/dispatch [:set-view-id (or stack-id :shell)])
|
||||
(when store?
|
||||
(async-storage/set-item! :selected-stack-id stack-id))))
|
||||
|
||||
(defn calculate-home-stack-position
|
||||
[]
|
||||
(let [{:keys [width height]} (shell.constants/dimensions)
|
||||
height (or @screen-height height)
|
||||
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)
|
||||
left-empty-space (* empty-space-half-scale width)
|
||||
top-empty-space (* empty-space-half-scale
|
||||
(- height (shell.constants/bottom-tabs-container-height)))]
|
||||
{:left (reduce
|
||||
(fn [acc stack-id]
|
||||
(assoc acc
|
||||
stack-id
|
||||
(+ (- left-margin left-empty-space)
|
||||
(* (.indexOf shell.constants/stacks-ids stack-id)
|
||||
bottom-nav-tab-width))))
|
||||
{:none 0}
|
||||
shell.constants/stacks-ids)
|
||||
:top (+ top-empty-space (shell.constants/bottom-tabs-container-height))
|
||||
:scale minimize-scale}))
|
||||
|
||||
;; 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 false)
|
||||
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)]
|
||||
(reset! shared-values-atom
|
||||
(reduce
|
||||
(fn [acc id]
|
||||
(let [tabs-icon-color-keyword (get shell.constants/tabs-icon-color-keywords id)
|
||||
stack-opacity-keyword (get shell.constants/stacks-opacity-keywords id)
|
||||
stack-z-index-keyword (get shell.constants/stacks-z-index-keywords id)]
|
||||
(assoc
|
||||
acc
|
||||
stack-opacity-keyword
|
||||
(worklets.shell/stack-opacity (name id) selected-stack-id-sv)
|
||||
stack-z-index-keyword
|
||||
(worklets.shell/stack-z-index (name id) selected-stack-id-sv)
|
||||
tabs-icon-color-keyword
|
||||
(worklets.shell/bottom-tab-icon-color
|
||||
(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 (worklets.shell/home-stack-left
|
||||
selected-stack-id-sv
|
||||
animate-home-stack-left
|
||||
home-stack-state-sv
|
||||
(clj->js (:left home-stack-position)))
|
||||
:home-stack-top (worklets.shell/home-stack-top
|
||||
home-stack-state-sv
|
||||
(:top home-stack-position))
|
||||
:home-stack-opacity (worklets.shell/home-stack-opacity home-stack-state-sv)
|
||||
:home-stack-pointer (worklets.shell/home-stack-pointer home-stack-state-sv)
|
||||
:home-stack-scale (worklets.shell/home-stack-scale home-stack-state-sv
|
||||
(:scale home-stack-position))
|
||||
:bottom-tabs-height (worklets.shell/bottom-tabs-height
|
||||
home-stack-state-sv
|
||||
(shell.constants/bottom-tabs-container-height)
|
||||
(shell.constants/bottom-tabs-extended-container-height))}
|
||||
shell.constants/stacks-ids)))
|
||||
@shared-values-atom)
|
||||
|
||||
;; Animations
|
||||
|
||||
(defn change-shell-status-bar-style
|
||||
[]
|
||||
(rf/dispatch [:change-shell-status-bar-style
|
||||
(if (or (colors/dark?)
|
||||
(not (home-stack-open?)))
|
||||
:light
|
||||
:dark)]))
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
;; Home stack
|
||||
(defn open-home-stack
|
||||
[stack-id animate?]
|
||||
(let [home-stack-state-value (calculate-home-stack-state-value stack-id animate?)]
|
||||
(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)
|
||||
(change-selected-stack-id stack-id true home-stack-state-value)
|
||||
(js/setTimeout change-shell-status-bar-style shell.constants/shell-animation-time)))
|
||||
(let [home-stack-state-value (utils/calculate-home-stack-state-value stack-id animate?)]
|
||||
(reanimated/set-shared-value (:selected-stack-id @state/shared-values-atom) (name stack-id))
|
||||
(reanimated/set-shared-value (:home-stack-state @state/shared-values-atom) home-stack-state-value)
|
||||
(utils/change-selected-stack-id stack-id true home-stack-state-value)
|
||||
(js/setTimeout
|
||||
(fn []
|
||||
(utils/load-stack stack-id)
|
||||
(utils/change-shell-status-bar-style))
|
||||
(if animate? shell.constants/shell-animation-time 0))))
|
||||
|
||||
(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))
|
||||
(change-selected-stack-id stack-id true))
|
||||
(reanimated/set-shared-value (:animate-home-stack-left @state/shared-values-atom) false)
|
||||
(reanimated/set-shared-value (:selected-stack-id @state/shared-values-atom) (name stack-id))
|
||||
(utils/load-stack stack-id)
|
||||
(utils/change-selected-stack-id stack-id true nil))
|
||||
|
||||
(defn bottom-tab-on-press
|
||||
[stack-id]
|
||||
(when (and @shared-values-atom (not= stack-id @selected-stack-id))
|
||||
(let [stack-load-delay (if (home-stack-open?)
|
||||
0
|
||||
shell.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))))
|
||||
[stack-id animate?]
|
||||
(when (and @state/shared-values-atom (not= stack-id @state/selected-stack-id))
|
||||
(if (utils/home-stack-open?)
|
||||
(change-tab stack-id)
|
||||
(open-home-stack stack-id animate?))
|
||||
(when animate? (utils/update-view-id (or stack-id :shell)))))
|
||||
|
||||
(defn close-home-stack
|
||||
[animate?]
|
||||
(let [stack-id nil
|
||||
home-stack-state-value (calculate-home-stack-state-value stack-id animate?)]
|
||||
(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)
|
||||
(change-selected-stack-id stack-id true home-stack-state-value)
|
||||
(change-shell-status-bar-style)))
|
||||
home-stack-state-value (utils/calculate-home-stack-state-value stack-id animate?)]
|
||||
(reanimated/set-shared-value (:animate-home-stack-left @state/shared-values-atom) true)
|
||||
(reanimated/set-shared-value (:home-stack-state @state/shared-values-atom) home-stack-state-value)
|
||||
(utils/change-selected-stack-id stack-id true home-stack-state-value)
|
||||
(utils/change-shell-status-bar-style)
|
||||
(when animate? (utils/update-view-id (or stack-id :shell)))))
|
||||
|
||||
;; Floating Screen
|
||||
(defn animate-floating-screen
|
||||
[screen-id {:keys [id animation community-id hidden-screen?]}]
|
||||
(when (not= animation (get @state/floating-screens-state screen-id))
|
||||
;; Animate Floating Screen
|
||||
(reanimated/set-shared-value
|
||||
(get-in @state/shared-values-atom [screen-id :screen-state])
|
||||
animation)
|
||||
(reset! state/floating-screens-state
|
||||
(assoc @state/floating-screens-state screen-id animation)))
|
||||
(js/setTimeout
|
||||
(fn [floating-screen-open?]
|
||||
(if floating-screen-open?
|
||||
;; Events realted to opening of a screen
|
||||
(rf/dispatch [:shell/floating-screen-opened screen-id
|
||||
id community-id hidden-screen?])
|
||||
;; Events realted to closing of a screen
|
||||
(rf/dispatch [:shell/floating-screen-closed screen-id])))
|
||||
shell.constants/shell-animation-time
|
||||
(utils/floating-screen-open? screen-id)))
|
||||
|
||||
(defn set-floating-screen-position
|
||||
[left top card-type]
|
||||
(let [screen-id (cond
|
||||
(#{shell.constants/one-to-one-chat-card
|
||||
shell.constants/private-group-chat-card
|
||||
shell.constants/community-channel-card}
|
||||
card-type)
|
||||
shell.constants/chat-screen
|
||||
|
||||
(= card-type shell.constants/community-card)
|
||||
shell.constants/community-screen
|
||||
|
||||
:else nil)]
|
||||
(when screen-id
|
||||
(reanimated/set-shared-value
|
||||
(get-in @state/shared-values-atom [screen-id :screen-left])
|
||||
left)
|
||||
(reanimated/set-shared-value
|
||||
(get-in @state/shared-values-atom [screen-id :screen-top])
|
||||
top))))
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
(ns status-im2.contexts.shell.components.bottom-tabs.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.shell.utils :as utils]))
|
||||
|
||||
(defn bottom-tabs-container
|
||||
[pass-through? height]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:height height}
|
||||
{:background-color (if pass-through? :transparent colors/neutral-100)
|
||||
:flex 1
|
||||
:align-items :center
|
||||
:height (utils/bottom-tabs-container-height)
|
||||
:position :absolute
|
||||
:bottom 0
|
||||
:right 0
|
||||
:left 0
|
||||
:overflow :hidden
|
||||
:accessibility-label :bottom-tabs-container}))
|
||||
|
||||
(defn bottom-tabs
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:position :absolute
|
||||
:bottom (if platform/android? 8 34)
|
||||
:flex 1
|
||||
:accessibility-label :bottom-tabs})
|
||||
|
||||
(def bottom-tabs-blur-overlay
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:height (utils/bottom-tabs-extended-container-height)
|
||||
:background-color colors/neutral-100-opa-70})
|
|
@ -1,13 +1,15 @@
|
|||
(ns status-im2.contexts.shell.bottom-tabs
|
||||
(ns status-im2.contexts.shell.components.bottom-tabs.view
|
||||
(:require [utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.gesture :as gesture]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.shell.style :as style]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[quo2.components.navigation.bottom-nav-tab :as bottom-nav-tab]
|
||||
[react-native.gesture :as gesture]))
|
||||
[status-im2.contexts.shell.components.bottom-tabs.style :as style]))
|
||||
|
||||
(defn blur-overlay-params
|
||||
[style]
|
||||
|
@ -26,18 +28,14 @@
|
|||
:icon-color-anim (get
|
||||
shared-values
|
||||
(get shell.constants/tabs-icon-color-keywords stack-id))
|
||||
:on-press #(animation/bottom-tab-on-press stack-id)
|
||||
:on-press #(animation/bottom-tab-on-press stack-id true)
|
||||
:accessibility-label (str (name stack-id) "-tab"))])
|
||||
|
||||
(defn- f-bottom-tabs
|
||||
(defn f-bottom-tabs
|
||||
[]
|
||||
(let [notifications-data (rf/sub [:shell/bottom-tabs-notifications-data])
|
||||
pass-through? (rf/sub [:shell/shell-pass-through?])
|
||||
shared-values @animation/shared-values-atom
|
||||
original-style (style/bottom-tabs-container pass-through?)
|
||||
animated-style (reanimated/apply-animations-to-style
|
||||
{:height (:bottom-tabs-height shared-values)}
|
||||
original-style)
|
||||
shared-values @state/shared-values-atom
|
||||
communities-double-tab-gesture (-> (gesture/gesture-tap)
|
||||
(gesture/number-of-taps 2)
|
||||
(gesture/on-start
|
||||
|
@ -48,9 +46,10 @@
|
|||
(gesture/on-start
|
||||
(fn [_event]
|
||||
(rf/dispatch [:messages-home/select-tab :tab/recent]))))]
|
||||
(animation/load-stack @animation/selected-stack-id)
|
||||
(utils/load-stack @state/selected-stack-id)
|
||||
(reanimated/set-shared-value (:pass-through? shared-values) pass-through?)
|
||||
[reanimated/view {:style animated-style}
|
||||
[reanimated/view
|
||||
{:style (style/bottom-tabs-container pass-through? (:bottom-tabs-height shared-values))}
|
||||
(when pass-through?
|
||||
[blur/view (blur-overlay-params style/bottom-tabs-blur-overlay)])
|
||||
[rn/view {:style (style/bottom-tabs)}
|
||||
|
@ -60,7 +59,3 @@
|
|||
[bottom-tab :i/messages :chats-stack shared-values notifications-data]]
|
||||
[bottom-tab :i/wallet :wallet-stack shared-values notifications-data]
|
||||
[bottom-tab :i/browser :browser-stack shared-values notifications-data]]]))
|
||||
|
||||
(defn bottom-tabs
|
||||
[]
|
||||
[:f> f-bottom-tabs])
|
|
@ -0,0 +1,20 @@
|
|||
(ns status-im2.contexts.shell.components.floating-screens.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]))
|
||||
|
||||
(defn screen
|
||||
[{:keys [screen-left screen-top screen-width screen-height screen-z-index]}]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:left screen-left
|
||||
:top screen-top
|
||||
:width screen-width
|
||||
:height screen-height
|
||||
:z-index screen-z-index}
|
||||
{:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:overflow :hidden
|
||||
:position :absolute}))
|
||||
|
||||
(defn screen-container
|
||||
[{:keys [width height]}]
|
||||
{:width width
|
||||
:height height})
|
|
@ -0,0 +1,43 @@
|
|||
(ns status-im2.contexts.shell.components.floating-screens.view
|
||||
(:require [utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.contexts.chat.messages.view :as chat]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.components.floating-screens.style :as style]
|
||||
[status-im2.contexts.communities.overview.view :as communities.overview]))
|
||||
|
||||
(def screens-map
|
||||
{shell.constants/community-screen communities.overview/overview
|
||||
shell.constants/chat-screen chat/chat})
|
||||
|
||||
(defn f-screen
|
||||
[screen-id {:keys [id animation] :as screen-param}]
|
||||
;; First render screen, then animate (smoother animation)
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(animation/animate-floating-screen screen-id screen-param))
|
||||
[animation id])
|
||||
[reanimated/view
|
||||
{:style (style/screen (get @state/shared-values-atom screen-id))}
|
||||
[rn/view
|
||||
{:style (style/screen-container (utils/dimensions))
|
||||
:key id}
|
||||
[(get screens-map screen-id) id]]])
|
||||
|
||||
;; Currently chat screen and events both depends on current-chat-id, once we remove
|
||||
;; use of current-chat-id from view then we can keep last chat loaded, for fast navigation
|
||||
(defn lazy-screen
|
||||
[screen-id]
|
||||
(let [screen-param (rf/sub [:shell/floating-screen screen-id])]
|
||||
(when screen-param
|
||||
[:f> f-screen screen-id screen-param])))
|
||||
|
||||
(defn view
|
||||
[]
|
||||
[:<>
|
||||
[lazy-screen shell.constants/community-screen]
|
||||
[lazy-screen shell.constants/chat-screen]])
|
|
@ -0,0 +1,32 @@
|
|||
(ns status-im2.contexts.shell.components.home-stack.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.shell.utils :as utils]))
|
||||
|
||||
(defn home-stack
|
||||
[shared-values {:keys [width height]}]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:top (:home-stack-top shared-values)
|
||||
:left (:home-stack-left shared-values)
|
||||
:opacity (:home-stack-opacity shared-values)
|
||||
:pointer-events (:home-stack-pointer shared-values)
|
||||
:transform [{:scale (:home-stack-scale shared-values)}]}
|
||||
{:border-bottom-left-radius 20
|
||||
:border-bottom-right-radius 20
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:overflow :hidden
|
||||
:position :absolute
|
||||
:width width
|
||||
:height (- height (utils/bottom-tabs-container-height))}))
|
||||
|
||||
(defn stack-view
|
||||
[stack-id {:keys [opacity z-index]}]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity
|
||||
:z-index z-index}
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:accessibility-label stack-id}))
|
|
@ -0,0 +1,48 @@
|
|||
(ns status-im2.contexts.shell.components.home-stack.view
|
||||
(:require [react-native.reanimated :as reanimated]
|
||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[status-im2.contexts.chat.home.view :as chat]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.contexts.communities.home.view :as communities]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.components.home-stack.style :as style]
|
||||
[status-im.ui.screens.browser.stack :as browser.stack]))
|
||||
|
||||
(defn load-stack?
|
||||
[stack-id]
|
||||
(case stack-id
|
||||
:communities-stack @state/load-communities-stack?
|
||||
:chats-stack @state/load-chats-stack?
|
||||
:browser-stack @state/load-browser-stack?
|
||||
:wallet-stack @state/load-wallet-stack?))
|
||||
|
||||
(defn- f-stack-view
|
||||
[stack-id shared-values]
|
||||
[reanimated/view
|
||||
{:style (style/stack-view
|
||||
stack-id
|
||||
{:opacity (get shared-values
|
||||
(get shell.constants/stacks-opacity-keywords stack-id))
|
||||
:z-index (get shared-values
|
||||
(get shell.constants/stacks-z-index-keywords stack-id))})}
|
||||
(case stack-id
|
||||
:communities-stack [communities/home]
|
||||
:chats-stack [chat/home]
|
||||
:wallet-stack [wallet.accounts/accounts-overview-old]
|
||||
:browser-stack [browser.stack/browser-stack]
|
||||
[:<>])])
|
||||
|
||||
(defn lazy-screen
|
||||
[stack-id shared-values]
|
||||
(when (load-stack? stack-id)
|
||||
[:f> f-stack-view stack-id shared-values]))
|
||||
|
||||
(defn f-home-stack
|
||||
[]
|
||||
(let [shared-values @state/shared-values-atom]
|
||||
[reanimated/view {:style (style/home-stack shared-values (utils/dimensions))}
|
||||
[lazy-screen :communities-stack shared-values]
|
||||
[lazy-screen :chats-stack shared-values]
|
||||
[lazy-screen :browser-stack shared-values]
|
||||
[lazy-screen :wallet-stack shared-values]]))
|
|
@ -0,0 +1,64 @@
|
|||
(ns status-im2.contexts.shell.components.shell-screen.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[status-im2.contexts.shell.utils :as utils]))
|
||||
|
||||
;;;; Placeholder
|
||||
(defn placeholder-container
|
||||
[status-bar-height]
|
||||
{:position :absolute
|
||||
:top (+ 112 status-bar-height)
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom (utils/bottom-tabs-container-height)
|
||||
:align-items :center
|
||||
:accessibility-label :shell-placeholder-view})
|
||||
|
||||
(def placeholder-image
|
||||
{:margin-top 186
|
||||
:width 120
|
||||
:height 120
|
||||
;; Code to remove once placeholder image/vector will be available
|
||||
:border-width 5
|
||||
:border-radius 10
|
||||
:border-color :red})
|
||||
|
||||
(def placeholder-title
|
||||
{:margin-top 20
|
||||
:color colors/white})
|
||||
|
||||
(def placeholder-subtitle
|
||||
{:margin-top 4
|
||||
:color colors/white})
|
||||
|
||||
;;;; Shell
|
||||
(defn jump-to-text
|
||||
[status-bar-height]
|
||||
{:color colors/white
|
||||
:margin-top (+ 68 status-bar-height)
|
||||
:margin-bottom 20
|
||||
:margin-left 20})
|
||||
|
||||
(def jump-to-list
|
||||
{:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:position :absolute})
|
||||
|
||||
(defn top-nav-blur-overlay-container
|
||||
[height pass-through?]
|
||||
{:height height
|
||||
:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:right 0
|
||||
:overflow :hidden
|
||||
:background-color (if pass-through? :transparent colors/neutral-100)})
|
||||
|
||||
(def top-nav-blur-overlay
|
||||
{:height 100
|
||||
:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:background-color colors/neutral-100-opa-70})
|
|
@ -0,0 +1,113 @@
|
|||
(ns status-im2.contexts.shell.components.shell-screen.view
|
||||
(:require [utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.common.home.view :as common.home]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.components.shell-screen.style :as style]
|
||||
[status-im2.contexts.shell.components.bottom-tabs.view :as bottom-tabs]
|
||||
[status-im2.contexts.shell.components.switcher-cards.view :as switcher-cards]))
|
||||
|
||||
(defn placeholder
|
||||
[]
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [colors/neutral-100-opa-0 colors/neutral-100-opa-100]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0 :y 1}
|
||||
:style (style/placeholder-container (safe-area/get-top))}
|
||||
[rn/image
|
||||
{:source nil ;; TODO(parvesh) - add placeholder image
|
||||
:style style/placeholder-image}]
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style style/placeholder-title}
|
||||
(i18n/label :t/shell-placeholder-title)]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:align :center
|
||||
:style style/placeholder-subtitle}
|
||||
(i18n/label :t/shell-placeholder-subtitle)]])
|
||||
|
||||
(defn jump-to-text
|
||||
[]
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style (style/jump-to-text (safe-area/get-top))}
|
||||
(i18n/label :t/jump-to)])
|
||||
|
||||
(defn render-card
|
||||
[{:keys [type screen-id] :as card}]
|
||||
(let [card-data (cond
|
||||
(= type shell.constants/one-to-one-chat-card)
|
||||
(rf/sub [:shell/one-to-one-chat-card screen-id])
|
||||
|
||||
(= type shell.constants/private-group-chat-card)
|
||||
(rf/sub [:shell/private-group-chat-card screen-id])
|
||||
|
||||
(= type shell.constants/community-card)
|
||||
(rf/sub [:shell/community-card screen-id])
|
||||
|
||||
(= type shell.constants/community-channel-card)
|
||||
(rf/sub [:shell/community-channel-card screen-id])
|
||||
|
||||
:else nil)]
|
||||
[switcher-cards/card (merge card card-data)]))
|
||||
|
||||
(def empty-cards (repeat 6 {:type shell.constants/empty-card}))
|
||||
|
||||
(defn jump-to-list
|
||||
[switcher-cards shell-margin]
|
||||
(let [data (if (seq switcher-cards) switcher-cards empty-cards)]
|
||||
[:<>
|
||||
[rn/flat-list
|
||||
{:data data
|
||||
:render-fn render-card
|
||||
:key-fn :id
|
||||
:header (jump-to-text)
|
||||
:ref #(reset! state/jump-to-list-ref %)
|
||||
:num-columns 2
|
||||
:column-wrapper-style {:margin-horizontal shell-margin
|
||||
:justify-content :space-between
|
||||
:margin-bottom 16}
|
||||
:style style/jump-to-list
|
||||
:content-container-style {:padding-bottom (utils/bottom-tabs-container-height)}}]
|
||||
(when-not (seq switcher-cards)
|
||||
[placeholder])]))
|
||||
|
||||
(defn top-nav-blur-overlay
|
||||
[top]
|
||||
(let [pass-through? (rf/sub [:shell/shell-pass-through?])]
|
||||
[rn/view {:style (style/top-nav-blur-overlay-container (+ 56 top) pass-through?)}
|
||||
(when pass-through?
|
||||
[blur/view (bottom-tabs/blur-overlay-params style/top-nav-blur-overlay)])]))
|
||||
|
||||
(defn view
|
||||
[customization-color]
|
||||
(let [switcher-cards (rf/sub [:shell/sorted-switcher-cards])
|
||||
width (rf/sub [:dimensions/window-width])
|
||||
top (safe-area/get-top)
|
||||
shell-margin (/ (- width (* 2 shell.constants/switcher-card-size)) 3)]
|
||||
[rn/view
|
||||
{:style {:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom -1
|
||||
:position :absolute
|
||||
:background-color colors/neutral-100}}
|
||||
[jump-to-list switcher-cards shell-margin]
|
||||
[top-nav-blur-overlay top]
|
||||
[common.home/top-nav
|
||||
{:type :shell
|
||||
:avatar {:customization-color customization-color}
|
||||
:style {:margin-top top
|
||||
:z-index 2}}]]))
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im2.contexts.shell.cards.style
|
||||
(ns status-im2.contexts.shell.components.switcher-cards.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def colors-map
|
|
@ -1,13 +1,15 @@
|
|||
(ns status-im2.contexts.shell.cards.view
|
||||
(ns status-im2.contexts.shell.components.switcher-cards.view
|
||||
(:require [clojure.string :as string]
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[utils.re-frame :as rf]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.core :as rn]
|
||||
[react-native.fast-image :as fast-image]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.shell.cards.style :as style]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.components.switcher-cards.style :as style]
|
||||
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]))
|
||||
|
||||
(defn content-container
|
||||
|
@ -180,43 +182,76 @@
|
|||
|
||||
"")))
|
||||
|
||||
(defn open-screen
|
||||
[card-type id]
|
||||
(cond
|
||||
(#{shell.constants/one-to-one-chat-card
|
||||
shell.constants/private-group-chat-card
|
||||
shell.constants/community-channel-card}
|
||||
card-type)
|
||||
(rf/dispatch [:chat/navigate-to-chat id])
|
||||
|
||||
(= card-type shell.constants/community-card)
|
||||
(rf/dispatch [:navigate-to :community-overview id])))
|
||||
|
||||
(defn calculate-card-position-and-open-screen
|
||||
[card-ref card-type id]
|
||||
(when @card-ref
|
||||
(.measure
|
||||
^js
|
||||
@card-ref
|
||||
(fn [_ _ _ _ page-x page-y]
|
||||
(animation/set-floating-screen-position
|
||||
page-x
|
||||
page-y
|
||||
card-type)
|
||||
(open-screen card-type id)))))
|
||||
|
||||
;; Screens Card
|
||||
(defn screens-card
|
||||
[{:keys [avatar-params title type customization-color
|
||||
on-press on-close content banner]}]
|
||||
(let [color-50 (colors/custom-color customization-color 50)
|
||||
color-60 (colors/custom-color customization-color 60)]
|
||||
[rn/touchable-without-feedback {:on-press on-press}
|
||||
[rn/view {:style (style/base-container color-50)}
|
||||
(when banner
|
||||
[rn/image
|
||||
{:source (:source banner)
|
||||
:style {:width 160}}])
|
||||
[rn/view {:style style/secondary-container}
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:style style/title}
|
||||
title]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/subtitle}
|
||||
(subtitle type content)]
|
||||
[bottom-container type (merge {:color-50 color-50 :color-60 color-60} content)]]
|
||||
(when avatar-params
|
||||
[rn/view {:style style/avatar-container}
|
||||
[avatar avatar-params type customization-color]])
|
||||
[quo/button
|
||||
{:size 24
|
||||
:type :grey
|
||||
:icon true
|
||||
:on-press on-close
|
||||
:override-theme :dark
|
||||
:style style/close-button}
|
||||
:i/close]]]))
|
||||
[]
|
||||
(let [card-ref (atom nil)]
|
||||
(fn [{:keys [avatar-params title type customization-color
|
||||
content banner id channel-id]}]
|
||||
(let [color-50 (colors/custom-color customization-color 50)
|
||||
color-60 (colors/custom-color customization-color 60)]
|
||||
[rn/touchable-opacity
|
||||
{:on-press #(calculate-card-position-and-open-screen
|
||||
card-ref
|
||||
type
|
||||
(or channel-id id))
|
||||
:ref #(reset! card-ref %)
|
||||
:active-opacity 1}
|
||||
[rn/view {:style (style/base-container color-50)}
|
||||
(when banner
|
||||
[rn/image
|
||||
{:source (:source banner)
|
||||
:style {:width 160}}])
|
||||
[rn/view {:style style/secondary-container}
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :tail
|
||||
:style style/title}
|
||||
title]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :medium
|
||||
:style style/subtitle}
|
||||
(subtitle type content)]
|
||||
[bottom-container type (merge {:color-50 color-50 :color-60 color-60} content)]]
|
||||
(when avatar-params
|
||||
[rn/view {:style style/avatar-container}
|
||||
[avatar avatar-params type customization-color]])
|
||||
[quo/button
|
||||
{:size 24
|
||||
:type :grey
|
||||
:icon true
|
||||
:on-press #(rf/dispatch [:shell/close-switcher-card id])
|
||||
:override-theme :dark
|
||||
:style style/close-button}
|
||||
:i/close]]]))))
|
||||
|
||||
;; browser Card
|
||||
(defn browser-card
|
|
@ -1,59 +1,42 @@
|
|||
(ns status-im2.contexts.shell.constants
|
||||
(:require [react-native.platform :as platform]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.safe-area :as safe-area]))
|
||||
(ns status-im2.contexts.shell.constants)
|
||||
|
||||
(def shell-animation-time 200)
|
||||
(def ^:const shell-animation-time 200)
|
||||
(def ^:const switcher-card-size 160)
|
||||
|
||||
(defn bottom-tabs-container-height
|
||||
[]
|
||||
(if platform/android? 57 82))
|
||||
;; Bottom tabs
|
||||
(def ^:const bottom-tabs-container-height-android 57)
|
||||
(def ^:const bottom-tabs-container-height-ios 82)
|
||||
(def ^:const bottom-tabs-container-extended-height-android 90)
|
||||
(def ^:const bottom-tabs-container-extended-height-ios 120)
|
||||
(def ^:const bottom-tab-width 90)
|
||||
|
||||
(defn bottom-tabs-extended-container-height
|
||||
[]
|
||||
(if platform/android? 90 120))
|
||||
;; Stacks
|
||||
(def ^:const stacks-ids [:communities-stack :chats-stack :wallet-stack :browser-stack])
|
||||
|
||||
(defn status-bar-offset
|
||||
[]
|
||||
(if platform/android? (safe-area/get-top) 0))
|
||||
|
||||
;; status bar height is not included in : the dimensions/window for devices with a notch
|
||||
;; https://github.com/facebook/react-native/issues/23693#issuecomment-662860819
|
||||
;; More info - https://github.com/status-im/status-mobile/issues/14633
|
||||
(defn dimensions
|
||||
[]
|
||||
(let [{:keys [width height]} (rf/sub [:dimensions/window])]
|
||||
{:width width
|
||||
:height (if (> (status-bar-offset) 28)
|
||||
(+ height (status-bar-offset))
|
||||
height)}))
|
||||
|
||||
(def stacks-ids [:communities-stack :chats-stack :wallet-stack :browser-stack])
|
||||
|
||||
(def stacks-opacity-keywords
|
||||
;; Keywords
|
||||
(def ^:const stacks-opacity-keywords
|
||||
{:communities-stack :communities-stack-opacity
|
||||
:chats-stack :chats-stack-opacity
|
||||
:wallet-stack :wallet-stack-opacity
|
||||
:browser-stack :browser-stack-opacity})
|
||||
|
||||
(def tabs-icon-color-keywords
|
||||
(def ^:const tabs-icon-color-keywords
|
||||
{:communities-stack :communities-tab-icon-color
|
||||
:chats-stack :chats-tab-icon-opacity
|
||||
:wallet-stack :wallet-tab-icon-opacity
|
||||
:browser-stack :browser-tab-icon-opacity})
|
||||
|
||||
(def stacks-z-index-keywords
|
||||
(def ^:const stacks-z-index-keywords
|
||||
{:communities-stack :communities-stack-z-index
|
||||
:chats-stack :chats-stack-z-index
|
||||
:wallet-stack :wallet-stack-z-index
|
||||
:browser-stack :browser-stack-z-index})
|
||||
|
||||
;; Home stack states
|
||||
|
||||
(def ^:const close-with-animation 0)
|
||||
(def ^:const open-with-animation 1)
|
||||
(def ^:const close-without-animation 3)
|
||||
(def ^:const open-without-animation 4)
|
||||
(def ^:const close-without-animation 2)
|
||||
(def ^:const open-without-animation 3)
|
||||
|
||||
;; Switcher Cards
|
||||
(def ^:const empty-card 0)
|
||||
|
@ -66,3 +49,15 @@
|
|||
(def ^:const wallet-collectible 7)
|
||||
(def ^:const wallet-graph 8)
|
||||
(def ^:const communities-discover 9)
|
||||
|
||||
;; Floating Screens
|
||||
(def ^:const community-screen :community-overview)
|
||||
(def ^:const chat-screen :chat)
|
||||
|
||||
;; Floating Screen states
|
||||
(def ^:const close-screen-with-slide-animation 0)
|
||||
(def ^:const open-screen-with-slide-animation 1)
|
||||
(def ^:const close-screen-with-shell-animation 2)
|
||||
(def ^:const open-screen-with-shell-animation 3)
|
||||
(def ^:const close-screen-without-animation 4)
|
||||
(def ^:const open-screen-without-animation 5)
|
||||
|
|
|
@ -3,42 +3,42 @@
|
|||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.core :as utils]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.navigation.events :as navigation]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.utils :as shell.utils]
|
||||
[status-im2.navigation.state :as navigation.state]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im.data-store.switcher-cards :as switcher-cards-store]))
|
||||
|
||||
;; Effects
|
||||
;;;; Effects
|
||||
|
||||
;; Navigation
|
||||
(re-frame/reg-fx
|
||||
:shell/change-tab-fx
|
||||
(fn [stack-id]
|
||||
(when (some #(= stack-id %) shell.constants/stacks-ids)
|
||||
(animation/bottom-tab-on-press stack-id))))
|
||||
(animation/bottom-tab-on-press stack-id false))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shell/navigate-to-jump-to-fx
|
||||
(fn []
|
||||
(animation/close-home-stack false)))
|
||||
(animation/close-home-stack false)
|
||||
(some-> ^js @state/jump-to-list-ref
|
||||
(.scrollToOffset #js {:y 0 :animated false}))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shell/navigate-from-shell-fx
|
||||
(fn [stack-id]
|
||||
(animation/bottom-tab-on-press stack-id)))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:shell/reset-bottom-tabs
|
||||
:shell/pop-to-root-fx
|
||||
(fn []
|
||||
(let [selected-stack-id @animation/selected-stack-id]
|
||||
(async-storage/set-item! :selected-stack-id nil)
|
||||
(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)))))
|
||||
(reset! state/floating-screens-state {})))
|
||||
|
||||
;; Events
|
||||
(re-frame/reg-fx
|
||||
:shell/reset-state
|
||||
(fn []
|
||||
(reset! state/floating-screens-state {})))
|
||||
|
||||
;;;; Events
|
||||
|
||||
;; Switcher
|
||||
(rf/defn switcher-cards-loaded
|
||||
{:events [:shell/switcher-cards-loaded]}
|
||||
[{:keys [db]} loaded-switcher-cards]
|
||||
|
@ -53,24 +53,21 @@
|
|||
(let [chat (get-in db [:chats id])]
|
||||
(case (:chat-type chat)
|
||||
constants/one-to-one-chat-type
|
||||
{:navigate-from :chats-stack
|
||||
:card-id id
|
||||
{:card-id id
|
||||
:switcher-card {:type shell.constants/one-to-one-chat-card
|
||||
:card-id id
|
||||
:clock now
|
||||
:screen-id id}}
|
||||
|
||||
constants/private-group-chat-type
|
||||
{:navigate-from :chats-stack
|
||||
:card-id id
|
||||
{:card-id id
|
||||
:switcher-card {:type shell.constants/private-group-chat-card
|
||||
:card-id id
|
||||
:clock now
|
||||
:screen-id id}}
|
||||
|
||||
constants/community-chat-type
|
||||
{:navigate-from :communities-stack
|
||||
:card-id (:community-id chat)
|
||||
{:card-id (:community-id chat)
|
||||
:switcher-card {:type shell.constants/community-channel-card
|
||||
:card-id (:community-id chat)
|
||||
:clock now
|
||||
|
@ -79,8 +76,7 @@
|
|||
nil))
|
||||
|
||||
:community-overview
|
||||
{:navigate-from :communities-stack
|
||||
:card-id id
|
||||
{:card-id id
|
||||
:switcher-card {:type shell.constants/community-card
|
||||
:card-id id
|
||||
:clock now
|
||||
|
@ -95,11 +91,10 @@
|
|||
(when card-data
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (assoc-in
|
||||
db
|
||||
[:shell/switcher-cards (:card-id card-data)]
|
||||
switcher-card)
|
||||
:shell/navigate-from-shell-fx (:navigate-from card-data)}
|
||||
{:db (assoc-in
|
||||
db
|
||||
[:shell/switcher-cards (:card-id card-data)]
|
||||
switcher-card)}
|
||||
(switcher-cards-store/upsert-switcher-card-rpc switcher-card)))))
|
||||
|
||||
(rf/defn close-switcher-card
|
||||
|
@ -110,13 +105,29 @@
|
|||
{:db (update db :shell/switcher-cards dissoc card-id)}
|
||||
(switcher-cards-store/delete-switcher-card-rpc card-id)))
|
||||
|
||||
;; Navigation
|
||||
(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 :shell-stack)))
|
||||
[{:keys [db]}]
|
||||
(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)]
|
||||
{:db
|
||||
(cond-> db
|
||||
|
||||
chat-screen-open?
|
||||
(assoc-in [:shell/floating-screens shell.constants/chat-screen :animation]
|
||||
shell.constants/close-screen-with-shell-animation)
|
||||
|
||||
(and chat-screen-open? community-screen-open?)
|
||||
(assoc-in [:shell/floating-screens shell.constants/community-screen :animation]
|
||||
shell.constants/close-screen-without-animation)
|
||||
|
||||
(and (not chat-screen-open?) community-screen-open?)
|
||||
(assoc-in [:shell/floating-screens shell.constants/community-screen :animation]
|
||||
shell.constants/close-screen-with-shell-animation))
|
||||
|
||||
:dispatch [:set-view-id :shell]
|
||||
:shell/navigate-to-jump-to-fx nil}))
|
||||
|
||||
(rf/defn change-shell-status-bar-style
|
||||
{:events [:change-shell-status-bar-style]}
|
||||
|
@ -127,3 +138,85 @@
|
|||
{:events [:change-shell-nav-bar-color]}
|
||||
[_ color]
|
||||
{:merge-options {:id "shell-stack" :options {:navigationBar {:backgroundColor color}}}})
|
||||
|
||||
(rf/defn shell-navigate-to
|
||||
{:events [:shell/navigate-to]}
|
||||
[{:keys [db]} go-to-view-id screen-params animation hidden-screen?]
|
||||
(if (shell.utils/shell-navigation? go-to-view-id)
|
||||
(let [current-view-id (:view-id db)
|
||||
community-id (get-in db [:chats screen-params :community-id])]
|
||||
{:db (assoc-in
|
||||
db
|
||||
[:shell/floating-screens go-to-view-id]
|
||||
{:id screen-params
|
||||
:community-id community-id
|
||||
:hidden-screen? hidden-screen?
|
||||
:animation (or animation
|
||||
(case current-view-id
|
||||
:shell shell.constants/open-screen-with-shell-animation
|
||||
:chat shell.constants/open-screen-without-animation
|
||||
shell.constants/open-screen-with-slide-animation))})
|
||||
:dispatch-n (cond-> []
|
||||
(not hidden-screen?)
|
||||
(conj [:set-view-id go-to-view-id])
|
||||
(and (= go-to-view-id shell.constants/community-screen)
|
||||
(not hidden-screen?)
|
||||
(:current-chat-id db))
|
||||
(conj [:chat/close]))})
|
||||
{:db (assoc db :view-id go-to-view-id)
|
||||
:navigate-to go-to-view-id}))
|
||||
|
||||
(rf/defn shell-navigate-back
|
||||
{:events [:shell/navigate-back]}
|
||||
[{:keys [db]}]
|
||||
(let [chat-screen-open? (shell.utils/floating-screen-open? shell.constants/chat-screen)
|
||||
community-screen-open? (shell.utils/floating-screen-open? shell.constants/community-screen)
|
||||
current-chat-id (:current-chat-id db)
|
||||
community-id (when current-chat-id
|
||||
(get-in db [:chats current-chat-id :community-id]))]
|
||||
(if (and (not @navigation.state/curr-modal)
|
||||
(or chat-screen-open? community-screen-open?))
|
||||
{:db (assoc-in
|
||||
db
|
||||
[:shell/floating-screens
|
||||
(if chat-screen-open? shell.constants/chat-screen shell.constants/community-screen)
|
||||
:animation]
|
||||
shell.constants/close-screen-with-slide-animation)
|
||||
:dispatch-n (cond-> [[:set-view-id
|
||||
(cond
|
||||
(and chat-screen-open? community-screen-open?)
|
||||
shell.constants/community-screen
|
||||
community-screen-open?
|
||||
:communities-stack
|
||||
:else :chats-stack)]]
|
||||
;; When navigating back from community chat to community, update switcher card
|
||||
(and chat-screen-open? community-screen-open? community-id)
|
||||
(conj [:shell/add-switcher-card shell.constants/community-screen community-id]))}
|
||||
{:navigate-back nil})))
|
||||
|
||||
(rf/defn floating-screen-opened
|
||||
{:events [:shell/floating-screen-opened]}
|
||||
[{:keys [db]} screen-id id community-id hidden-screen?]
|
||||
(merge
|
||||
{:db (assoc-in db [:shell/loaded-screens screen-id] true)
|
||||
:shell/change-tab-fx (if (or (= screen-id shell.constants/community-screen)
|
||||
community-id)
|
||||
:communities-stack
|
||||
:chats-stack)}
|
||||
(when community-id
|
||||
;; When opening community chat, open community screen in background
|
||||
{:dispatch [:shell/navigate-to shell.constants/community-screen
|
||||
community-id shell.constants/open-screen-without-animation true]})
|
||||
;; Only update switcher cards for top screen
|
||||
(when-not hidden-screen?
|
||||
{:dispatch-later [{:ms (* 2 shell.constants/shell-animation-time)
|
||||
:dispatch [:shell/add-switcher-card screen-id id]}]})))
|
||||
|
||||
(rf/defn floating-screen-closed
|
||||
{:events [:shell/floating-screen-closed]}
|
||||
[{:keys [db]} screen-id]
|
||||
(merge
|
||||
{:db (-> (update db :shell/floating-screens dissoc screen-id)
|
||||
(update :shell/loaded-screens dissoc screen-id))}
|
||||
(when (= screen-id shell.constants/chat-screen)
|
||||
{:dispatch [:chat/close]})))
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
(ns status-im2.contexts.shell.home-stack
|
||||
(:require [react-native.reanimated :as reanimated]
|
||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||
[status-im2.contexts.chat.home.view :as chat]
|
||||
[status-im2.contexts.communities.home.view :as communities]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.style :as styles]
|
||||
[status-im.ui.screens.browser.stack :as browser.stack]))
|
||||
|
||||
(defn load-stack?
|
||||
[stack-id]
|
||||
(case stack-id
|
||||
: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- f-stack-view
|
||||
[stack-id shared-values]
|
||||
[reanimated/view
|
||||
{:style (reanimated/apply-animations-to-style
|
||||
{:opacity (get shared-values
|
||||
(get shell.constants/stacks-opacity-keywords stack-id))
|
||||
:z-index (get shared-values
|
||||
(get shell.constants/stacks-z-index-keywords stack-id))}
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0
|
||||
:accessibility-label stack-id})}
|
||||
(case stack-id
|
||||
:communities-stack [communities/home]
|
||||
:chats-stack [chat/home]
|
||||
:wallet-stack [wallet.accounts/accounts-overview-old]
|
||||
:browser-stack [browser.stack/browser-stack])])
|
||||
|
||||
(defn lazy-screen
|
||||
[stack-id shared-values]
|
||||
(when (load-stack? stack-id)
|
||||
[:f> f-stack-view stack-id shared-values]))
|
||||
|
||||
(defn f-home-stack
|
||||
[]
|
||||
(let [shared-values @animation/shared-values-atom
|
||||
home-stack-original-style (styles/home-stack @animation/screen-height)
|
||||
home-stack-animated-style (reanimated/apply-animations-to-style
|
||||
{:top (:home-stack-top shared-values)
|
||||
:left (:home-stack-left shared-values)
|
||||
:opacity (:home-stack-opacity shared-values)
|
||||
:pointer-events (:home-stack-pointer shared-values)
|
||||
:transform [{:scale (:home-stack-scale shared-values)}]}
|
||||
home-stack-original-style)]
|
||||
[reanimated/view {:style home-stack-animated-style}
|
||||
[lazy-screen :communities-stack shared-values]
|
||||
[lazy-screen :chats-stack shared-values]
|
||||
[lazy-screen :browser-stack shared-values]
|
||||
[lazy-screen :wallet-stack shared-values]]))
|
|
@ -0,0 +1,127 @@
|
|||
(ns status-im2.contexts.shell.shared-values
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[utils.worklets.shell :as worklets.shell]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
(defn calculate-home-stack-position
|
||||
[{:keys [width height]}]
|
||||
(let [bottom-nav-tab-width shell.constants/bottom-tab-width
|
||||
minimize-scale (/ bottom-nav-tab-width width)
|
||||
empty-space-half-scale (/ (- 1 minimize-scale) 2)
|
||||
left-margin (/ (- width (* 4 bottom-nav-tab-width)) 2)
|
||||
left-empty-space (* empty-space-half-scale width)
|
||||
top-empty-space (* empty-space-half-scale
|
||||
(- height (utils/bottom-tabs-container-height)))]
|
||||
{:left (reduce
|
||||
(fn [acc stack-id]
|
||||
(assoc acc
|
||||
stack-id
|
||||
(+ (- left-margin left-empty-space)
|
||||
(* (.indexOf shell.constants/stacks-ids stack-id)
|
||||
bottom-nav-tab-width))))
|
||||
{:none 0}
|
||||
shell.constants/stacks-ids)
|
||||
:top (+ top-empty-space (utils/bottom-tabs-container-height))
|
||||
:scale minimize-scale}))
|
||||
|
||||
(defn stacks-and-bottom-tabs-derived-values
|
||||
[{:keys [selected-stack-id home-stack-state]}]
|
||||
(let [pass-through (reanimated/use-shared-value false)]
|
||||
(reduce
|
||||
(fn [acc id]
|
||||
(let [tabs-icon-color-keyword (get shell.constants/tabs-icon-color-keywords id)
|
||||
stack-opacity-keyword (get shell.constants/stacks-opacity-keywords id)
|
||||
stack-z-index-keyword (get shell.constants/stacks-z-index-keywords id)]
|
||||
(assoc
|
||||
acc
|
||||
stack-opacity-keyword
|
||||
(worklets.shell/stack-opacity (name id) selected-stack-id)
|
||||
stack-z-index-keyword
|
||||
(worklets.shell/stack-z-index (name id) selected-stack-id)
|
||||
tabs-icon-color-keyword
|
||||
(worklets.shell/bottom-tab-icon-color
|
||||
(name id)
|
||||
selected-stack-id
|
||||
home-stack-state
|
||||
pass-through
|
||||
colors/white
|
||||
colors/neutral-50
|
||||
colors/white-opa-40))))
|
||||
{:bottom-tabs-height (worklets.shell/bottom-tabs-height
|
||||
home-stack-state
|
||||
(utils/bottom-tabs-container-height)
|
||||
(utils/bottom-tabs-extended-container-height))
|
||||
:pass-through pass-through}
|
||||
shell.constants/stacks-ids)))
|
||||
|
||||
(defn home-stack-derived-values
|
||||
[{:keys [selected-stack-id home-stack-state]} dimensions]
|
||||
(let [home-stack-position (calculate-home-stack-position dimensions)
|
||||
animate-home-stack-left (reanimated/use-shared-value (not (utils/home-stack-open?)))]
|
||||
{:animate-home-stack-left animate-home-stack-left
|
||||
:home-stack-left (worklets.shell/home-stack-left
|
||||
selected-stack-id
|
||||
animate-home-stack-left
|
||||
home-stack-state
|
||||
(clj->js (:left home-stack-position)))
|
||||
:home-stack-top (worklets.shell/home-stack-top
|
||||
home-stack-state
|
||||
(:top home-stack-position))
|
||||
:home-stack-opacity (worklets.shell/home-stack-opacity home-stack-state)
|
||||
:home-stack-pointer (worklets.shell/home-stack-pointer home-stack-state)
|
||||
:home-stack-scale (worklets.shell/home-stack-scale
|
||||
home-stack-state
|
||||
(:scale home-stack-position))}))
|
||||
|
||||
(defn floating-screen-derived-values
|
||||
[screen-id {:keys [width height]} switcher-card-left-position switcher-card-top-position]
|
||||
(let [screen-state (reanimated/use-shared-value
|
||||
(if (utils/floating-screen-open? screen-id)
|
||||
shell.constants/open-screen-without-animation
|
||||
shell.constants/close-screen-without-animation))]
|
||||
{:screen-state screen-state
|
||||
:screen-left (worklets.shell/floating-screen-left screen-state width switcher-card-left-position)
|
||||
:screen-top (worklets.shell/floating-screen-top screen-state switcher-card-top-position)
|
||||
:screen-z-index (worklets.shell/floating-screen-z-index screen-state)
|
||||
:screen-width (worklets.shell/floating-screen-width screen-state
|
||||
width
|
||||
shell.constants/switcher-card-size)
|
||||
:screen-height (worklets.shell/floating-screen-height screen-state
|
||||
height
|
||||
shell.constants/switcher-card-size)}))
|
||||
|
||||
(defn calculate-and-set-shared-values
|
||||
[]
|
||||
(let [{:keys [width] :as dimensions} (utils/dimensions)
|
||||
switcher-card-left-position (/ (- width (* 2 shell.constants/switcher-card-size)) 3)
|
||||
switcher-card-top-position (+ (safe-area/get-top) 120)
|
||||
shared-values
|
||||
{:selected-stack-id (reanimated/use-shared-value
|
||||
(name (or @state/selected-stack-id :communities-stack)))
|
||||
:home-stack-state (reanimated/use-shared-value @state/home-stack-state)}]
|
||||
;; Whenever shell stack is created, calculate shared values function is called
|
||||
;; Means On login and on UI reloading (like changing theme)
|
||||
;; So we are also resetting bottom tabs here (disabling loading of unselected tabs),
|
||||
;; for Speed up UI reloading
|
||||
(utils/reset-bottom-tabs)
|
||||
(reset!
|
||||
state/shared-values-atom
|
||||
(merge
|
||||
shared-values
|
||||
(stacks-and-bottom-tabs-derived-values shared-values)
|
||||
(home-stack-derived-values shared-values dimensions)
|
||||
{shell.constants/community-screen (floating-screen-derived-values
|
||||
shell.constants/community-screen
|
||||
dimensions
|
||||
switcher-card-left-position
|
||||
switcher-card-top-position)
|
||||
shell.constants/chat-screen (floating-screen-derived-values
|
||||
shell.constants/chat-screen
|
||||
dimensions
|
||||
switcher-card-left-position
|
||||
switcher-card-top-position)}))
|
||||
@state/shared-values-atom))
|
|
@ -0,0 +1,18 @@
|
|||
(ns status-im2.contexts.shell.state
|
||||
(:require [reagent.core :as reagent]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
;; Atoms
|
||||
(def selected-stack-id (atom nil))
|
||||
(def screen-height (atom nil))
|
||||
(def shared-values-atom (atom nil))
|
||||
(def jump-to-list-ref (atom nil))
|
||||
|
||||
(def home-stack-state (atom shell.constants/close-with-animation))
|
||||
(def floating-screens-state (atom {}))
|
||||
|
||||
;; 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))
|
|
@ -1,108 +0,0 @@
|
|||
(ns status-im2.contexts.shell.style
|
||||
(:require [quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
;; Bottom Tabs
|
||||
(defn bottom-tabs-container
|
||||
[pass-through?]
|
||||
{:background-color (if pass-through? :transparent colors/neutral-100)
|
||||
:flex 1
|
||||
:align-items :center
|
||||
:height (shell.constants/bottom-tabs-container-height)
|
||||
:position :absolute
|
||||
:bottom 0
|
||||
:right 0
|
||||
:left 0
|
||||
:overflow :hidden
|
||||
:accessibility-label :bottom-tabs-container})
|
||||
|
||||
(defn bottom-tabs
|
||||
[]
|
||||
{:flex-direction :row
|
||||
:position :absolute
|
||||
:bottom (if platform/android? 8 34)
|
||||
:flex 1
|
||||
:accessibility-label :bottom-tabs})
|
||||
|
||||
(def bottom-tabs-blur-overlay
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:height (shell.constants/bottom-tabs-extended-container-height)
|
||||
:background-color colors/neutral-100-opa-70})
|
||||
|
||||
;; Home Stack
|
||||
(defn home-stack
|
||||
[screen-height]
|
||||
(let [{:keys [width height]} (shell.constants/dimensions)
|
||||
height (or screen-height height)]
|
||||
{:border-bottom-left-radius 20
|
||||
:border-bottom-right-radius 20
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:overflow :hidden
|
||||
:position :absolute
|
||||
:width width
|
||||
:height (- height (shell.constants/bottom-tabs-container-height))}))
|
||||
|
||||
;; Placeholder
|
||||
(defn placeholder-container
|
||||
[status-bar-height]
|
||||
{:position :absolute
|
||||
:top (+ 112 status-bar-height)
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom (shell.constants/bottom-tabs-container-height)
|
||||
:align-items :center
|
||||
:accessibility-label :shell-placeholder-view})
|
||||
|
||||
(def placeholder-image
|
||||
{:margin-top 186
|
||||
:width 120
|
||||
:height 120
|
||||
;; Code to remove once placeholder image/vector will be available
|
||||
:border-width 5
|
||||
:border-radius 10
|
||||
:border-color :red})
|
||||
|
||||
(def placeholder-title
|
||||
{:margin-top 20
|
||||
:color colors/white})
|
||||
|
||||
(def placeholder-subtitle
|
||||
{:margin-top 4
|
||||
:color colors/white})
|
||||
|
||||
;; Shell
|
||||
(defn jump-to-text
|
||||
[status-bar-height]
|
||||
{:color colors/white
|
||||
:margin-top (+ 68 status-bar-height)
|
||||
:margin-bottom 20
|
||||
:margin-left 20})
|
||||
|
||||
(def jump-to-list
|
||||
{:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom 0
|
||||
:position :absolute})
|
||||
|
||||
(defn top-nav-blur-overlay-container
|
||||
[height pass-through?]
|
||||
{:height height
|
||||
:position :absolute
|
||||
:left 0
|
||||
:top 0
|
||||
:right 0
|
||||
:overflow :hidden
|
||||
:background-color (if pass-through? :transparent colors/neutral-100)})
|
||||
|
||||
(def top-nav-blur-overlay
|
||||
{:height 100
|
||||
:position :absolute
|
||||
:left 0
|
||||
:right 0
|
||||
:top 0
|
||||
:background-color colors/neutral-100-opa-70})
|
|
@ -0,0 +1,120 @@
|
|||
(ns status-im2.contexts.shell.utils
|
||||
(:require [utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.contexts.shell.state :as state]
|
||||
[status-im.async-storage.core :as async-storage]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
;;;; Helper Functions
|
||||
|
||||
;;; UI
|
||||
(defn bottom-tabs-container-height
|
||||
[]
|
||||
(if platform/android?
|
||||
shell.constants/bottom-tabs-container-height-android
|
||||
shell.constants/bottom-tabs-container-height-ios))
|
||||
|
||||
(defn bottom-tabs-extended-container-height
|
||||
[]
|
||||
(if platform/android?
|
||||
shell.constants/bottom-tabs-container-extended-height-android
|
||||
shell.constants/bottom-tabs-container-extended-height-ios))
|
||||
|
||||
(defn status-bar-offset
|
||||
[]
|
||||
(if platform/android? (safe-area/get-top) 0))
|
||||
|
||||
;; status bar height is not included in : the dimensions/window for devices with a notch
|
||||
;; https://github.com/facebook/react-native/issues/23693#issuecomment-662860819
|
||||
;; More info - https://github.com/status-im/status-mobile/issues/14633
|
||||
(defn dimensions
|
||||
[]
|
||||
(let [{:keys [width height]} (rn/get-window)]
|
||||
{:width width
|
||||
:height (or @state/screen-height
|
||||
(if (> (status-bar-offset) 28)
|
||||
(+ height (status-bar-offset))
|
||||
height))}))
|
||||
|
||||
;;;; State
|
||||
|
||||
;;; Home Stack
|
||||
(defn home-stack-open?
|
||||
[]
|
||||
(let [state @state/home-stack-state]
|
||||
(or (= state shell.constants/open-with-animation)
|
||||
(= state shell.constants/open-without-animation))))
|
||||
|
||||
(defn calculate-home-stack-state-value
|
||||
[stack-id animate?]
|
||||
(if animate?
|
||||
(if (some? stack-id)
|
||||
shell.constants/open-with-animation
|
||||
shell.constants/close-with-animation)
|
||||
(if (some? stack-id)
|
||||
shell.constants/open-without-animation
|
||||
shell.constants/close-without-animation)))
|
||||
|
||||
(defn load-stack
|
||||
[stack-id]
|
||||
(case stack-id
|
||||
:communities-stack (reset! state/load-communities-stack? true)
|
||||
:chats-stack (reset! state/load-chats-stack? true)
|
||||
:wallet-stack (reset! state/load-wallet-stack? true)
|
||||
:browser-stack (reset! state/load-browser-stack? true)
|
||||
""))
|
||||
|
||||
(defn change-selected-stack-id
|
||||
[stack-id store? home-stack-state-value]
|
||||
(let [home-stack-state-value (or home-stack-state-value
|
||||
(calculate-home-stack-state-value stack-id nil))]
|
||||
(reset! state/selected-stack-id stack-id)
|
||||
(reset! state/home-stack-state home-stack-state-value)
|
||||
(when store?
|
||||
(async-storage/set-item! :selected-stack-id stack-id))))
|
||||
|
||||
(defn reset-bottom-tabs
|
||||
[]
|
||||
(let [selected-stack-id @state/selected-stack-id]
|
||||
(reset! state/load-communities-stack? (= selected-stack-id :communities-stack))
|
||||
(reset! state/load-chats-stack? (= selected-stack-id :chats-stack))
|
||||
(reset! state/load-wallet-stack? (= selected-stack-id :wallet-stack))
|
||||
(reset! state/load-browser-stack? (= selected-stack-id :browser-stack))))
|
||||
|
||||
;;; Floating screen
|
||||
(defn floating-screen-open?
|
||||
[screen-id]
|
||||
(let [state (get @state/floating-screens-state screen-id)]
|
||||
(or (= state shell.constants/open-screen-with-slide-animation)
|
||||
(= state shell.constants/open-screen-with-shell-animation)
|
||||
(= state shell.constants/open-screen-without-animation))))
|
||||
|
||||
;;; Navigation
|
||||
(defn shell-navigation?
|
||||
[view-id]
|
||||
(#{:chat :community-overview} view-id))
|
||||
|
||||
(defn calculate-view-id
|
||||
[]
|
||||
(cond
|
||||
(floating-screen-open? shell.constants/chat-screen)
|
||||
shell.constants/chat-screen
|
||||
(floating-screen-open? shell.constants/community-screen)
|
||||
shell.constants/community-screen
|
||||
:else (or @state/selected-stack-id :shell)))
|
||||
|
||||
(defn update-view-id
|
||||
[view-id]
|
||||
(rf/dispatch [:set-view-id view-id]))
|
||||
|
||||
;;; Misc
|
||||
(defn change-shell-status-bar-style
|
||||
[]
|
||||
(rf/dispatch [:change-shell-status-bar-style
|
||||
(if (or (colors/dark?)
|
||||
(not (home-stack-open?)))
|
||||
:light
|
||||
:dark)]))
|
|
@ -1,136 +1,53 @@
|
|||
(ns status-im2.contexts.shell.view
|
||||
(:require [utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
(:require [quo2.core :as quo]
|
||||
[utils.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[react-native.core :as rn]
|
||||
[react-native.blur :as blur]
|
||||
[react-native.linear-gradient :as linear-gradient]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[status-im2.common.home.view :as common.home]
|
||||
[status-im2.contexts.shell.utils :as utils]
|
||||
[status-im2.navigation.state :as navigation.state]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
|
||||
[status-im2.contexts.shell.cards.view :as switcher-cards]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]
|
||||
[status-im2.contexts.shell.home-stack :as home-stack]
|
||||
[status-im2.contexts.shell.style :as style]
|
||||
[utils.re-frame :as rf]))
|
||||
[status-im2.contexts.shell.shared-values :as shared-values]
|
||||
[status-im2.contexts.shell.components.home-stack.view :as home-stack]
|
||||
[status-im2.contexts.shell.components.bottom-tabs.view :as bottom-tabs]
|
||||
[status-im2.contexts.shell.components.shell-screen.view :as shell-screen]
|
||||
[status-im2.contexts.shell.components.floating-screens.view :as floating-screens]))
|
||||
|
||||
(defn placeholder
|
||||
(defn navigate-back-handler
|
||||
[]
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [colors/neutral-100-opa-0 colors/neutral-100-opa-100]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0 :y 1}
|
||||
:style (style/placeholder-container (safe-area/get-top))}
|
||||
[rn/image
|
||||
{:source nil ;; TODO(parvesh) - add placeholder image
|
||||
:style style/placeholder-image}]
|
||||
[quo/text
|
||||
{:size :paragraph-1
|
||||
:weight :semi-bold
|
||||
:style style/placeholder-title}
|
||||
(i18n/label :t/shell-placeholder-title)]
|
||||
[quo/text
|
||||
{:size :paragraph-2
|
||||
:weight :regular
|
||||
:align :center
|
||||
:style style/placeholder-subtitle}
|
||||
(i18n/label :t/shell-placeholder-subtitle)]])
|
||||
|
||||
(defn jump-to-text
|
||||
[]
|
||||
[quo/text
|
||||
{:size :heading-1
|
||||
:weight :semi-bold
|
||||
:style (style/jump-to-text (safe-area/get-top))}
|
||||
(i18n/label :t/jump-to)])
|
||||
|
||||
(defn render-card
|
||||
[{:keys [type screen-id] :as card}]
|
||||
(let [card-data (case type
|
||||
shell.constants/one-to-one-chat-card
|
||||
(rf/sub [:shell/one-to-one-chat-card screen-id])
|
||||
|
||||
shell.constants/private-group-chat-card
|
||||
(rf/sub [:shell/private-group-chat-card screen-id])
|
||||
|
||||
shell.constants/community-card
|
||||
(rf/sub [:shell/community-card screen-id])
|
||||
|
||||
shell.constants/community-channel-card
|
||||
(rf/sub [:shell/community-channel-card screen-id])
|
||||
|
||||
nil)]
|
||||
[switcher-cards/card (merge card card-data)]))
|
||||
|
||||
(def empty-cards (repeat 6 {:type shell.constants/empty-card}))
|
||||
|
||||
(defn jump-to-list
|
||||
[switcher-cards shell-margin]
|
||||
(let [data (if (seq switcher-cards) switcher-cards empty-cards)]
|
||||
[:<>
|
||||
[rn/flat-list
|
||||
{:data data
|
||||
: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 style/jump-to-list
|
||||
:content-container-style {:padding-bottom (shell.constants/bottom-tabs-container-height)}}]
|
||||
(when-not (seq switcher-cards)
|
||||
[placeholder])]))
|
||||
|
||||
(defn top-nav-blur-overlay
|
||||
[top]
|
||||
(let [pass-through? (rf/sub [:shell/shell-pass-through?])]
|
||||
[rn/view {:style (style/top-nav-blur-overlay-container (+ 56 top) pass-through?)}
|
||||
(when pass-through?
|
||||
[blur/view (bottom-tabs/blur-overlay-params style/top-nav-blur-overlay)])]))
|
||||
|
||||
(defn shell
|
||||
[customization-color]
|
||||
(let [switcher-cards (rf/sub [:shell/sorted-switcher-cards])
|
||||
width (rf/sub [:dimensions/window-width])
|
||||
top (safe-area/get-top)
|
||||
shell-margin (/ (- width 320) 3)] ;; 320 - two cards width
|
||||
[rn/view
|
||||
{:style {:top 0
|
||||
:left 0
|
||||
:right 0
|
||||
:bottom -1
|
||||
:position :absolute
|
||||
:background-color colors/neutral-100}}
|
||||
[jump-to-list switcher-cards shell-margin]
|
||||
[top-nav-blur-overlay top]
|
||||
[common.home/top-nav
|
||||
{:type :shell
|
||||
:avatar {:customization-color customization-color}
|
||||
:style {:margin-top top
|
||||
:z-index 2}}]]))
|
||||
(if (and (not @navigation.state/curr-modal)
|
||||
(or
|
||||
(utils/floating-screen-open? shell.constants/community-screen)
|
||||
(utils/floating-screen-open? shell.constants/chat-screen)))
|
||||
(do (rf/dispatch [:navigate-back])
|
||||
true)
|
||||
false))
|
||||
|
||||
(defn f-shell-stack
|
||||
[]
|
||||
(let [shared-values (animation/calculate-shared-values)
|
||||
(let [shared-values (shared-values/calculate-and-set-shared-values)
|
||||
{:keys [key-uid]} (rf/sub [:multiaccount])
|
||||
profile-color (:color (rf/sub [:onboarding-2/profile]))
|
||||
customization-color (if profile-color
|
||||
profile-color
|
||||
customization-color (if profile-color ;; Todo - 1. Use single sub for customization color
|
||||
profile-color ;; Todo - 2. Move sub to child view
|
||||
(rf/sub [:profile/customization-color key-uid]))]
|
||||
[rn/view
|
||||
{:style {:flex 1}}
|
||||
[shell customization-color]
|
||||
[bottom-tabs/bottom-tabs]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(rn/hw-back-add-listener navigate-back-handler)
|
||||
#(rn/hw-back-remove-listener navigate-back-handler))
|
||||
[])
|
||||
[:<>
|
||||
[shell-screen/view customization-color]
|
||||
[:f> bottom-tabs/f-bottom-tabs]
|
||||
[:f> home-stack/f-home-stack]
|
||||
[quo/floating-shell-button
|
||||
{:jump-to {:on-press #(animation/close-home-stack true)
|
||||
:label (i18n/label :t/jump-to)
|
||||
:customization-color customization-color}}
|
||||
{:position :absolute
|
||||
:bottom (+ (shell.constants/bottom-tabs-container-height) 12)}
|
||||
(:home-stack-opacity shared-values)]]))
|
||||
:bottom (+ (utils/bottom-tabs-container-height) 12)}
|
||||
(:home-stack-opacity shared-values)]
|
||||
[floating-screens/view]]))
|
||||
|
||||
(defn shell-stack
|
||||
[]
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
[react-native.platform :as platform]
|
||||
[react-native.shake :as react-native-shake]
|
||||
[reagent.impl.batching :as batching]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[status-im2.contexts.shell.utils :as shell.utils]
|
||||
[status-im2.contexts.shell.state :as shell.state]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.setup.dev :as dev]
|
||||
[status-im2.setup.global-error :as global-error]
|
||||
|
@ -44,10 +45,9 @@
|
|||
(react-native-shake/add-shake-listener #(re-frame/dispatch [:shake-event]))
|
||||
(utils.universal-links/initialize)
|
||||
|
||||
;; TODO(parvesh) - Remove while moving functionality to status-go
|
||||
(async-storage/get-item :selected-stack-id #(animation/change-selected-stack-id %))
|
||||
|
||||
(async-storage/get-item :screen-height #(reset! animation/screen-height %))
|
||||
;; Shell
|
||||
(async-storage/get-item :selected-stack-id #(shell.utils/change-selected-stack-id % nil nil))
|
||||
(async-storage/get-item :screen-height #(reset! shell.state/screen-height %))
|
||||
|
||||
(dev/setup)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
[react-native.gesture :as gesture]
|
||||
[react-native.navigation :as navigation]
|
||||
[status-im.multiaccounts.login.core :as login-core]
|
||||
[status-im2.contexts.shell.animation :as shell.animation]
|
||||
[status-im2.navigation.roots :as roots]
|
||||
[status-im2.navigation.state :as state]
|
||||
[status-im2.navigation.view :as views]
|
||||
|
@ -36,14 +35,16 @@
|
|||
|
||||
(defn set-view-id
|
||||
[view-id]
|
||||
(when-let [{:keys [on-focus]} (get views/screens view-id)]
|
||||
(re-frame/dispatch [:screens/on-will-focus view-id])
|
||||
(re-frame/dispatch [:set-view-id
|
||||
(if (= view-id :shell-stack)
|
||||
(or @shell.animation/selected-stack-id :shell)
|
||||
view-id)])
|
||||
(when on-focus
|
||||
(re-frame/dispatch on-focus))))
|
||||
(when (get views/screens view-id)
|
||||
(re-frame/dispatch [:set-view-id view-id])))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:set-view-id-fx
|
||||
(fn [view-id]
|
||||
(re-frame/dispatch [:screens/on-will-focus view-id])
|
||||
(when-let [{:keys [on-focus]} (get views/screens view-id)]
|
||||
(when on-focus
|
||||
(re-frame/dispatch on-focus)))))
|
||||
|
||||
(navigation/reg-component-did-appear-listener
|
||||
(fn [view-id]
|
||||
|
@ -106,7 +107,12 @@
|
|||
(dissmissModal)
|
||||
(navigation/pop (name @state/root-id)))))
|
||||
|
||||
(re-frame/reg-fx :pop-to-root-fx navigation/pop-to-root)
|
||||
(defn pop-to-root
|
||||
[root-id]
|
||||
(navigation/pop-to-root root-id)
|
||||
(dismiss-all-modals))
|
||||
|
||||
(re-frame/reg-fx :pop-to-root-fx pop-to-root)
|
||||
|
||||
;; MODAL
|
||||
(defn open-modal
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
(ns status-im2.navigation.events
|
||||
(:require [utils.re-frame :as rf]))
|
||||
(:require [utils.re-frame :as rf]
|
||||
[status-im2.contexts.shell.utils :as shell.utils]
|
||||
[status-im2.contexts.shell.events :as shell.events]))
|
||||
|
||||
(defn- all-screens-params
|
||||
[db view screen-params]
|
||||
|
@ -12,17 +14,12 @@
|
|||
|
||||
(rf/defn navigate-to
|
||||
{:events [:navigate-to]}
|
||||
[{:keys [db]} go-to-view-id screen-params]
|
||||
(merge
|
||||
{:db (-> (assoc db :view-id go-to-view-id)
|
||||
(all-screens-params go-to-view-id screen-params))
|
||||
:navigate-to go-to-view-id
|
||||
:dispatch [:hide-bottom-sheet]}
|
||||
(when (#{:chat :community-overview} go-to-view-id)
|
||||
{:dispatch-later
|
||||
;; 300 ms delay because, navigation is priority over shell card update
|
||||
[{:dispatch [:shell/add-switcher-card go-to-view-id screen-params]
|
||||
:ms 300}]})))
|
||||
[{:keys [db] :as cofx} go-to-view-id screen-params]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:db (all-screens-params db go-to-view-id screen-params)
|
||||
:dispatch-n [[:hide-bottom-sheet]]}
|
||||
(shell.events/shell-navigate-to go-to-view-id screen-params nil nil)))
|
||||
|
||||
(rf/defn open-modal
|
||||
{:events [:open-modal]}
|
||||
|
@ -34,13 +31,15 @@
|
|||
|
||||
(rf/defn navigate-back
|
||||
{:events [:navigate-back]}
|
||||
[_]
|
||||
{:navigate-back nil})
|
||||
[cofx]
|
||||
(shell.events/shell-navigate-back cofx))
|
||||
|
||||
(rf/defn pop-to-root
|
||||
{:events [:pop-to-root]}
|
||||
[_ tab]
|
||||
{:pop-to-root-fx tab})
|
||||
[{:keys [db]} tab]
|
||||
{:pop-to-root-fx tab
|
||||
:db (dissoc db :shell/floating-screens)
|
||||
:shell/pop-to-root-fx nil})
|
||||
|
||||
(rf/defn init-root
|
||||
{:events [:init-root]}
|
||||
|
@ -54,8 +53,9 @@
|
|||
|
||||
(rf/defn change-tab
|
||||
{:events [:navigate-change-tab]}
|
||||
[_ stack-id]
|
||||
{:shell/change-tab-fx stack-id})
|
||||
[{:keys [db]} stack-id]
|
||||
{:db (assoc db :view-id stack-id)
|
||||
:shell/change-tab-fx stack-id})
|
||||
|
||||
(rf/defn navigate-replace
|
||||
{:events [:navigate-replace]}
|
||||
|
@ -154,3 +154,10 @@
|
|||
[:hide-select-acc-sheet]
|
||||
[:bottom-sheet/hide-old-navigation-overlay]
|
||||
[:toasts/close-all-toasts]]})
|
||||
|
||||
(rf/defn set-view-id
|
||||
{:events [:set-view-id]}
|
||||
[{:keys [db]} view-id]
|
||||
(let [view-id (if (= view-id :shell-stack) (shell.utils/calculate-view-id) view-id)]
|
||||
{:db (assoc db :view-id view-id)
|
||||
:set-view-id-fx view-id}))
|
||||
|
|
|
@ -75,6 +75,8 @@
|
|||
(reg-root-key-sub :visibility-status-updates :visibility-status-updates)
|
||||
(reg-root-key-sub :shell/switcher-cards :shell/switcher-cards)
|
||||
(reg-root-key-sub :password-authentication :password-authentication)
|
||||
(reg-root-key-sub :shell/floating-screens :shell/floating-screens)
|
||||
(reg-root-key-sub :shell/loaded-screens :shell/loaded-screens)
|
||||
|
||||
;;NOTE this one is not related to ethereum network
|
||||
;; it is about cellular network/ wifi network
|
||||
|
|
|
@ -2,8 +2,11 @@
|
|||
(:require [re-frame.core :as re-frame]
|
||||
[utils.datetime :as datetime]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.common.resources :as resources]))
|
||||
[react-native.platform :as platform]
|
||||
[status-im2.common.resources :as resources]
|
||||
[status-im2.contexts.shell.constants :as shell.constants]))
|
||||
|
||||
;; Helper Functions
|
||||
(defn community-avatar
|
||||
[community]
|
||||
(let [images (:images community)]
|
||||
|
@ -66,18 +69,16 @@
|
|||
: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/navigate-to-chat id])
|
||||
:content (get-card-content chat communities)}))
|
||||
:content (get-card-content chat communities)
|
||||
:id id}))
|
||||
|
||||
(defn private-group-chat-card
|
||||
[chat id communities]
|
||||
{: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/navigate-to-chat id])
|
||||
:content (get-card-content chat communities)})
|
||||
:content (get-card-content chat communities)
|
||||
:id id})
|
||||
|
||||
(defn community-card
|
||||
[community id]
|
||||
|
@ -87,22 +88,18 @@
|
|||
{: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 :community-overview id])
|
||||
:content {:community-info {:type :permission}}}))
|
||||
:content {:community-info {:type :permission}}
|
||||
:id id}))
|
||||
|
||||
(defn community-channel-card
|
||||
[community community-id channel channel-id]
|
||||
(merge
|
||||
(community-card community community-id)
|
||||
{:content {:community-channel {:emoji (:emoji channel)
|
||||
:channel-name (str "# " (:name channel))}}
|
||||
:on-press (fn []
|
||||
(re-frame/dispatch [:navigate-to :community-overview community-id])
|
||||
(js/setTimeout
|
||||
#(re-frame/dispatch [:chat/navigate-to-chat channel-id])
|
||||
100))}))
|
||||
{:content {:community-channel {:emoji (:emoji channel)
|
||||
:channel-name (str "# " (:name channel))}}
|
||||
:channel-id channel-id}))
|
||||
|
||||
;;;; Subscriptions
|
||||
(def memo-shell-cards (atom nil))
|
||||
|
||||
(re-frame/reg-sub
|
||||
|
@ -122,6 +119,7 @@
|
|||
(fn [stacks]
|
||||
(> (count stacks) 6)))
|
||||
|
||||
;; Switcher Cards
|
||||
(re-frame/reg-sub
|
||||
:shell/one-to-one-chat-card
|
||||
(fn [[_ id] _]
|
||||
|
@ -157,6 +155,7 @@
|
|||
community (get communities (:community-id channel))]
|
||||
(community-channel-card community community-id channel channel-id))))
|
||||
|
||||
;; Bottom tabs
|
||||
(re-frame/reg-sub
|
||||
:shell/bottom-tabs-notifications-data
|
||||
:<- [:chats/chats]
|
||||
|
@ -191,3 +190,19 @@
|
|||
{:new-notifications? (pos? (:unviewed-messages-count chats-stack))
|
||||
:notification-indicator (if (pos? (:unviewed-mentions-count chats-stack)) :counter :unread-dot)
|
||||
:counter-label (:unviewed-mentions-count chats-stack)}})))
|
||||
|
||||
;; Floating screens
|
||||
(re-frame/reg-sub
|
||||
:shell/floating-screen
|
||||
:<- [:shell/floating-screens]
|
||||
(fn [screens [_ screen-id]]
|
||||
(get screens screen-id)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:shell/animation-complete?
|
||||
:<- [:shell/loaded-screens]
|
||||
(fn [screens [_ chat-type]]
|
||||
(or platform/ios?
|
||||
(cond-> (get screens shell.constants/chat-screen)
|
||||
(= chat-type constants/community-chat-type)
|
||||
(and (get screens shell.constants/community-screen))))))
|
||||
|
|
|
@ -1,23 +1,21 @@
|
|||
(ns utils.worklets.shell)
|
||||
|
||||
(def shell-worklets (js/require "../src/js/worklets/shell.js"))
|
||||
|
||||
(defn stack-opacity
|
||||
[id selected-stack-id]
|
||||
(.stackOpacity ^js shell-worklets id selected-stack-id))
|
||||
|
||||
(defn stack-z-index
|
||||
[id selected-stack-id]
|
||||
(.stackZIndex ^js shell-worklets id selected-stack-id))
|
||||
(def bottom-tabs-worklets (js/require "../src/js/worklets/shell/bottom_tabs.js"))
|
||||
(def home-stack-worklets (js/require "../src/js/worklets/shell/home_stack.js"))
|
||||
(def floating-screen-worklets (js/require "../src/js/worklets/shell/floating_screen.js"))
|
||||
|
||||
;; Derived values for Bottom tabs
|
||||
(defn bottom-tabs-height
|
||||
[home-stack-state-sv container-height extended-container-height]
|
||||
(.bottomTabsHeight ^js shell-worklets home-stack-state-sv container-height extended-container-height))
|
||||
(.bottomTabsHeight ^js bottom-tabs-worklets
|
||||
home-stack-state-sv
|
||||
container-height
|
||||
extended-container-height))
|
||||
|
||||
(defn bottom-tab-icon-color
|
||||
[id selected-stack-id-sv home-stack-state-sv pass-through-sv selected-tab-color default-color
|
||||
pass-through-color]
|
||||
(.bottomTabIconColor ^js shell-worklets
|
||||
(.bottomTabIconColor ^js bottom-tabs-worklets
|
||||
id
|
||||
selected-stack-id-sv
|
||||
home-stack-state-sv
|
||||
|
@ -26,22 +24,32 @@
|
|||
default-color
|
||||
pass-through-color))
|
||||
|
||||
;; Derived values for stacks (communities, chat, wallet, browser)
|
||||
(defn stack-opacity
|
||||
[id selected-stack-id]
|
||||
(.stackOpacity ^js home-stack-worklets id selected-stack-id))
|
||||
|
||||
(defn stack-z-index
|
||||
[id selected-stack-id]
|
||||
(.stackZIndex ^js home-stack-worklets id selected-stack-id))
|
||||
|
||||
;; Derived values for Home stack (container)
|
||||
(defn home-stack-opacity
|
||||
[home-stack-state-sv]
|
||||
(.homeStackOpacity ^js shell-worklets home-stack-state-sv))
|
||||
(.homeStackOpacity ^js home-stack-worklets home-stack-state-sv))
|
||||
|
||||
(defn home-stack-pointer
|
||||
[home-stack-state-sv]
|
||||
(.homeStackPointer ^js shell-worklets home-stack-state-sv))
|
||||
(.homeStackPointer ^js home-stack-worklets home-stack-state-sv))
|
||||
|
||||
(defn home-stack-scale
|
||||
[home-stack-state-sv scale]
|
||||
(.homeStackScale ^js shell-worklets home-stack-state-sv scale))
|
||||
(.homeStackScale ^js home-stack-worklets home-stack-state-sv scale))
|
||||
|
||||
(defn home-stack-left
|
||||
[selected-stack-id-sv animate-home-stack-left home-stack-state-sv left-home-stack-position]
|
||||
(.homeStackLeft
|
||||
^js shell-worklets
|
||||
^js home-stack-worklets
|
||||
selected-stack-id-sv
|
||||
animate-home-stack-left
|
||||
home-stack-state-sv
|
||||
|
@ -49,4 +57,25 @@
|
|||
|
||||
(defn home-stack-top
|
||||
[home-stack-state-sv top-home-stack-position]
|
||||
(.homeStackTop ^js shell-worklets home-stack-state-sv top-home-stack-position))
|
||||
(.homeStackTop ^js home-stack-worklets home-stack-state-sv top-home-stack-position))
|
||||
|
||||
;; Derived values for floating screen
|
||||
(defn floating-screen-left
|
||||
[screen-state screen-width switcher-card-left-position]
|
||||
(.screenLeft ^js floating-screen-worklets screen-state screen-width switcher-card-left-position))
|
||||
|
||||
(defn floating-screen-top
|
||||
[screen-state switcher-card-top-position]
|
||||
(.screenTop ^js floating-screen-worklets screen-state switcher-card-top-position))
|
||||
|
||||
(defn floating-screen-width
|
||||
[screen-state screen-width switcher-card-size]
|
||||
(.screenWidth ^js floating-screen-worklets screen-state screen-width switcher-card-size))
|
||||
|
||||
(defn floating-screen-height
|
||||
[screen-state screen-height switcher-card-size]
|
||||
(.screenHeight ^js floating-screen-worklets screen-state screen-height switcher-card-size))
|
||||
|
||||
(defn floating-screen-z-index
|
||||
[screen-state]
|
||||
(.screenZIndex ^js floating-screen-worklets screen-state))
|
||||
|
|
Loading…
Reference in New Issue