Shell & Bottom Tabs Migration (#14099)
* Shell & Bottom Tabs Migration * Added accessibility ids for elements in the new UI
This commit is contained in:
parent
38c95804ae
commit
0ff6fb25f4
|
@ -1,4 +1,4 @@
|
||||||
import { useDerivedValue } from 'react-native-reanimated';
|
import { useDerivedValue, withTiming, withSequence, withDelay, Easing } from 'react-native-reanimated';
|
||||||
|
|
||||||
// Generic Worklets
|
// Generic Worklets
|
||||||
|
|
||||||
|
@ -32,38 +32,99 @@ export function applyAnimationsToStyle(animations, style) {
|
||||||
|
|
||||||
// Switcher Worklets
|
// Switcher Worklets
|
||||||
|
|
||||||
export function switcherCloseButtonOpacity (switcherButtonOpacity) {
|
export function stackOpacity (stackId, selectedStackId) {
|
||||||
return useDerivedValue(
|
return useDerivedValue(
|
||||||
function () {
|
function () {
|
||||||
'worklet'
|
'worklet'
|
||||||
return 1 - switcherButtonOpacity.value;
|
return selectedStackId.value == stackId ? 1 : 0;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function switcherScreenRadius (switcherScreenSize) {
|
export function stackPointer (stackId, selectedStackId) {
|
||||||
return useDerivedValue(
|
return useDerivedValue(
|
||||||
function () {
|
function () {
|
||||||
'worklet'
|
'worklet'
|
||||||
return switcherScreenSize.value/2;
|
return selectedStackId.value == stackId ? "auto" : "none";
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function switcherScreenBottomPosition (switcherScreenRadius, switcherPressedRadius, initalPosition) {
|
export function bottomTabIconColor (stackId, selectedStackId, passThrough, selectedTabColor, defaultColor, passThroughColor) {
|
||||||
return useDerivedValue(
|
return useDerivedValue(
|
||||||
function () {
|
function () {
|
||||||
'worklet'
|
'worklet'
|
||||||
return initalPosition + switcherPressedRadius - switcherScreenRadius.value;
|
if (selectedStackId.value == stackId){
|
||||||
|
return selectedTabColor;
|
||||||
|
}
|
||||||
|
else if (passThrough.value){
|
||||||
|
return passThroughColor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return defaultColor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function switcherContainerBottomPosition (switcherScreenBottom, heightOffset) {
|
|
||||||
|
// Home Stack
|
||||||
|
|
||||||
|
const defaultDurationAndEasing = {
|
||||||
|
duration: 300,
|
||||||
|
easing: Easing.bezier(0, 0, 1, 1),
|
||||||
|
}
|
||||||
|
|
||||||
|
export function homeStackOpacity (homeStackOpen) {
|
||||||
return useDerivedValue(
|
return useDerivedValue(
|
||||||
function () {
|
function () {
|
||||||
'worklet'
|
'worklet'
|
||||||
return - (switcherScreenBottom.value + heightOffset);
|
return withTiming(homeStackOpen.value ? 1 : 0, defaultDurationAndEasing);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function homeStackTop (homeStackOpen, top) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
return withTiming(homeStackOpen.value ? 0 : top, defaultDurationAndEasing);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function homeStackLeft (selectedStackId, animateHomeStackLeft, homeStackOpen, left) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
if (animateHomeStackLeft.value) {
|
||||||
|
var leftValue = left[selectedStackId.value];
|
||||||
|
if (homeStackOpen.value) {
|
||||||
|
return withSequence(withTiming(leftValue, {duration: 0}), withTiming(0, defaultDurationAndEasing))
|
||||||
|
} else {
|
||||||
|
return withTiming(leftValue, defaultDurationAndEasing);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function homeStackPointer (homeStackOpen) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
return homeStackOpen.value ? "auto" : "none";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function homeStackScale (homeStackOpen, minimizeScale) {
|
||||||
|
return useDerivedValue(
|
||||||
|
function () {
|
||||||
|
'worklet'
|
||||||
|
return withTiming(homeStackOpen.value ? 1 : minimizeScale, defaultDurationAndEasing);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
{:keyboardVerticalOffset (+ 44 (:status-bar-height @navigation-const))})]
|
{:keyboardVerticalOffset (+ 44 (:status-bar-height @navigation-const))})]
|
||||||
(reagent/children this))))
|
(reagent/children this))))
|
||||||
|
|
||||||
|
(def status-bar (.-StatusBar ^js rn))
|
||||||
|
|
||||||
(def keyboard (.-Keyboard ^js rn))
|
(def keyboard (.-Keyboard ^js rn))
|
||||||
|
|
||||||
(def dismiss-keyboard! #(.dismiss ^js keyboard))
|
(def dismiss-keyboard! #(.dismiss ^js keyboard))
|
||||||
|
|
|
@ -62,9 +62,10 @@
|
||||||
(let [pressed? (reagent/atom false)]
|
(let [pressed? (reagent/atom false)]
|
||||||
(fn [{:keys [type on-press count customization-color style]}]
|
(fn [{:keys [type on-press count customization-color style]}]
|
||||||
[rn/touchable-without-feedback
|
[rn/touchable-without-feedback
|
||||||
{:on-press-in #(reset! pressed? true)
|
{:on-press-in #(reset! pressed? true)
|
||||||
:on-press-out #(reset! pressed? false)
|
:on-press-out #(reset! pressed? false)
|
||||||
:on-press on-press}
|
:on-press on-press
|
||||||
|
:accessibility-label type}
|
||||||
[rn/view {:style (merge
|
[rn/view {:style (merge
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:height 24
|
:height 24
|
||||||
|
|
|
@ -1,71 +1,77 @@
|
||||||
(ns quo2.components.navigation.bottom-nav-tab
|
(ns quo2.components.navigation.bottom-nav-tab
|
||||||
(:require [quo.react-native :as rn]
|
(:require [quo.react-native :as rn]
|
||||||
[reagent.core :as reagent]
|
[quo2.reanimated :as reanimated]
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.colors :as colors]
|
||||||
[quo2.components.icon :as icon]
|
[quo2.components.icons.icons :as icons]
|
||||||
[quo2.components.counter.counter :as counter]))
|
[quo2.components.counter.counter :as counter]))
|
||||||
|
|
||||||
(defn toggle-background-color [background-color press-out? pass-through?]
|
(defn toggle-background-color [background-color press-out? pass-through?]
|
||||||
(let [color (cond
|
(reanimated/set-shared-value
|
||||||
press-out? nil
|
background-color
|
||||||
pass-through? colors/white-opa-5
|
(cond
|
||||||
:else colors/neutral-70)]
|
press-out? "transparent"
|
||||||
(reset! background-color color)))
|
pass-through? colors/white-opa-5
|
||||||
|
:else colors/neutral-70)))
|
||||||
|
|
||||||
(defn bottom-nav-tab
|
(defn bottom-nav-tab
|
||||||
"[bottom-nav-tab opts]
|
"[bottom-nav-tab opts]
|
||||||
opts
|
opts
|
||||||
{:icon :main-icons2/communities
|
{:icon :main-icons2/communities
|
||||||
:selected? true/false
|
|
||||||
:new-notifications? true/false
|
:new-notifications? true/false
|
||||||
:notification-indicator :unread-dot/:counter
|
:notification-indicator :unread-dot/:counter
|
||||||
:counter-label number
|
:counter-label number
|
||||||
:on-press bottom-tab on-press function
|
:on-press bottom-tab on-press function
|
||||||
:pass-through? true/false
|
:pass-through? true/false
|
||||||
|
:icon-color-anim reanimated shared value
|
||||||
"
|
"
|
||||||
[_]
|
[{:keys [icon new-notifications? notification-indicator counter-label
|
||||||
(let [background-color (reagent/atom nil)]
|
on-press pass-through? icon-color-anim accessibility-label]}]
|
||||||
(fn [{:keys [icon selected? new-notifications? notification-indicator counter-label on-press pass-through?]}]
|
[:f>
|
||||||
[rn/touchable-without-feedback
|
(fn []
|
||||||
{:on-press on-press
|
(let [icon-animated-style (reanimated/apply-animations-to-style
|
||||||
:on-press-in #(toggle-background-color background-color false pass-through?)
|
{:tint-color icon-color-anim}
|
||||||
:on-press-out #(toggle-background-color background-color true pass-through?)}
|
{:width 24
|
||||||
[rn/view {:style {:width 90
|
:height 24})
|
||||||
:height 40
|
background-color (reanimated/use-shared-value "transparent")
|
||||||
:background-color @background-color
|
background-animated-style (reanimated/apply-animations-to-style
|
||||||
:border-radius 10}}
|
{:background-color background-color}
|
||||||
[rn/hole-view {:style {:padding-left 33
|
{:width 90
|
||||||
:padding-top 8}
|
:height 40
|
||||||
:key new-notifications? ;; Key is required to force removal of holes
|
:border-radius 10})]
|
||||||
:holes (cond
|
[rn/touchable-without-feedback
|
||||||
(not new-notifications?) ;; No new notifications, remove holes
|
{:on-press on-press
|
||||||
[]
|
:on-press-in #(toggle-background-color background-color false pass-through?)
|
||||||
|
:on-press-out #(toggle-background-color background-color true pass-through?)
|
||||||
|
:accessibility-label accessibility-label}
|
||||||
|
[reanimated/view {:style background-animated-style}
|
||||||
|
[rn/hole-view {:style {:padding-left 33
|
||||||
|
:padding-top 8}
|
||||||
|
:key new-notifications? ;; Key is required to force removal of holes
|
||||||
|
:holes (cond
|
||||||
|
(not new-notifications?) ;; No new notifications, remove holes
|
||||||
|
[]
|
||||||
|
|
||||||
(= notification-indicator :unread-dot)
|
(= notification-indicator :unread-dot)
|
||||||
[{:x 50 :y 5 :width 10 :height 10 :borderRadius 5}]
|
[{:x 50 :y 5 :width 10 :height 10 :borderRadius 5}]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
[{:x 47 :y 1 :width 18 :height 18 :borderRadius 7}])}
|
[{:x 47 :y 1 :width 18 :height 18 :borderRadius 7}])}
|
||||||
[icon/icon
|
[reanimated/image
|
||||||
icon
|
{:style icon-animated-style
|
||||||
{:size 24
|
:source (icons/icon-source (keyword (str icon 24)))}]]
|
||||||
:color (cond
|
(when new-notifications?
|
||||||
selected? colors/white
|
(if (= notification-indicator :counter)
|
||||||
pass-through? colors/white-opa-40
|
[counter/counter {:outline false
|
||||||
:else colors/neutral-50)}]]
|
:override-text-color colors/white
|
||||||
(when new-notifications?
|
:override-bg-color colors/primary-50
|
||||||
(if (= notification-indicator :counter)
|
:style {:position :absolute
|
||||||
[counter/counter {:outline false
|
:left 48
|
||||||
:override-text-color colors/white
|
:top 2}}
|
||||||
:override-bg-color colors/primary-50
|
counter-label]
|
||||||
:style {:position :absolute
|
[rn/view {:style {:width 8
|
||||||
:left 48
|
:height 8
|
||||||
:top 2}}
|
:border-radius 4
|
||||||
counter-label]
|
:top 6
|
||||||
[rn/view {:style {:width 8
|
:left 51
|
||||||
:height 8
|
:position :absolute
|
||||||
:border-radius 4
|
:background-color colors/primary-50}}]))]]))])
|
||||||
:top 6
|
|
||||||
:left 51
|
|
||||||
:position :absolute
|
|
||||||
:background-color colors/primary-50}}]))]])))
|
|
||||||
|
|
|
@ -44,8 +44,7 @@
|
||||||
open-scanner show-qr open-activity-center style avatar counter-label]}]
|
open-scanner show-qr open-activity-center style avatar counter-label]}]
|
||||||
(let [button-common-props (get-button-common-props type)]
|
(let [button-common-props (get-button-common-props type)]
|
||||||
[rn/view {:style (merge
|
[rn/view {:style (merge
|
||||||
{:height 56
|
{:height 56}
|
||||||
:flex 1}
|
|
||||||
style)}
|
style)}
|
||||||
;; Left Section
|
;; Left Section
|
||||||
[rn/touchable-without-feedback {:on-press open-profile}
|
[rn/touchable-without-feedback {:on-press open-profile}
|
||||||
|
|
|
@ -16,14 +16,16 @@
|
||||||
(defn open-reactions-menu
|
(defn open-reactions-menu
|
||||||
[{:keys [on-press]}]
|
[{:keys [on-press]}]
|
||||||
(let [dark? (theme/dark?)]
|
(let [dark? (theme/dark?)]
|
||||||
[rn/touchable-opacity {:on-press on-press
|
[rn/touchable-opacity
|
||||||
:style (merge reaction-styling
|
{:on-press on-press
|
||||||
|
:accessibility-label :emoji-reaction-add
|
||||||
|
:style (merge reaction-styling
|
||||||
{:padding-horizontal 9
|
{:padding-horizontal 9
|
||||||
:border-width 1
|
:border-width 1
|
||||||
:margin-top 5
|
:margin-top 5
|
||||||
:border-color (if dark?
|
:border-color (if dark?
|
||||||
colors/neutral-70
|
colors/neutral-70
|
||||||
colors/neutral-30)})}
|
colors/neutral-30)})}
|
||||||
[icons/icon :main-icons2/add
|
[icons/icon :main-icons2/add
|
||||||
{:size 20
|
{:size 20
|
||||||
:color (if dark?
|
:color (if dark?
|
||||||
|
@ -32,26 +34,30 @@
|
||||||
|
|
||||||
(defn reaction
|
(defn reaction
|
||||||
"Add your emoji as a param here"
|
"Add your emoji as a param here"
|
||||||
[{:keys [emoji clicks neutral? on-press]}]
|
[{:keys [emoji clicks neutral? on-press accessibility-label]}]
|
||||||
(let [dark? (theme/dark?)
|
(let [dark? (theme/dark?)
|
||||||
text-color (if dark? colors/white
|
text-color (if dark? colors/white
|
||||||
colors/neutral-100)
|
colors/neutral-100)
|
||||||
numeric-value (int clicks)
|
numeric-value (int clicks)
|
||||||
clicks-positive? (pos? numeric-value)]
|
clicks-positive? (pos? numeric-value)]
|
||||||
[rn/touchable-opacity {:on-press on-press
|
[rn/touchable-opacity
|
||||||
:style (merge reaction-styling
|
{:on-press on-press
|
||||||
(cond-> {:background-color
|
:accessibility-label accessibility-label
|
||||||
(if dark?
|
:style (merge reaction-styling
|
||||||
(if neutral?
|
(cond-> {:background-color
|
||||||
colors/neutral-70
|
(if dark?
|
||||||
:transparent)
|
(if neutral?
|
||||||
(if neutral?
|
colors/neutral-70
|
||||||
colors/neutral-30
|
:transparent)
|
||||||
:transparent))}
|
(if neutral?
|
||||||
(and dark? (not neutral?)) (assoc :border-color colors/neutral-70
|
colors/neutral-30
|
||||||
:border-width 1)
|
:transparent))}
|
||||||
(and (not dark?) (not neutral?)) (assoc :border-color colors/neutral-30
|
(and dark? (not neutral?))
|
||||||
:border-width 1)))}
|
(assoc :border-color colors/neutral-70
|
||||||
|
:border-width 1)
|
||||||
|
(and (not dark?) (not neutral?))
|
||||||
|
(assoc :border-color colors/neutral-30
|
||||||
|
:border-width 1)))}
|
||||||
[icons/icon emoji {:no-color true
|
[icons/icon emoji {:no-color true
|
||||||
:size 16}]
|
:size 16}]
|
||||||
[quo2.text/text {:size :paragraph-2
|
[quo2.text/text {:size :paragraph-2
|
||||||
|
|
|
@ -45,7 +45,6 @@
|
||||||
;;Blur
|
;;Blur
|
||||||
(def neutral-5-opa-70 (alpha neutral-5 0.7))
|
(def neutral-5-opa-70 (alpha neutral-5 0.7))
|
||||||
(def neutral-90-opa-70 (alpha neutral-90 0.7))
|
(def neutral-90-opa-70 (alpha neutral-90 0.7))
|
||||||
(def neutral-95-opa-70 (alpha neutral-95 0.7))
|
|
||||||
|
|
||||||
;;80 with transparency
|
;;80 with transparency
|
||||||
(def neutral-80-opa-5 (alpha neutral-80 0.05))
|
(def neutral-80-opa-5 (alpha neutral-80 0.05))
|
||||||
|
@ -60,6 +59,20 @@
|
||||||
(def neutral-80-opa-90 (alpha neutral-80 0.9))
|
(def neutral-80-opa-90 (alpha neutral-80 0.9))
|
||||||
(def neutral-80-opa-95 (alpha neutral-80 0.95))
|
(def neutral-80-opa-95 (alpha neutral-80 0.95))
|
||||||
|
|
||||||
|
;;95 with transparency
|
||||||
|
(def neutral-95-opa-60 (alpha neutral-95 0.6))
|
||||||
|
(def neutral-95-opa-70 (alpha neutral-95 0.7))
|
||||||
|
(def neutral-95-opa-80 (alpha neutral-95 0.8))
|
||||||
|
(def neutral-95-opa-90 (alpha neutral-95 0.9))
|
||||||
|
(def neutral-95-opa-95 (alpha neutral-95 0.95))
|
||||||
|
|
||||||
|
;;100 with transparency
|
||||||
|
(def neutral-100-opa-60 (alpha neutral-100 0.6))
|
||||||
|
(def neutral-100-opa-70 (alpha neutral-100 0.7))
|
||||||
|
(def neutral-100-opa-80 (alpha neutral-100 0.8))
|
||||||
|
(def neutral-100-opa-90 (alpha neutral-100 0.9))
|
||||||
|
(def neutral-100-opa-95 (alpha neutral-100 0.95))
|
||||||
|
|
||||||
;;;;White
|
;;;;White
|
||||||
|
|
||||||
;;Solid
|
;;Solid
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
(:require [quo.react-native :as rn]
|
(:require [quo.react-native :as rn]
|
||||||
[quo.previews.preview :as preview]
|
[quo.previews.preview :as preview]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
[quo2.reanimated :as reanimated]
|
||||||
[quo2.components.navigation.bottom-nav-tab :as quo2]
|
[quo2.components.navigation.bottom-nav-tab :as quo2]
|
||||||
[quo2.foundations.colors :as colors]))
|
[quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
@ -36,21 +37,34 @@
|
||||||
:key :counter-label
|
:key :counter-label
|
||||||
:type :text}])
|
:type :text}])
|
||||||
|
|
||||||
|
(defn get-icon-color [selected? pass-through?]
|
||||||
|
(cond
|
||||||
|
selected? colors/white
|
||||||
|
pass-through? colors/white-opa-40
|
||||||
|
:else colors/neutral-50))
|
||||||
|
|
||||||
(defn cool-preview []
|
(defn cool-preview []
|
||||||
(let [state (reagent/atom {:icon :main-icons2/communities
|
(let [state (reagent/atom {:icon :main-icons2/communities
|
||||||
:selected? true
|
:new-notifications? true
|
||||||
:pass-through? true
|
:notification-indicator :counter
|
||||||
:new-notifications? true
|
:counter-label 8
|
||||||
:notification-indicator :counter
|
:preview-label-color colors/white})
|
||||||
:counter-label 8
|
selected? (reagent/cursor state [:selected?])
|
||||||
:preview-label-color colors/white})]
|
pass-through? (reagent/cursor state [:pass-through?])]
|
||||||
(fn []
|
[:f>
|
||||||
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
(fn []
|
||||||
[rn/view {:padding-bottom 150}
|
(let [icon-color-anim (reanimated/use-shared-value colors/white)]
|
||||||
[preview/customizer state descriptor]
|
(reanimated/set-shared-value
|
||||||
[rn/view {:padding-vertical 60
|
icon-color-anim
|
||||||
:align-items :center}
|
(get-icon-color @selected? @pass-through?))
|
||||||
[quo2/bottom-nav-tab @state (:value @state)]]]])))
|
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
|
||||||
|
[rn/view {:padding-bottom 150}
|
||||||
|
[preview/customizer state descriptor]
|
||||||
|
[rn/view {:padding-vertical 60
|
||||||
|
:align-items :center}
|
||||||
|
[quo2/bottom-nav-tab
|
||||||
|
(merge @state {:icon-color-anim icon-color-anim})
|
||||||
|
(:value @state)]]]]))]))
|
||||||
|
|
||||||
(defn preview-bottom-nav-tab []
|
(defn preview-bottom-nav-tab []
|
||||||
[rn/view {:background-color colors/neutral-100
|
[rn/view {:background-color colors/neutral-100
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
[status-im.utils.logging.core :as utils.logs]
|
[status-im.utils.logging.core :as utils.logs]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.utils.snoopy :as snoopy]
|
[status-im.utils.snoopy :as snoopy]
|
||||||
|
[status-im.switcher.animation :as animation]
|
||||||
|
[status-im.async-storage.core :as async-storage]
|
||||||
[status-im.utils.universal-links.core :as utils.universal-links]))
|
[status-im.utils.universal-links.core :as utils.universal-links]))
|
||||||
|
|
||||||
(set! interop/next-tick js/setTimeout)
|
(set! interop/next-tick js/setTimeout)
|
||||||
|
@ -39,6 +41,9 @@
|
||||||
|
|
||||||
(utils.universal-links/initialize)
|
(utils.universal-links/initialize)
|
||||||
|
|
||||||
|
;; TODO(parvesh) - Remove while moving functionality to status-go
|
||||||
|
(async-storage/get-item :selected-stack-id #(animation/selected-stack-id-loaded %))
|
||||||
|
|
||||||
;;DEV
|
;;DEV
|
||||||
(snoopy/subscribe!)
|
(snoopy/subscribe!)
|
||||||
(when (and js/goog.DEBUG platform/ios? DevSettings)
|
(when (and js/goog.DEBUG platform/ios? DevSettings)
|
||||||
|
|
|
@ -468,7 +468,7 @@
|
||||||
"Decides which root should be initialised depending on user and app state"
|
"Decides which root should be initialised depending on user and app state"
|
||||||
[db]
|
[db]
|
||||||
(if (get db :tos/accepted?)
|
(if (get db :tos/accepted?)
|
||||||
(re-frame/dispatch [:init-root (if config/new-ui-enabled? :home-stack :chat-stack)])
|
(re-frame/dispatch [:init-root (if config/new-ui-enabled? :shell-stack :chat-stack)])
|
||||||
(re-frame/dispatch [:init-root :tos])))
|
(re-frame/dispatch [:init-root :tos])))
|
||||||
|
|
||||||
(fx/defn login-only-events
|
(fx/defn login-only-events
|
||||||
|
@ -517,7 +517,7 @@
|
||||||
(logging/set-log-level (:log-level multiaccount))
|
(logging/set-log-level (:log-level multiaccount))
|
||||||
|
|
||||||
(if config/new-ui-enabled?
|
(if config/new-ui-enabled?
|
||||||
(navigation/init-root :home-stack)
|
(navigation/init-root :shell-stack)
|
||||||
;; if it's a first account, the ToS will be accepted at welcome carousel
|
;; if it's a first account, the ToS will be accepted at welcome carousel
|
||||||
;; if not a first account, the ToS might have been accepted by other account logins
|
;; if not a first account, the ToS might have been accepted by other account logins
|
||||||
(if (or first-account? tos-accepted?)
|
(if (or first-account? tos-accepted?)
|
||||||
|
|
|
@ -3,14 +3,14 @@
|
||||||
[status-im.reloader :as reloader]
|
[status-im.reloader :as reloader]
|
||||||
[status-im.utils.datetime :as datetime]))
|
[status-im.utils.datetime :as datetime]))
|
||||||
|
|
||||||
(def parent-stack (atom :home-stack))
|
(def parent-stack (atom :shell-stack))
|
||||||
|
|
||||||
(fx/defn reload-new-ui
|
(fx/defn reload-new-ui
|
||||||
{:events [:reload-new-ui]}
|
{:events [:reload-new-ui]}
|
||||||
[_]
|
[_]
|
||||||
(reloader/reload)
|
(reloader/reload)
|
||||||
{:new-ui/reset-bottom-tabs nil
|
{:new-ui/reset-bottom-tabs nil
|
||||||
:dispatch [:init-root :home-stack]})
|
:dispatch [:init-root :shell-stack]})
|
||||||
|
|
||||||
(fx/defn init-root-nav2
|
(fx/defn init-root-nav2
|
||||||
{:events [:init-root-nav2]}
|
{:events [:init-root-nav2]}
|
||||||
|
@ -27,7 +27,7 @@
|
||||||
[_ modal]
|
[_ modal]
|
||||||
{:close-modal-fx-nav2 modal})
|
{:close-modal-fx-nav2 modal})
|
||||||
|
|
||||||
(defn navigate-from-home-stack [go-to-view-id id db]
|
(defn navigate-from-shell-stack [go-to-view-id id db]
|
||||||
(reset! parent-stack go-to-view-id)
|
(reset! parent-stack go-to-view-id)
|
||||||
{:navigate-to-fx-nav2 [go-to-view-id id]
|
{:navigate-to-fx-nav2 [go-to-view-id id]
|
||||||
:db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id
|
:db (assoc-in db [:navigation2/navigation2-stacks id] {:type go-to-view-id
|
||||||
|
@ -49,8 +49,12 @@
|
||||||
(if from-switcher?
|
(if from-switcher?
|
||||||
(navigate-from-switcher go-to-view-id id db from-home?)
|
(navigate-from-switcher go-to-view-id id db from-home?)
|
||||||
(if from-home?
|
(if from-home?
|
||||||
(navigate-from-home-stack go-to-view-id id db)
|
(navigate-from-shell-stack go-to-view-id id db)
|
||||||
;; TODO(parvesh) - new stacks created from other screens should be stacked on current stack, instead of creating new entry
|
;; TODO(parvesh) - new stacks created from other screens should be stacked on current stack, instead of creating new entry
|
||||||
(navigate-from-home-stack go-to-view-id id db)))))
|
(navigate-from-shell-stack go-to-view-id id db)))))
|
||||||
|
|
||||||
|
(fx/defn change-root-status-bar-style
|
||||||
|
{:events [:change-root-status-bar-style]}
|
||||||
|
[_ style]
|
||||||
|
{:change-root-status-bar-style-fx style})
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,10 @@
|
||||||
:wallet 2
|
:wallet 2
|
||||||
:browser 3})
|
:browser 3})
|
||||||
|
|
||||||
;; (defonce set-navigation-default-options
|
(defn change-root-status-bar-style [style]
|
||||||
;; (.setDefaultOptions Navigation (clj->js {:options {:topBar {:visible false}}})))
|
(.mergeOptions Navigation
|
||||||
|
"shell-stack"
|
||||||
|
(clj->js {:statusBar {:style style}})))
|
||||||
|
|
||||||
;; TODO (parvesh) - improve open-modal and close-modal
|
;; TODO (parvesh) - improve open-modal and close-modal
|
||||||
(defn open-modal [comp]
|
(defn open-modal [comp]
|
||||||
|
@ -55,7 +57,7 @@
|
||||||
(let [{:keys [options]} (get views/screens comp)]
|
(let [{:keys [options]} (get views/screens comp)]
|
||||||
(reset! nav2-utils/container-stack-view-id comp)
|
(reset! nav2-utils/container-stack-view-id comp)
|
||||||
(.push Navigation
|
(.push Navigation
|
||||||
(name :home-stack)
|
"shell-stack"
|
||||||
(clj->js {:stack {:id comp
|
(clj->js {:stack {:id comp
|
||||||
:children [{:component {:id comp
|
:children [{:component {:id comp
|
||||||
:name comp
|
:name comp
|
||||||
|
@ -79,3 +81,5 @@
|
||||||
(re-frame/reg-fx :navigate-to-fx-nav2 navigate)
|
(re-frame/reg-fx :navigate-to-fx-nav2 navigate)
|
||||||
|
|
||||||
(re-frame/reg-fx :navigate-from-switcher-fx navigate-from-switcher)
|
(re-frame/reg-fx :navigate-from-switcher-fx navigate-from-switcher)
|
||||||
|
|
||||||
|
(re-frame/reg-fx :change-root-status-bar-style-fx change-root-status-bar-style)
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
(ns status-im.navigation2.roots
|
(ns status-im.navigation2.roots
|
||||||
(:require [quo.theme :as theme]
|
(:require [quo2.foundations.colors :as colors]
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
(defn status-bar-options []
|
(defn status-bar-options []
|
||||||
(if platform/android?
|
(if platform/android?
|
||||||
{:navigationBar {:backgroundColor colors/neutral-80}
|
{:navigationBar {:backgroundColor colors/neutral-100}
|
||||||
:statusBar {:backgroundColor :transparent
|
:statusBar {:backgroundColor :transparent
|
||||||
:style (if (theme/dark?) :light :dark)
|
:style :light
|
||||||
:drawBehind true}}
|
:drawBehind true}}
|
||||||
{:statusBar {:style (if (theme/dark?) :light :dark)}}))
|
{:statusBar {:style :light}}))
|
||||||
|
|
||||||
(defn roots []
|
(defn roots []
|
||||||
{:home-stack
|
{:shell-stack
|
||||||
{:root
|
{:root
|
||||||
{:stack {:id :home-stack
|
{:stack {:id :shell-stack
|
||||||
:children [{:component {:name :chat-stack
|
:children [{:component {:name :chat-stack
|
||||||
:id :chat-stack
|
:id :chat-stack
|
||||||
:options (merge (status-bar-options)
|
:options (merge (status-bar-options)
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
(ns status-im.navigation2.screens
|
(ns status-im.navigation2.screens
|
||||||
(:require [status-im.ui2.screens.chat.view :as chat]
|
(:require [status-im.ui2.screens.chat.view :as chat]
|
||||||
[status-im.switcher.home-stack :as home-stack]
|
[status-im.switcher.shell-stack :as shell-stack]))
|
||||||
[status-im.navigation2.stack-with-switcher :as stack-with-switcher]))
|
|
||||||
|
|
||||||
;; We have to use the home screen name :chat-stack for now, for compatibility with navigation.cljs
|
;; We have to use the home screen name :chat-stack for now, for compatibility with navigation.cljs
|
||||||
(def screens [{:name :chat-stack ;; TODO(parvesh) - rename to home-stack
|
(def screens [{:name :chat-stack ;; TODO(parvesh) - rename to shell-stack
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component home-stack/home}])
|
:component shell-stack/shell-stack}])
|
||||||
|
|
||||||
;; These screens will overwrite navigation/screens.cljs screens on enabling new UI toggle
|
;; These screens will overwrite navigation/screens.cljs screens on enabling new UI toggle
|
||||||
(def screen-overwrites
|
(def screen-overwrites
|
||||||
[{:name :chat
|
[{:name :chat
|
||||||
:options {:topBar {:visible false}}
|
:options {:topBar {:visible false}}
|
||||||
:component #(stack-with-switcher/overlap-stack chat/chat :chat)}])
|
:component chat/chat}])
|
||||||
|
|
|
@ -1,10 +0,0 @@
|
||||||
(ns status-im.navigation2.stack-with-switcher
|
|
||||||
(:require [quo.react-native :as rn]
|
|
||||||
[status-im.utils.platform :as platform]
|
|
||||||
[status-im.switcher.switcher :as switcher]))
|
|
||||||
|
|
||||||
(defn overlap-stack [comp view-id]
|
|
||||||
[rn/view {:style {:flex 1
|
|
||||||
:margin-bottom (if platform/ios? 30 0)}}
|
|
||||||
[comp]
|
|
||||||
[switcher/switcher view-id]])
|
|
|
@ -1,65 +1,108 @@
|
||||||
(ns status-im.switcher.animation
|
(ns status-im.switcher.animation
|
||||||
(:require [quo2.reanimated :as reanimated]
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[quo2.reanimated :as reanimated]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[status-im.async-storage.core :as async-storage]
|
||||||
[status-im.switcher.constants :as constants]))
|
[status-im.switcher.constants :as constants]))
|
||||||
|
|
||||||
;;;; Switcher Animations
|
|
||||||
|
|
||||||
;; Component Animations
|
|
||||||
(defn switcher-touchable-on-press-in
|
|
||||||
[touchable-scale]
|
|
||||||
(reanimated/animate-shared-value-with-timing touchable-scale constants/switcher-pressed-scale 300 :easing1))
|
|
||||||
|
|
||||||
(defn switcher-touchable-on-press-out [switcher-opened? view-id shared-values]
|
|
||||||
(let [{:keys [width height]} (constants/dimensions)
|
|
||||||
switcher-bottom-position (constants/switcher-pressed-bottom-position view-id)
|
|
||||||
switcher-target-radius (Math/hypot
|
|
||||||
(/ width 2)
|
|
||||||
(- height constants/switcher-pressed-radius switcher-bottom-position))
|
|
||||||
switcher-size (* 2 switcher-target-radius)]
|
|
||||||
(reanimated/animate-shared-value-with-timing (:button-touchable-scale shared-values) 1 300 :easing1)
|
|
||||||
(if @switcher-opened?
|
|
||||||
(do
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-button-opacity shared-values) 1 300 :easing1)
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-screen-size shared-values) constants/switcher-pressed-size 300 :linear)
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-container-scale shared-values) 0.9 300 :linear))
|
|
||||||
(do
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-button-opacity shared-values) 0 300 :easing1)
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-screen-size shared-values) switcher-size 300 :linear)
|
|
||||||
(reanimated/animate-shared-value-with-timing (:switcher-container-scale shared-values) 1 300 :linear)))
|
|
||||||
(swap! switcher-opened? not)))
|
|
||||||
|
|
||||||
;; Derived Values
|
|
||||||
|
|
||||||
(defn switcher-close-button-opacity [switcher-button-opacity]
|
|
||||||
(.switcherCloseButtonOpacity ^js reanimated/worklet-factory switcher-button-opacity))
|
|
||||||
|
|
||||||
(defn switcher-screen-radius [switcher-screen-size]
|
|
||||||
(.switcherScreenRadius ^js reanimated/worklet-factory switcher-screen-size))
|
|
||||||
|
|
||||||
(defn switcher-screen-bottom-position [switcher-screen-radius view-id]
|
|
||||||
(.switcherScreenBottomPosition ^js reanimated/worklet-factory
|
|
||||||
switcher-screen-radius
|
|
||||||
constants/switcher-pressed-radius
|
|
||||||
(constants/switcher-pressed-bottom-position view-id)))
|
|
||||||
|
|
||||||
(defn switcher-container-bottom-position [switcher-screen-bottom]
|
|
||||||
(.switcherContainerBottomPosition ^js reanimated/worklet-factory
|
|
||||||
switcher-screen-bottom
|
|
||||||
(+ constants/switcher-container-height-padding
|
|
||||||
constants/switcher-height-offset)))
|
|
||||||
|
|
||||||
|
|
||||||
;;;; Bottom Tabs & Home Stack Animations
|
;;;; Bottom Tabs & Home Stack Animations
|
||||||
|
|
||||||
|
(def selected-stack-id (atom nil))
|
||||||
|
(def home-stack-open? (atom false))
|
||||||
|
(def pass-through? (atom false))
|
||||||
|
|
||||||
|
(def bottom-nav-tab-width 90)
|
||||||
|
|
||||||
|
(defn selected-stack-id-loaded [stack-id]
|
||||||
|
(reset! selected-stack-id stack-id)
|
||||||
|
(reset! home-stack-open? (some? stack-id)))
|
||||||
|
|
||||||
|
(defn calculate-home-stack-position []
|
||||||
|
(let [{:keys [width height]} (constants/dimensions)
|
||||||
|
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 (constants/bottom-tabs-container-height)))]
|
||||||
|
{:left (reduce
|
||||||
|
(fn [acc stack-id]
|
||||||
|
(assoc acc stack-id (+ (- left-margin left-empty-space)
|
||||||
|
(* (.indexOf constants/stacks-ids stack-id)
|
||||||
|
bottom-nav-tab-width))))
|
||||||
|
{:none 0} constants/stacks-ids)
|
||||||
|
:top (+ top-empty-space (constants/bottom-tabs-container-height))
|
||||||
|
:scale minimize-scale}))
|
||||||
|
|
||||||
|
(defn get-shared-values []
|
||||||
|
(let [selected-stack-id-sv (reanimated/use-shared-value
|
||||||
|
;; passing keywords or nil is not working with reanimated
|
||||||
|
(name (if @selected-stack-id @selected-stack-id :none)))
|
||||||
|
;; Second shared value of selected-stack-id required to make sure stack is still visible while minimizing
|
||||||
|
selected-stack-id-sv2 (reanimated/use-shared-value
|
||||||
|
(name (if @selected-stack-id @selected-stack-id :none)))
|
||||||
|
pass-through-sv (reanimated/use-shared-value @pass-through?)
|
||||||
|
home-stack-open-sv (reanimated/use-shared-value @home-stack-open?)
|
||||||
|
animate-home-stack-left (reanimated/use-shared-value (not @home-stack-open?))
|
||||||
|
home-stack-position (calculate-home-stack-position)]
|
||||||
|
(reduce
|
||||||
|
(fn [acc id]
|
||||||
|
(let [tabs-icon-color-keyword (get constants/tabs-icon-color-keywords id)
|
||||||
|
stack-opacity-keyword (get constants/stacks-opacity-keywords id)
|
||||||
|
stack-pointer-keyword (get constants/stacks-pointer-keywords id)]
|
||||||
|
(assoc
|
||||||
|
acc
|
||||||
|
stack-opacity-keyword (.stackOpacity
|
||||||
|
^js reanimated/worklet-factory
|
||||||
|
(name id) selected-stack-id-sv2)
|
||||||
|
stack-pointer-keyword (.stackPointer
|
||||||
|
^js reanimated/worklet-factory
|
||||||
|
(name id) selected-stack-id-sv2)
|
||||||
|
tabs-icon-color-keyword (.bottomTabIconColor
|
||||||
|
^js reanimated/worklet-factory
|
||||||
|
(name id) selected-stack-id-sv pass-through-sv
|
||||||
|
colors/white colors/neutral-50 colors/white-opa-40))))
|
||||||
|
{:selected-stack-id selected-stack-id-sv
|
||||||
|
:selected-stack-id2 selected-stack-id-sv2
|
||||||
|
:pass-through? pass-through-sv
|
||||||
|
:home-stack-open? home-stack-open-sv
|
||||||
|
:animate-home-stack-left animate-home-stack-left
|
||||||
|
:home-stack-left (.homeStackLeft
|
||||||
|
^js reanimated/worklet-factory
|
||||||
|
selected-stack-id-sv2 animate-home-stack-left home-stack-open-sv
|
||||||
|
(clj->js (:left home-stack-position)))
|
||||||
|
:home-stack-top (.homeStackTop
|
||||||
|
^js reanimated/worklet-factory
|
||||||
|
home-stack-open-sv (:top home-stack-position))
|
||||||
|
:home-stack-opacity (.homeStackOpacity
|
||||||
|
^js reanimated/worklet-factory home-stack-open-sv)
|
||||||
|
:home-stack-pointer (.homeStackPointer
|
||||||
|
^js reanimated/worklet-factory home-stack-open-sv)
|
||||||
|
:home-stack-scale (.homeStackScale
|
||||||
|
^js reanimated/worklet-factory home-stack-open-sv
|
||||||
|
(:scale home-stack-position))}
|
||||||
|
constants/stacks-ids)))
|
||||||
|
|
||||||
|
;; Animation
|
||||||
|
|
||||||
|
(defn change-tab [shared-values stack-id]
|
||||||
|
(when-not (colors/dark?)
|
||||||
|
(js/setTimeout #(re-frame/dispatch [:change-root-status-bar-style :dark]) 300))
|
||||||
|
(if @home-stack-open?
|
||||||
|
(reanimated/set-shared-value (:animate-home-stack-left shared-values) false)
|
||||||
|
(reset! home-stack-open? true))
|
||||||
|
(reset! selected-stack-id stack-id)
|
||||||
|
(reanimated/set-shared-value (:selected-stack-id2 shared-values) (name stack-id))
|
||||||
|
(reanimated/set-shared-value (:selected-stack-id shared-values) (name stack-id))
|
||||||
|
(reanimated/set-shared-value (:home-stack-open? shared-values) true)
|
||||||
|
(async-storage/set-item! :selected-stack-id stack-id))
|
||||||
|
|
||||||
|
(defn close-home-stack [shared-values]
|
||||||
|
(re-frame/dispatch [:change-root-status-bar-style :light])
|
||||||
|
(reanimated/set-shared-value (:animate-home-stack-left shared-values) true)
|
||||||
|
(reset! home-stack-open? false)
|
||||||
|
(reset! selected-stack-id nil)
|
||||||
|
(reanimated/set-shared-value (:home-stack-open? shared-values) false)
|
||||||
|
(reanimated/set-shared-value (:selected-stack-id shared-values) "none")
|
||||||
|
(async-storage/set-item! :selected-stack-id nil))
|
||||||
|
|
||||||
(defn bottom-tab-on-press [shared-values selected-stack-id]
|
|
||||||
(doseq [id constants/stacks-ids]
|
|
||||||
(let [selected-tab? (= id selected-stack-id)
|
|
||||||
tab-opacity-shared-value (get shared-values (get constants/tabs-opacity-keywords id))
|
|
||||||
stack-opacity-shared-value (get shared-values (get constants/stacks-opacity-keywords id))
|
|
||||||
stack-pointer-shared-value (get shared-values (get constants/stacks-pointer-keywords id))]
|
|
||||||
(reanimated/animate-shared-value-with-timing tab-opacity-shared-value (if selected-tab? 1 0) 300 :easing3)
|
|
||||||
(reanimated/set-shared-value stack-pointer-shared-value (if selected-tab? "auto" "none"))
|
|
||||||
(if selected-tab?
|
|
||||||
(reanimated/animate-shared-value-with-delay stack-opacity-shared-value 1 300 :easing3 150)
|
|
||||||
(reanimated/animate-shared-value-with-timing stack-opacity-shared-value 0 300 :easing3)))))
|
|
||||||
|
|
|
@ -2,66 +2,58 @@
|
||||||
(:require [quo.react-native :as rn]
|
(:require [quo.react-native :as rn]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[quo2.reanimated :as reanimated]
|
|
||||||
[status-im.switcher.styles :as styles]
|
[status-im.switcher.styles :as styles]
|
||||||
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.switcher.constants :as constants]
|
[status-im.switcher.constants :as constants]
|
||||||
[status-im.switcher.animation :as animation]
|
[status-im.switcher.animation :as animation]
|
||||||
[quo2.components.icon :as icons]))
|
[quo2.components.navigation.bottom-nav-tab :as bottom-nav-tab]))
|
||||||
|
|
||||||
(def selected-stack-id (atom :communities-stack))
|
|
||||||
|
|
||||||
;; Reagent atoms used for lazily loading home screen tabs
|
;; Reagent atoms used for lazily loading home screen tabs
|
||||||
(def load-communities-tab? (reagent/atom true))
|
(def load-communities-tab? (reagent/atom false))
|
||||||
(def load-chats-tab? (reagent/atom false))
|
(def load-chats-tab? (reagent/atom false))
|
||||||
(def load-wallet-tab? (reagent/atom false))
|
(def load-wallet-tab? (reagent/atom false))
|
||||||
(def load-browser-tab? (reagent/atom false))
|
(def load-browser-tab? (reagent/atom false))
|
||||||
|
|
||||||
|
(defn load-selected-stack [stack-id]
|
||||||
|
(case stack-id
|
||||||
|
:communities-stack (reset! load-communities-tab? true)
|
||||||
|
:chats-stack (reset! load-chats-tab? true)
|
||||||
|
:wallet-stack (reset! load-wallet-tab? true)
|
||||||
|
:browser-stack (reset! load-browser-tab? true)
|
||||||
|
""))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
:new-ui/reset-bottom-tabs
|
:new-ui/reset-bottom-tabs
|
||||||
(fn []
|
(fn []
|
||||||
(reset! selected-stack-id :communities-stack)
|
(let [selected-stack-id @animation/selected-stack-id]
|
||||||
(reset! load-communities-tab? true)
|
(reset! load-communities-tab? (= selected-stack-id :communities-stack))
|
||||||
(reset! load-chats-tab? false)
|
(reset! load-chats-tab? (= selected-stack-id :chats-stack))
|
||||||
(reset! load-wallet-tab? false)
|
(reset! load-wallet-tab? (= selected-stack-id :wallet-stack))
|
||||||
(reset! load-browser-tab? false)))
|
(reset! load-browser-tab? (= selected-stack-id :browser-stack)))))
|
||||||
|
|
||||||
(defn bottom-tab-on-press [shared-values stack-id]
|
(defn bottom-tab-on-press [shared-values stack-id]
|
||||||
(when-not (= stack-id @selected-stack-id)
|
(when-not (= stack-id @animation/selected-stack-id)
|
||||||
(reset! selected-stack-id stack-id)
|
(let [stack-load-delay (cond
|
||||||
(animation/bottom-tab-on-press shared-values stack-id)
|
@animation/home-stack-open? 0
|
||||||
(case stack-id
|
platform/android? 250
|
||||||
:communities-stack (reset! load-communities-tab? true)
|
:else 300)]
|
||||||
:chats-stack (reset! load-chats-tab? true)
|
(animation/change-tab shared-values stack-id)
|
||||||
:wallet-stack (reset! load-wallet-tab? true)
|
(js/setTimeout #(load-selected-stack stack-id) stack-load-delay))))
|
||||||
:browser-stack (reset! load-browser-tab? true))))
|
|
||||||
|
|
||||||
;; TODO(parvesh) - reimplement tab with counter, once design is complete
|
(defn bottom-tab [icon stack-id shared-values]
|
||||||
(defn bottom-tab [icon stack-id icons-only? shared-values]
|
[bottom-nav-tab/bottom-nav-tab
|
||||||
[:f>
|
{:icon icon
|
||||||
(fn []
|
:icon-color-anim (get
|
||||||
(let [bottom-tab-original-style {:padding 16}]
|
shared-values
|
||||||
(if icons-only?
|
(get constants/tabs-icon-color-keywords stack-id))
|
||||||
[rn/touchable-opacity {:active-opacity 1
|
:on-press #(bottom-tab-on-press shared-values stack-id)
|
||||||
:style bottom-tab-original-style
|
:accessibility-label (str (name stack-id) "-tab")}])
|
||||||
:on-press #(bottom-tab-on-press shared-values stack-id)}
|
|
||||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
|
||||||
{:opacity (get
|
|
||||||
shared-values
|
|
||||||
(get constants/tabs-opacity-keywords stack-id))}
|
|
||||||
{})}
|
|
||||||
[icons/icon icon (styles/bottom-tab-icon :bottom-tabs-selected-tab)]]]
|
|
||||||
[rn/view {:style bottom-tab-original-style}
|
|
||||||
[icons/icon icon (styles/bottom-tab-icon :bottom-tabs-non-selected-tab)]])))])
|
|
||||||
|
|
||||||
(defn tabs [shared-values icons-only?]
|
|
||||||
[rn/view {:style (styles/bottom-tabs icons-only?)}
|
|
||||||
[bottom-tab :main-icons2/communities :communities-stack icons-only? shared-values]
|
|
||||||
[bottom-tab :main-icons2/messages :chats-stack icons-only? shared-values]
|
|
||||||
[rn/view {:width 50}]
|
|
||||||
[bottom-tab :main-icons2/wallet :wallet-stack icons-only? shared-values]
|
|
||||||
[bottom-tab :main-icons2/browser :browser-stack icons-only? shared-values]])
|
|
||||||
|
|
||||||
(defn bottom-tabs [shared-values]
|
(defn bottom-tabs [shared-values]
|
||||||
[:<>
|
(load-selected-stack @animation/selected-stack-id)
|
||||||
[tabs shared-values false]
|
[rn/view {:style (styles/bottom-tabs-container false)}
|
||||||
[tabs shared-values true]])
|
[rn/view {:style (styles/bottom-tabs)}
|
||||||
|
[bottom-tab :main-icons2/communities :communities-stack shared-values]
|
||||||
|
[bottom-tab :main-icons2/messages :chats-stack shared-values]
|
||||||
|
[bottom-tab :main-icons2/wallet :wallet-stack shared-values]
|
||||||
|
[bottom-tab :main-icons2/browser :browser-stack shared-values]]])
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
(ns status-im.switcher.cards.messaging-card
|
|
||||||
(:require [quo.react-native :as rn]
|
|
||||||
[quo2.components.markdown.text :as text]
|
|
||||||
[status-im.constants :as constants]
|
|
||||||
[quo2.components.buttons.button :as button]
|
|
||||||
[status-im.utils.handlers :refer [>evt <sub]]
|
|
||||||
[status-im.switcher.cards.styles :as styles]))
|
|
||||||
|
|
||||||
;; TODO - Add switcher close animation (fade) while opening screen from cards
|
|
||||||
;; currently dealy is added to avoid default circular animation
|
|
||||||
(defn on-press [id toggle-switcher-screen]
|
|
||||||
(js/setTimeout toggle-switcher-screen 100)
|
|
||||||
(>evt [:chat.ui/navigate-to-chat-nav2 id true]))
|
|
||||||
|
|
||||||
;; TODO - add last message for other content types
|
|
||||||
(defn last-message [{:keys [content content-type]}]
|
|
||||||
(cond
|
|
||||||
(= constants/content-type-text content-type)
|
|
||||||
[text/text (styles/messaging-card-last-message-text-props) (:text content)]))
|
|
||||||
|
|
||||||
(defn card [{:keys [id toggle-switcher-screen]}]
|
|
||||||
(let [chat (<sub [:chats/chat id])]
|
|
||||||
[rn/touchable-without-feedback {:on-press #(on-press id toggle-switcher-screen)}
|
|
||||||
[rn/view {:style (styles/messaging-card-main-container)}
|
|
||||||
[rn/view {:style (styles/messaging-card-secondary-container)}
|
|
||||||
[text/text (styles/messaging-card-title-props) (:alias chat)]
|
|
||||||
[text/text (styles/messaging-card-subtitle-props) "Message"]
|
|
||||||
[rn/view {:style (styles/messaging-card-details-container)}
|
|
||||||
[last-message (:last-message chat)]]]
|
|
||||||
[rn/view {:style (styles/messaging-card-avatar-container)}]
|
|
||||||
[button/button (styles/messaging-card-close-button-props) :main-icons/close]]]))
|
|
||||||
|
|
|
@ -1,103 +0,0 @@
|
||||||
(ns status-im.switcher.cards.styles
|
|
||||||
(:require [quo.theme :as theme]
|
|
||||||
[quo2.foundations.colors :as colors]))
|
|
||||||
|
|
||||||
(def themes
|
|
||||||
{:light {:messaging-card-container-background-color "#26A69A"
|
|
||||||
:messaging-card-secondary-container-background-color colors/white
|
|
||||||
:messaging-card-title-color colors/neutral-100
|
|
||||||
:messaging-card-subtitle-color colors/neutral-50
|
|
||||||
:messaging-card-last-message-text-color colors/neutral-100
|
|
||||||
:messaging-card-close-button-bg-color colors/white-opa-50
|
|
||||||
:messaging-card-close-button-icon-color colors/neutral-100}
|
|
||||||
:dark {:messaging-card-container-background-color "#26A69A"
|
|
||||||
:messaging-card-secondary-container-background-color colors/neutral-90
|
|
||||||
:messaging-card-title-color colors/white
|
|
||||||
:messaging-card-subtitle-color colors/neutral-40
|
|
||||||
:messaging-card-last-message-text-color colors/white
|
|
||||||
:messaging-card-close-button-bg-color colors/neutral-80-opa-60
|
|
||||||
:messaging-card-close-button-icon-color colors/white}})
|
|
||||||
|
|
||||||
(defn get-color [key]
|
|
||||||
(get-in themes [(theme/get-theme) key]))
|
|
||||||
|
|
||||||
;; Messaging Card
|
|
||||||
|
|
||||||
(defn messaging-card-main-container []
|
|
||||||
{:width 160
|
|
||||||
:height 172
|
|
||||||
:border-radius 16
|
|
||||||
:margin 8
|
|
||||||
:background-color (get-color :messaging-card-container-background-color)})
|
|
||||||
|
|
||||||
(defn messaging-card-secondary-container []
|
|
||||||
{:width 160
|
|
||||||
:height 132
|
|
||||||
:background-color (get-color :messaging-card-secondary-container-background-color)
|
|
||||||
:border-radius 16
|
|
||||||
:position :absolute
|
|
||||||
:bottom 0})
|
|
||||||
|
|
||||||
(defn messaging-card-title []
|
|
||||||
{:position :absolute
|
|
||||||
:top 32
|
|
||||||
:margin-horizontal 12
|
|
||||||
:color (get-color :messaging-card-title-color)})
|
|
||||||
|
|
||||||
(defn messaging-card-title-props []
|
|
||||||
{:size :paragraph-1
|
|
||||||
:weight :semi-bold
|
|
||||||
:number-of-lines 1
|
|
||||||
:ellipsize-mode :tail
|
|
||||||
:style (messaging-card-title)})
|
|
||||||
|
|
||||||
(defn messaging-card-subtitle []
|
|
||||||
{:position :absolute
|
|
||||||
:top 54
|
|
||||||
:margin-horizontal 12
|
|
||||||
:color (get-color :messaging-card-subtitle-color)})
|
|
||||||
|
|
||||||
(defn messaging-card-subtitle-props []
|
|
||||||
{:size :paragraph-2
|
|
||||||
:weight :medium
|
|
||||||
:style (messaging-card-subtitle)})
|
|
||||||
|
|
||||||
(defn messaging-card-details-container []
|
|
||||||
{:position :absolute
|
|
||||||
:bottom 12
|
|
||||||
:margin-horizontal 12
|
|
||||||
:width 136
|
|
||||||
:height 36})
|
|
||||||
|
|
||||||
(defn messaging-card-last-message-text []
|
|
||||||
{:color (get-color :messaging-card-last-message-text-color)})
|
|
||||||
|
|
||||||
(defn messaging-card-last-message-text-props []
|
|
||||||
{:size :paragraph-2
|
|
||||||
:weight :regular
|
|
||||||
:number-of-lines 2
|
|
||||||
:ellipsize-mode :tail
|
|
||||||
:style (messaging-card-last-message-text)})
|
|
||||||
|
|
||||||
(defn messaging-card-close-button []
|
|
||||||
{:position :absolute
|
|
||||||
:right 8
|
|
||||||
:top 8
|
|
||||||
:background-color (get-color :messaging-card-close-button-bg-color)
|
|
||||||
:icon-color (get-color :messaging-card-icon-color)})
|
|
||||||
|
|
||||||
(defn messaging-card-close-button-props []
|
|
||||||
{:size 24
|
|
||||||
:type :grey
|
|
||||||
:icon true
|
|
||||||
:on-press #(print "close pressed")
|
|
||||||
:style (messaging-card-close-button)})
|
|
||||||
|
|
||||||
(defn messaging-card-avatar-container []
|
|
||||||
{:width 48
|
|
||||||
:height 48
|
|
||||||
:border-radius 24
|
|
||||||
:position :absolute
|
|
||||||
:left 12
|
|
||||||
:top 16
|
|
||||||
:background-color :pink})
|
|
|
@ -1,57 +1,26 @@
|
||||||
(ns status-im.switcher.constants
|
(ns status-im.switcher.constants
|
||||||
(:require [quo.react-native :as rn]
|
(:require [quo.react-native :as rn]
|
||||||
|
[reagent.core :as reagent]
|
||||||
[status-im.utils.handlers :refer [<sub]]
|
[status-im.utils.handlers :refer [<sub]]
|
||||||
[status-im.utils.platform :as platform]))
|
[status-im.utils.platform :as platform]))
|
||||||
|
|
||||||
;; For translucent status bar(android), dimensions/window also includes status bar's height,
|
(defn bottom-tabs-container-height []
|
||||||
;; this offset is used for correctly calculating switcher position
|
(if platform/android? 57 82))
|
||||||
(def switcher-height-offset
|
|
||||||
(if platform/android? (:status-bar-height @rn/navigation-const) 0))
|
|
||||||
|
|
||||||
;; extra height of switcher container for show/peek hidden cards while opening animation
|
(defn bottom-tabs-extended-container-height []
|
||||||
(def switcher-container-height-padding 100)
|
(if platform/android? 90 120))
|
||||||
|
|
||||||
(def switcher-button-radius 24)
|
(def status-bar-offset
|
||||||
|
(if platform/android? (.-currentHeight ^js rn/status-bar) 0))
|
||||||
(def switcher-button-size
|
|
||||||
(* switcher-button-radius 2))
|
|
||||||
|
|
||||||
(def switcher-pressed-scale 0.9)
|
|
||||||
|
|
||||||
(def switcher-pressed-radius
|
|
||||||
(* switcher-pressed-scale switcher-button-radius))
|
|
||||||
|
|
||||||
(def switcher-pressed-size
|
|
||||||
(* 2 switcher-pressed-radius))
|
|
||||||
|
|
||||||
(def switcher-bottom-positions
|
|
||||||
{:android
|
|
||||||
{:home-stack 15
|
|
||||||
:chat 140}
|
|
||||||
:ios
|
|
||||||
{:home-stack 40
|
|
||||||
:chat 140}})
|
|
||||||
|
|
||||||
(defn switcher-bottom-position [view-id]
|
|
||||||
(get-in
|
|
||||||
switcher-bottom-positions
|
|
||||||
[(keyword platform/os) view-id]))
|
|
||||||
|
|
||||||
(defn switcher-pressed-bottom-position [view-id]
|
|
||||||
(+
|
|
||||||
(get-in
|
|
||||||
switcher-bottom-positions
|
|
||||||
[(keyword platform/os) view-id])
|
|
||||||
(- switcher-button-radius switcher-pressed-radius)))
|
|
||||||
|
|
||||||
;; TODO(parvesh) - use different height for android and ios(Confirm from Design)
|
|
||||||
(defn bottom-tabs-height []
|
|
||||||
(if platform/android? 55 80))
|
|
||||||
|
|
||||||
|
;; 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
|
||||||
(defn dimensions []
|
(defn dimensions []
|
||||||
(let [{:keys [width height]} (<sub [:dimensions/window])]
|
(let [{:keys [width height]} (<sub [:dimensions/window])]
|
||||||
{:width width
|
{:width width
|
||||||
:height (+ height switcher-height-offset)}))
|
:height (if (> status-bar-offset 28)
|
||||||
|
(+ height status-bar-offset)
|
||||||
|
height)}))
|
||||||
|
|
||||||
(def stacks-ids [:communities-stack :chats-stack :wallet-stack :browser-stack])
|
(def stacks-ids [:communities-stack :chats-stack :wallet-stack :browser-stack])
|
||||||
|
|
||||||
|
@ -67,8 +36,10 @@
|
||||||
:wallet-stack :wallet-stack-pointer
|
:wallet-stack :wallet-stack-pointer
|
||||||
:browser-stack :browser-stack-pointer})
|
:browser-stack :browser-stack-pointer})
|
||||||
|
|
||||||
(def tabs-opacity-keywords
|
(def tabs-icon-color-keywords
|
||||||
{:communities-stack :communities-tab-opacity
|
{:communities-stack :communities-tab-icon-color
|
||||||
:chats-stack :chats-tab-opacity
|
:chats-stack :chats-tab-icon-opacity
|
||||||
:wallet-stack :wallet-tab-opacity
|
:wallet-stack :wallet-tab-icon-opacity
|
||||||
:browser-stack :browser-tab-opacity})
|
:browser-stack :browser-tab-icon-opacity})
|
||||||
|
|
||||||
|
(def pass-through? (reagent/atom false))
|
||||||
|
|
|
@ -1,33 +1,36 @@
|
||||||
(ns status-im.switcher.home-stack
|
(ns status-im.switcher.home-stack
|
||||||
(:require [quo2.reanimated :as reanimated]
|
(:require [quo2.reanimated :as reanimated]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.switcher.styles :as styles]
|
||||||
[status-im.switcher.switcher :as switcher]
|
[status-im.switcher.animation :as animation]
|
||||||
[status-im.ui2.screens.chat.home :as chat.home]
|
|
||||||
[status-im.switcher.constants :as constants]
|
[status-im.switcher.constants :as constants]
|
||||||
|
[status-im.ui2.screens.chat.home :as chat.home]
|
||||||
[status-im.switcher.bottom-tabs :as bottom-tabs]
|
[status-im.switcher.bottom-tabs :as bottom-tabs]
|
||||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||||
[status-im.ui.screens.communities.communities-list-redesign :as communities]
|
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]))
|
[quo2.components.navigation.floating-shell-button :as floating-shell-button]
|
||||||
|
[status-im.ui.screens.communities.communities-list-redesign :as communities]))
|
||||||
|
|
||||||
(defn load-stack? [stack-id]
|
(defn load-stack? [stack-id]
|
||||||
(case stack-id
|
(case stack-id
|
||||||
:communities-stack @bottom-tabs/load-communities-tab?
|
:communities-stack @bottom-tabs/load-communities-tab?
|
||||||
:chats-stack @bottom-tabs/load-chats-tab?
|
:chats-stack @bottom-tabs/load-chats-tab?
|
||||||
:browser-stack @bottom-tabs/load-browser-tab?
|
:browser-stack @bottom-tabs/load-browser-tab?
|
||||||
:wallet-stack @bottom-tabs/load-wallet-tab?))
|
:wallet-stack @bottom-tabs/load-wallet-tab?))
|
||||||
|
|
||||||
(defn stack-view [stack-id shared-values]
|
(defn stack-view [stack-id shared-values]
|
||||||
(when (load-stack? stack-id)
|
(when (load-stack? stack-id)
|
||||||
[:f>
|
[:f>
|
||||||
(fn []
|
(fn []
|
||||||
[reanimated/view {:style (reanimated/apply-animations-to-style
|
[reanimated/view
|
||||||
{:opacity (get shared-values (get constants/stacks-opacity-keywords stack-id))
|
{:style (reanimated/apply-animations-to-style
|
||||||
:pointer-events (get shared-values (get constants/stacks-pointer-keywords stack-id))}
|
{:opacity (get shared-values (get constants/stacks-opacity-keywords stack-id))
|
||||||
{:top 0
|
:pointer-events (get shared-values (get constants/stacks-pointer-keywords stack-id))}
|
||||||
:bottom (if platform/ios? 79 54)
|
{:position :absolute
|
||||||
:left 0
|
:top 0
|
||||||
:right 0
|
:bottom 0
|
||||||
:position :absolute})}
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:accessibility-label stack-id})}
|
||||||
(case stack-id
|
(case stack-id
|
||||||
:communities-stack [communities/communities-list]
|
:communities-stack [communities/communities-list]
|
||||||
:chats-stack [chat.home/home]
|
:chats-stack [chat.home/home]
|
||||||
|
@ -35,29 +38,22 @@
|
||||||
:browser-stack [profile.user/my-profile])])]))
|
:browser-stack [profile.user/my-profile])])]))
|
||||||
|
|
||||||
(defn home-stack [shared-values]
|
(defn home-stack [shared-values]
|
||||||
[:<>
|
|
||||||
[stack-view :communities-stack shared-values]
|
|
||||||
[stack-view :chats-stack shared-values]
|
|
||||||
[stack-view :browser-stack shared-values]
|
|
||||||
[stack-view :wallet-stack shared-values]])
|
|
||||||
|
|
||||||
(defn home []
|
|
||||||
[:f>
|
[:f>
|
||||||
(fn []
|
(fn []
|
||||||
(let [selected-stack-id @bottom-tabs/selected-stack-id
|
(let [home-stack-original-style (styles/home-stack)
|
||||||
shared-values (reduce (fn [acc id]
|
home-stack-animated-style (reanimated/apply-animations-to-style
|
||||||
(let [selected-tab? (= id selected-stack-id)
|
{:top (:home-stack-top shared-values)
|
||||||
tab-opacity-keyword (get constants/tabs-opacity-keywords id)
|
:left (:home-stack-left shared-values)
|
||||||
stack-opacity-keyword (get constants/stacks-opacity-keywords id)
|
:opacity (:home-stack-opacity shared-values)
|
||||||
stack-pointer-keyword (get constants/stacks-pointer-keywords id)]
|
:pointer-events (:home-stack-pointer shared-values)
|
||||||
(assoc
|
:transform [{:scale (:home-stack-scale shared-values)}]}
|
||||||
acc
|
home-stack-original-style)]
|
||||||
tab-opacity-keyword (reanimated/use-shared-value (if selected-tab? 1 0))
|
[reanimated/view {:style home-stack-animated-style}
|
||||||
stack-opacity-keyword (reanimated/use-shared-value (if selected-tab? 1 0))
|
[stack-view :communities-stack shared-values]
|
||||||
stack-pointer-keyword (reanimated/use-shared-value (if selected-tab? "auto" "none")))))
|
[stack-view :chats-stack shared-values]
|
||||||
{}
|
[stack-view :browser-stack shared-values]
|
||||||
constants/stacks-ids)]
|
[stack-view :wallet-stack shared-values]
|
||||||
[:<>
|
[floating-shell-button/floating-shell-button
|
||||||
[home-stack shared-values]
|
{:jump-to {:on-press #(animation/close-home-stack shared-values)}}
|
||||||
[bottom-tabs/bottom-tabs shared-values]
|
{:position :absolute
|
||||||
[switcher/switcher :home-stack]]))])
|
:bottom 12}]]))])
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
(ns status-im.switcher.shell
|
||||||
|
(:require [quo.react-native :as rn]
|
||||||
|
[status-im.i18n.i18n :as i18n]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.components.markdown.text :as text]
|
||||||
|
[quo.components.safe-area :as safe-area]
|
||||||
|
[quo2.components.navigation.top-nav :as top-nav]))
|
||||||
|
|
||||||
|
(defn placeholder []
|
||||||
|
[rn/view {:style {:position :absolute
|
||||||
|
:top 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom -1
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:accessibility-label :shell-placeholder-view}}
|
||||||
|
[rn/view {:style {:margin-top 12
|
||||||
|
:width 80
|
||||||
|
:height 80
|
||||||
|
:border-radius 16
|
||||||
|
:background-color colors/neutral-90}}]
|
||||||
|
[text/text {:size :heading-2
|
||||||
|
:weight :semi-bold
|
||||||
|
:style {:margin-top 20
|
||||||
|
:color colors/white}}
|
||||||
|
(i18n/label :t/shell-placeholder-title)]
|
||||||
|
[text/text {:size :paragraph-1
|
||||||
|
:weight :regular
|
||||||
|
:align :center
|
||||||
|
:style {:margin-top 8
|
||||||
|
:color colors/white}}
|
||||||
|
(i18n/label :t/shell-placeholder-subtitle)]])
|
||||||
|
|
||||||
|
(defn shell []
|
||||||
|
[safe-area/consumer
|
||||||
|
(fn [insets]
|
||||||
|
[rn/view {:style {:top 0
|
||||||
|
:left 0
|
||||||
|
:right 0
|
||||||
|
:bottom -1
|
||||||
|
:position :absolute
|
||||||
|
:background-color colors/neutral-100}}
|
||||||
|
[top-nav/top-nav {:type :shell
|
||||||
|
:style {:margin-top (:top insets)}}]
|
||||||
|
[placeholder]
|
||||||
|
[rn/scroll-view {:style {:padding-horizontal 20
|
||||||
|
:flex-direction :row}}
|
||||||
|
[text/text {:size :heading-1
|
||||||
|
:weight :semi-bold
|
||||||
|
:style {:color colors/white
|
||||||
|
:margin-top 12}}
|
||||||
|
(i18n/label :t/jump-to)]]])])
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
(ns status-im.switcher.shell-stack
|
||||||
|
(:require [status-im.switcher.shell :as shell]
|
||||||
|
[status-im.switcher.animation :as animation]
|
||||||
|
[status-im.switcher.home-stack :as home-stack]
|
||||||
|
[status-im.switcher.bottom-tabs :as bottom-tabs]))
|
||||||
|
|
||||||
|
(defn shell-stack []
|
||||||
|
[:f>
|
||||||
|
(fn []
|
||||||
|
(let [shared-values (animation/get-shared-values)]
|
||||||
|
[:<>
|
||||||
|
[shell/shell]
|
||||||
|
[bottom-tabs/bottom-tabs shared-values]
|
||||||
|
[home-stack/home-stack shared-values]]))])
|
|
@ -1,89 +1,35 @@
|
||||||
(ns status-im.switcher.styles
|
(ns status-im.switcher.styles
|
||||||
(:require [quo.theme :as theme]
|
(:require [quo2.foundations.colors :as colors]
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.switcher.constants :as constants]))
|
[status-im.switcher.constants :as constants]))
|
||||||
|
|
||||||
(def themes
|
|
||||||
{:light {:bottom-tabs-bg-color colors/neutral-80
|
|
||||||
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-80
|
|
||||||
:bottom-tabs-non-selected-tab colors/neutral-50
|
|
||||||
:bottom-tabs-selected-tab colors/white
|
|
||||||
:switcher-close-button-bg-color colors/white}
|
|
||||||
:dark {:bottom-tabs-bg-color colors/neutral-80
|
|
||||||
:bottom-tabs-on-scroll-bg-color colors/neutral-80-opa-80
|
|
||||||
:bottom-tabs-non-selected-tab colors/neutral-50
|
|
||||||
:bottom-tabs-selected-tab colors/white
|
|
||||||
:switcher-close-button-bg-color colors/white}})
|
|
||||||
|
|
||||||
(defn get-color [key]
|
|
||||||
(get-in themes [(theme/get-theme) key]))
|
|
||||||
|
|
||||||
;; Bottom Tabs
|
;; Bottom Tabs
|
||||||
(defn bottom-tab-icon [tab-state]
|
(defn bottom-tabs-container [pass-through?]
|
||||||
{:size 24
|
{:background-color (if pass-through? colors/neutral-100-opa-70 colors/neutral-100)
|
||||||
:color (get-color tab-state)})
|
:flex 1
|
||||||
|
:align-items :center
|
||||||
|
:flex-direction :column
|
||||||
|
:height (constants/bottom-tabs-container-height)
|
||||||
|
:position :absolute
|
||||||
|
:bottom -1
|
||||||
|
:right 0
|
||||||
|
:left 0
|
||||||
|
:accessibility-label :bottom-tabs-container})
|
||||||
|
|
||||||
(defn bottom-tabs [icons-only?]
|
(defn bottom-tabs []
|
||||||
{:background-color (if icons-only? nil (get-color :bottom-tabs-bg-color))
|
{:flex-direction :row
|
||||||
:flex-direction :row
|
:position :absolute
|
||||||
:flex 1
|
:bottom (if platform/android? 8 34)
|
||||||
:justify-content :space-between
|
:flex 1
|
||||||
:height (constants/bottom-tabs-height)
|
:accessibility-label :bottom-tabs})
|
||||||
:position :absolute
|
|
||||||
:bottom -1
|
|
||||||
:right 0
|
|
||||||
:left 0
|
|
||||||
:padding-horizontal 16})
|
|
||||||
|
|
||||||
;; Switcher
|
;; Home Stack
|
||||||
(defn switcher-button []
|
(defn home-stack []
|
||||||
{:width constants/switcher-button-size
|
|
||||||
:height constants/switcher-button-size
|
|
||||||
:z-index 2})
|
|
||||||
|
|
||||||
(defn merge-switcher-button-common-styles [style]
|
|
||||||
(merge
|
|
||||||
{:width constants/switcher-button-size
|
|
||||||
:height constants/switcher-button-size
|
|
||||||
:border-radius constants/switcher-button-radius
|
|
||||||
:position :absolute
|
|
||||||
:z-index 2
|
|
||||||
:align-items :center
|
|
||||||
:align-self :center
|
|
||||||
:justify-content :center}
|
|
||||||
style))
|
|
||||||
|
|
||||||
(defn switcher-button-touchable [view-id]
|
|
||||||
(merge-switcher-button-common-styles
|
|
||||||
{:bottom (constants/switcher-bottom-position view-id)}))
|
|
||||||
|
|
||||||
(defn switcher-close-button []
|
|
||||||
(merge-switcher-button-common-styles
|
|
||||||
{:backgroundColor (get-color :switcher-close-button-bg-color)}))
|
|
||||||
|
|
||||||
(defn switcher-screen []
|
|
||||||
(cond-> (merge-switcher-button-common-styles
|
|
||||||
{:background-color colors/neutral-80-opa-80
|
|
||||||
:z-index 1
|
|
||||||
:overflow :hidden})
|
|
||||||
platform/android? (dissoc :background-color)
|
|
||||||
true (dissoc :justify-content)))
|
|
||||||
|
|
||||||
(defn switcher-blur-background []
|
|
||||||
(let [{:keys [width height]} (constants/dimensions)]
|
(let [{:keys [width height]} (constants/dimensions)]
|
||||||
{:style {:width width
|
{:border-bottom-left-radius 20
|
||||||
:height (+ height constants/switcher-container-height-padding)}
|
:border-bottom-right-radius 20
|
||||||
:blur-amount 17
|
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)
|
||||||
:overlay-color colors/neutral-80-opa-80}))
|
:overflow :hidden
|
||||||
|
:position :absolute
|
||||||
(defn switcher-screen-container []
|
:width width
|
||||||
(let [{:keys [width height]} (constants/dimensions)]
|
:height (- height (constants/bottom-tabs-container-height))}))
|
||||||
{:width width
|
|
||||||
:height (+ height constants/switcher-container-height-padding)
|
|
||||||
:align-items :center
|
|
||||||
:position :absolute}))
|
|
||||||
|
|
||||||
(defn switcher-switch-screen []
|
|
||||||
{:margin-top 40
|
|
||||||
:align-items :center})
|
|
||||||
|
|
|
@ -1,80 +0,0 @@
|
||||||
(ns status-im.switcher.switcher
|
|
||||||
(:require [reagent.core :as reagent]
|
|
||||||
[quo2.reanimated :as reanimated]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[status-im.switcher.styles :as styles]
|
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[status-im.switcher.constants :as constants]
|
|
||||||
[status-im.switcher.animation :as animation]
|
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
|
||||||
[status-im.react-native.resources :as resources]
|
|
||||||
[status-im.switcher.switcher-container :as switcher-container]
|
|
||||||
[quo.react-native :as rn]))
|
|
||||||
|
|
||||||
(defn switcher-button [view-id toggle-switcher-screen-fn shared-values]
|
|
||||||
[:f>
|
|
||||||
(fn []
|
|
||||||
(let [touchable-original-style (styles/switcher-button-touchable view-id)
|
|
||||||
close-button-original-style (styles/switcher-close-button)
|
|
||||||
switcher-button-original-style (styles/switcher-button)
|
|
||||||
touchable-animated-style (reanimated/apply-animations-to-style
|
|
||||||
{:transform [{:scale (:button-touchable-scale shared-values)}]}
|
|
||||||
touchable-original-style)
|
|
||||||
close-button-animated-style (reanimated/apply-animations-to-style
|
|
||||||
{:opacity (:close-button-opacity shared-values)}
|
|
||||||
close-button-original-style)
|
|
||||||
switcher-button-animated-style (reanimated/apply-animations-to-style
|
|
||||||
{:opacity (:switcher-button-opacity shared-values)}
|
|
||||||
switcher-button-original-style)]
|
|
||||||
[reanimated/touchable-opacity {:active-opacity 1
|
|
||||||
:on-press-in #(animation/switcher-touchable-on-press-in
|
|
||||||
(:button-touchable-scale shared-values))
|
|
||||||
:on-press-out toggle-switcher-screen-fn
|
|
||||||
:style touchable-animated-style}
|
|
||||||
[reanimated/view {:style close-button-animated-style}
|
|
||||||
[icons/icon :main-icons/close {:color colors/neutral-100}]]
|
|
||||||
[reanimated/image {:source (resources/get-image :switcher)
|
|
||||||
:style switcher-button-animated-style}]]))])
|
|
||||||
|
|
||||||
(defn switcher-screen [toggle-switcher-screen-fn shared-values]
|
|
||||||
[:f>
|
|
||||||
(fn []
|
|
||||||
(let [switcher-screen-original-style (styles/switcher-screen)
|
|
||||||
switcher-container-original-style (styles/switcher-screen-container)
|
|
||||||
switcher-screen-animated-style (reanimated/apply-animations-to-style
|
|
||||||
{:width (:switcher-screen-size shared-values)
|
|
||||||
:height (:switcher-screen-size shared-values)
|
|
||||||
:bottom (:switcher-screen-bottom shared-values)
|
|
||||||
:border-radius (:switcher-screen-radius shared-values)}
|
|
||||||
switcher-screen-original-style)
|
|
||||||
switcher-container-animated-style (reanimated/apply-animations-to-style
|
|
||||||
{:bottom (:switcher-container-bottom shared-values)
|
|
||||||
:transform [{:scale (:switcher-container-scale shared-values)}]}
|
|
||||||
switcher-container-original-style)]
|
|
||||||
[reanimated/view {:style switcher-screen-animated-style}
|
|
||||||
[react/blur-view (styles/switcher-blur-background)]
|
|
||||||
[reanimated/view {:style switcher-container-animated-style}
|
|
||||||
[switcher-container/tabs toggle-switcher-screen-fn]]]))])
|
|
||||||
|
|
||||||
(defn switcher [view-id]
|
|
||||||
[:f>
|
|
||||||
(fn []
|
|
||||||
(let [switcher-opened? (reagent/atom false)
|
|
||||||
switcher-button-opacity (reanimated/use-shared-value 1)
|
|
||||||
switcher-screen-size (reanimated/use-shared-value constants/switcher-pressed-size)
|
|
||||||
switcher-screen-radius (animation/switcher-screen-radius switcher-screen-size)
|
|
||||||
switcher-screen-bottom (animation/switcher-screen-bottom-position switcher-screen-radius view-id)
|
|
||||||
shared-values {:switcher-button-opacity switcher-button-opacity
|
|
||||||
:switcher-screen-size switcher-screen-size
|
|
||||||
:switcher-screen-radius switcher-screen-radius
|
|
||||||
:switcher-screen-bottom switcher-screen-bottom
|
|
||||||
:button-touchable-scale (reanimated/use-shared-value 1)
|
|
||||||
:switcher-container-scale (reanimated/use-shared-value 0.9)
|
|
||||||
:close-button-opacity (animation/switcher-close-button-opacity switcher-button-opacity)
|
|
||||||
:switcher-container-bottom (animation/switcher-container-bottom-position switcher-screen-bottom)}
|
|
||||||
toggle-switcher-screen-fn #(animation/switcher-touchable-on-press-out switcher-opened? view-id shared-values)
|
|
||||||
{:keys [keyboard-shown]} (rn/use-keyboard)]
|
|
||||||
(when-not keyboard-shown
|
|
||||||
[:<>
|
|
||||||
[switcher-screen toggle-switcher-screen-fn shared-values]
|
|
||||||
[switcher-button view-id toggle-switcher-screen-fn shared-values]])))])
|
|
|
@ -1,31 +0,0 @@
|
||||||
(ns status-im.switcher.switcher-container
|
|
||||||
(:require [quo.react-native :as rn]
|
|
||||||
[status-im.switcher.cards.messaging-card :as messaging-card]
|
|
||||||
[status-im.switcher.styles :as styles]
|
|
||||||
[status-im.utils.handlers :refer [<sub]]))
|
|
||||||
|
|
||||||
;; TODO - use something like this to avoid multiple renders etc.
|
|
||||||
;; (defn switch-screen [toggle-switcher-screen]
|
|
||||||
;; (let [cards (<sub [:navigation2/switcher-cards])
|
|
||||||
;; new-cards (reduce (fn [acc card]
|
|
||||||
;; (conj acc (assoc card :toggle-switcher-screen toggle-switcher-screen)))
|
|
||||||
;; () cards)]
|
|
||||||
;; (fn []
|
|
||||||
;; [rn/view {:style (styles/switcher-switch-screen)}
|
|
||||||
;; [rn/flat-list {:width 352
|
|
||||||
;; :data new-cards
|
|
||||||
;; :render-fn messaging-card/card
|
|
||||||
;; :num-columns 2
|
|
||||||
;; :key-fn str}]])))
|
|
||||||
|
|
||||||
(defn switch-screen [toggle-switcher-screen]
|
|
||||||
(let [cards (<sub [:navigation2/switcher-cards toggle-switcher-screen])]
|
|
||||||
[rn/view {:style (styles/switcher-switch-screen)}
|
|
||||||
[rn/flat-list {:width 352
|
|
||||||
:data cards
|
|
||||||
:render-fn messaging-card/card
|
|
||||||
:num-columns 2
|
|
||||||
:key-fn str}]]))
|
|
||||||
|
|
||||||
(defn tabs [toggle-switcher-screen]
|
|
||||||
[switch-screen toggle-switcher-screen])
|
|
|
@ -1,6 +0,0 @@
|
||||||
(ns status-im.switcher.utils
|
|
||||||
(:require [re-frame.core :as re-frame]))
|
|
||||||
|
|
||||||
(def switcher-container-view-id (atom nil))
|
|
||||||
|
|
||||||
(re-frame/reg-fx :switcher-container-view-id #(reset! switcher-container-view-id %))
|
|
|
@ -10,13 +10,17 @@
|
||||||
|
|
||||||
(defn message-reactions [{:keys [content-type]} reactions timeline on-emoji-press on-open]
|
(defn message-reactions [{:keys [content-type]} reactions timeline on-emoji-press on-open]
|
||||||
(when (seq reactions)
|
(when (seq reactions)
|
||||||
[rn/view {:style (styles/reactions-row timeline (if (= content-type constants/content-type-text) text-reaction-margin-top default-reaction-margin-top))}
|
[rn/view {:style (styles/reactions-row
|
||||||
|
timeline
|
||||||
|
(if (= content-type constants/content-type-text)
|
||||||
|
text-reaction-margin-top default-reaction-margin-top))}
|
||||||
(for [{:keys [own emoji-id quantity] :as emoji-reaction} reactions]
|
(for [{:keys [own emoji-id quantity] :as emoji-reaction} reactions]
|
||||||
^{:key (str emoji-reaction)}
|
^{:key (str emoji-reaction)}
|
||||||
[rn/view {:style {:margin-right 6 :margin-top 5}}
|
[rn/view {:style {:margin-right 6 :margin-top 5}}
|
||||||
[quo2.reaction/reaction {:emoji (get constants/reactions emoji-id)
|
[quo2.reaction/reaction {:emoji (get constants/reactions emoji-id)
|
||||||
:neutral? own
|
:neutral? own
|
||||||
:clicks quantity
|
:clicks quantity
|
||||||
:on-press #(on-emoji-press emoji-id)}]])
|
:on-press #(on-emoji-press emoji-id)
|
||||||
|
:accessibility-label (str "emoji-reaction-" emoji-id)}]])
|
||||||
;; on-press won't work until we integrate Message Context Drawer
|
;; on-press won't work until we integrate Message Context Drawer
|
||||||
[quo2.reaction/open-reactions-menu (when @on-open {:on-press @on-open})]]))
|
[quo2.reaction/open-reactions-menu (when @on-open {:on-press @on-open})]]))
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
:type :grey
|
:type :grey
|
||||||
:icon true
|
:icon true
|
||||||
:icon-no-color true
|
:icon-no-color true
|
||||||
:accessibility-label :reply-cancel-button
|
:accessibility-label (str "emoji-picker-" id)
|
||||||
:on-press #(do
|
:on-press #(do
|
||||||
(send-emoji id)
|
(send-emoji id)
|
||||||
(re-frame/dispatch [:bottom-sheet/hide]))}
|
(re-frame/dispatch [:bottom-sheet/hide]))}
|
||||||
|
@ -73,4 +73,4 @@
|
||||||
:icon (:icon action)
|
:icon (:icon action)
|
||||||
:on-press #(do
|
:on-press #(do
|
||||||
(when on-press (on-press))
|
(when on-press (on-press))
|
||||||
(re-frame/dispatch [:bottom-sheet/hide]))}]))]])))
|
(re-frame/dispatch [:bottom-sheet/hide]))}]))]])))
|
||||||
|
|
|
@ -48,7 +48,9 @@
|
||||||
(let [contact-name (<sub [:contacts/contact-name-by-identity from])
|
(let [contact-name (<sub [:contacts/contact-name-by-identity from])
|
||||||
current-public-key (<sub [:multiaccount/public-key])
|
current-public-key (<sub [:multiaccount/public-key])
|
||||||
content-type (or content-type contentType)]
|
content-type (or content-type contentType)]
|
||||||
[rn/view {:style {:flex-direction :row :height (when-not pin? 24)}}
|
[rn/view {:style {:flex-direction :row
|
||||||
|
:height (when-not pin? 24)
|
||||||
|
:accessibility-label :reply-message}}
|
||||||
[rn/view {:style (styles/reply-content pin?)}
|
[rn/view {:style (styles/reply-content pin?)}
|
||||||
(when-not pin?
|
(when-not pin?
|
||||||
;;TODO quo2 icon should be used
|
;;TODO quo2 icon should be used
|
||||||
|
|
|
@ -148,7 +148,7 @@
|
||||||
(multiaccounts/displayed-photo row)]}]))
|
(multiaccounts/displayed-photo row)]}]))
|
||||||
|
|
||||||
(defn chat-list-key-fn [item]
|
(defn chat-list-key-fn [item]
|
||||||
(or (:chat-id item) (:public-key item)))
|
(or (:chat-id item) (:public-key item) (:id item)))
|
||||||
|
|
||||||
(defn get-item-layout [_ index]
|
(defn get-item-layout [_ index]
|
||||||
#js {:length 64 :offset (* 64 index) :index index})
|
#js {:length 64 :offset (* 64 index) :index index})
|
||||||
|
|
|
@ -1822,5 +1822,7 @@
|
||||||
"membership": "Membership",
|
"membership": "Membership",
|
||||||
"jump-to": "Jump to",
|
"jump-to": "Jump to",
|
||||||
"blank-messages-text": "Your messages will be here",
|
"blank-messages-text": "Your messages will be here",
|
||||||
"groups": "Groups"
|
"groups": "Groups",
|
||||||
|
"shell-placeholder-title": "Your apps will run here",
|
||||||
|
"shell-placeholder-subtitle": "Open tabs of your communities, messages,\nwallet account and browser windows"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue