Use new component to animate headers
fix header title spacing Remove translate animation Add press for profile header Rebase Attempt to fix e2e Add back button accessibility-label Signed-off-by: Gheorghe Pinzaru <feross95@gmail.com>
This commit is contained in:
parent
01452794a1
commit
d35deefcb5
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
(defn header-wrapper-style [{:keys [value offset]}]
|
(defn header-wrapper-style [{:keys [value offset]}]
|
||||||
(merge
|
(merge
|
||||||
{:background-color :white}
|
{:background-color (:ui-background @colors/theme)}
|
||||||
(when (and offset platform/android?)
|
(when (and offset platform/android?)
|
||||||
{:elevation (animated/interpolate
|
{:elevation (animated/interpolate
|
||||||
value
|
value
|
||||||
|
@ -24,51 +24,55 @@
|
||||||
:outputRange [0 1]
|
:outputRange [0 1]
|
||||||
:extrapolate (:clamp animated/extrapolate)})
|
:extrapolate (:clamp animated/extrapolate)})
|
||||||
:shadow-radius 16
|
:shadow-radius 16
|
||||||
:z-index 2
|
|
||||||
:shadow-color (:shadow-01 @colors/theme)
|
:shadow-color (:shadow-01 @colors/theme)
|
||||||
:shadow-offset {:width 0 :height 4}})))
|
:shadow-offset {:width 0 :height 4}})))
|
||||||
|
|
||||||
(defn header-opened-style [{:keys [value offset]}]
|
(defn title-style [layout]
|
||||||
(merge
|
{:flex 1
|
||||||
{:position :absolute
|
:justify-content :center
|
||||||
:top 0
|
:padding-right (get-in layout [:right :width])})
|
||||||
:left 0
|
|
||||||
:right 0}
|
|
||||||
(when offset
|
|
||||||
{:transform [{:translateY
|
|
||||||
(animated/interpolate
|
|
||||||
value
|
|
||||||
{:inputRange [0 offset]
|
|
||||||
:outputRange [0 (- header/header-height)]
|
|
||||||
:extrapolateRight (:clamp animated/extrapolate)})}]})))
|
|
||||||
|
|
||||||
(defn header-container []
|
(defn header-container []
|
||||||
(let [y (animated/value 0)
|
(let [y (animated/value 0)
|
||||||
on-scroll (animated/on-scroll {:y y})
|
animation-value (animated/value 0)
|
||||||
layout (reagent/atom {})
|
animation (animated/with-timing
|
||||||
offset (reagent/atom 0)
|
animation-value
|
||||||
on-layout (fn [evt]
|
{:duration 250
|
||||||
(reset! offset (oget evt "nativeEvent" "layout" "height")))]
|
:easing (:ease-in animated/easings)})
|
||||||
|
on-scroll (animated/on-scroll {:y y})
|
||||||
|
layout (reagent/atom {})
|
||||||
|
offset (reagent/atom 0)
|
||||||
|
on-layout (fn [evt]
|
||||||
|
(reset! offset (oget evt "nativeEvent" "layout" "height")))]
|
||||||
(fn [{:keys [extended-header] :as props} & children]
|
(fn [{:keys [extended-header] :as props} & children]
|
||||||
[animated/view {:flex 1
|
[animated/view {:flex 1
|
||||||
:pointer-events :box-none}
|
:pointer-events :box-none}
|
||||||
|
[animated/code {:key (str @offset)
|
||||||
|
:exec (animated/cond*
|
||||||
|
(animated/and* (animated/greater-or-eq y @offset)
|
||||||
|
(animated/greater-or-eq y 1))
|
||||||
|
(animated/set animation-value 1)
|
||||||
|
(animated/set animation-value 0))}]
|
||||||
[animated/view {:pointer-events :box-none
|
[animated/view {:pointer-events :box-none
|
||||||
:style (header-wrapper-style {:value y
|
:style (header-wrapper-style {:value y
|
||||||
:offset @offset})}
|
:offset @offset})}
|
||||||
[header/header (merge {:get-layout (fn [el l] (swap! layout assoc el l))}
|
[header/header (merge
|
||||||
(dissoc props :extended-header))]
|
{:get-layout (fn [el l] (swap! layout assoc el l))
|
||||||
[rn/view {:pointer-events :box-none}
|
:title-component [animated/view {:style (title-style @layout)}
|
||||||
[animated/view {:style (header-opened-style {:value y
|
[extended-header {:value y
|
||||||
:offset @offset})
|
:animation animation
|
||||||
:pointer-events :box-none
|
:minimized true
|
||||||
:on-layout on-layout}
|
:offset @offset}]]
|
||||||
[extended-header {:value y
|
:title-align :left}
|
||||||
:layout @layout
|
(dissoc props :extended-header))]]
|
||||||
:offset @offset}]]]]
|
|
||||||
(into [animated/scroll-view {:on-scroll on-scroll
|
(into [animated/scroll-view {:on-scroll on-scroll
|
||||||
:scrollEventThrottle 1}
|
:scrollEventThrottle 1}
|
||||||
[rn/view {:pointer-events :box-none
|
[rn/view {:pointer-events :box-none}
|
||||||
:height @offset}]]
|
[animated/view {:pointer-events :box-none
|
||||||
|
:on-layout on-layout}
|
||||||
|
[extended-header {:value y
|
||||||
|
:animation animation
|
||||||
|
:offset @offset}]]]]
|
||||||
children)])))
|
children)])))
|
||||||
|
|
||||||
(defn header [{:keys [use-insets] :as props} & children]
|
(defn header [{:keys [use-insets] :as props} & children]
|
||||||
|
|
|
@ -46,11 +46,7 @@
|
||||||
|
|
||||||
(defn title-style [{:keys [left right]} title-align]
|
(defn title-style [{:keys [left right]} title-align]
|
||||||
(merge
|
(merge
|
||||||
{:position :absolute
|
absolute-fill
|
||||||
:justify-content :center
|
|
||||||
:top 0
|
|
||||||
:bottom 0}
|
|
||||||
(:tiny spacing/padding-horizontal)
|
|
||||||
(case title-align
|
(case title-align
|
||||||
:left {:left (:width left)
|
:left {:left (:width left)
|
||||||
:right (:width right)}
|
:right (:width right)}
|
||||||
|
@ -67,7 +63,7 @@
|
||||||
(:tiny spacing/padding-horizontal)))
|
(:tiny spacing/padding-horizontal)))
|
||||||
|
|
||||||
(def header-action-placeholder
|
(def header-action-placeholder
|
||||||
{:width (:tiny spacing/spacing)})
|
{:width (:base spacing/spacing)})
|
||||||
|
|
||||||
(def header-icon-touchable
|
(def header-icon-touchable
|
||||||
(merge
|
(merge
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
|
|
||||||
(defn- wrap-render-fn [f]
|
(defn- wrap-render-fn [f]
|
||||||
(fn [data]
|
(fn [data]
|
||||||
(reagent/as-element (f (.-item data) (.-index data) (.-separators data)))))
|
(reagent/as-element (f (.-item ^js data) (.-index ^js data) (.-separators ^js data)))))
|
||||||
|
|
||||||
(defn- wrap-key-fn [f]
|
(defn- wrap-key-fn [f]
|
||||||
(fn [data index]
|
(fn [data index]
|
||||||
|
|
|
@ -1,84 +0,0 @@
|
||||||
(ns status-im.ui.components.large-toolbar.styles
|
|
||||||
(:require [status-im.ui.components.colors :as colors]
|
|
||||||
[status-im.ui.components.animation :as animation]
|
|
||||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]
|
|
||||||
[status-im.utils.platform :as platform]))
|
|
||||||
|
|
||||||
(defonce toolbar-shadow-component-height
|
|
||||||
(let [status-bar-height (get platform/platform-specific :status-bar-default-height)]
|
|
||||||
(+ 50 toolbar.styles/toolbar-height (if (zero? status-bar-height) 50 status-bar-height))))
|
|
||||||
|
|
||||||
(defonce toolbar-statusbar-height
|
|
||||||
(+ (get platform/platform-specific :status-bar-default-height) toolbar.styles/toolbar-height))
|
|
||||||
|
|
||||||
(defn minimized-toolbar-fade-in [anim-opacity]
|
|
||||||
(animation/timing
|
|
||||||
anim-opacity
|
|
||||||
{:toValue 1
|
|
||||||
:duration 200
|
|
||||||
:easing (.-ease ^js animation/easing)
|
|
||||||
:useNativeDriver true}))
|
|
||||||
|
|
||||||
(defn minimized-toolbar-fade-out [anim-opacity]
|
|
||||||
(animation/timing
|
|
||||||
anim-opacity
|
|
||||||
{:toValue 0
|
|
||||||
:duration 200
|
|
||||||
:easing (.-ease ^js animation/easing)
|
|
||||||
:useNativeDriver true}))
|
|
||||||
|
|
||||||
(defn- ios-shadow-opacity-anim [scroll-y]
|
|
||||||
(if platform/ios?
|
|
||||||
(animation/interpolate scroll-y
|
|
||||||
{:inputRange [0 toolbar-statusbar-height]
|
|
||||||
:outputRange [0 1]
|
|
||||||
:extrapolate "clamp"})
|
|
||||||
0))
|
|
||||||
|
|
||||||
(defn- android-shadow-elevation-anim [scroll-y]
|
|
||||||
(if platform/android?
|
|
||||||
(animation/interpolate scroll-y
|
|
||||||
{:inputRange [0 toolbar-statusbar-height]
|
|
||||||
:outputRange [0 9]
|
|
||||||
:extrapolate "clamp"})
|
|
||||||
0))
|
|
||||||
|
|
||||||
(defn bottom-border-opacity-anim [scroll-y]
|
|
||||||
(animation/interpolate scroll-y
|
|
||||||
{:inputRange [0 toolbar-statusbar-height]
|
|
||||||
:outputRange [1 0]
|
|
||||||
:extrapolate "clamp"}))
|
|
||||||
|
|
||||||
(defn animated-content-wrapper [anim-opacity]
|
|
||||||
{:flex 1
|
|
||||||
:align-self :stretch
|
|
||||||
:opacity anim-opacity})
|
|
||||||
|
|
||||||
(def minimized-toolbar
|
|
||||||
{:z-index 100
|
|
||||||
:elevation 9})
|
|
||||||
|
|
||||||
(defn flat-list-with-large-header-bottom [scroll-y]
|
|
||||||
{:height 16
|
|
||||||
:opacity (bottom-border-opacity-anim scroll-y)
|
|
||||||
:border-bottom-width 1
|
|
||||||
:border-bottom-color colors/gray-lighter})
|
|
||||||
|
|
||||||
(defn flat-list-with-large-header-shadow [window-width scroll-y]
|
|
||||||
(cond-> {:flex 1
|
|
||||||
:align-self :stretch
|
|
||||||
:position :absolute
|
|
||||||
:height toolbar-shadow-component-height
|
|
||||||
:width window-width
|
|
||||||
:top (- toolbar-shadow-component-height)
|
|
||||||
:shadow-radius 8
|
|
||||||
:shadow-offset {:width 0 :height 2}
|
|
||||||
:shadow-opacity 1
|
|
||||||
:shadow-color "rgba(0, 9, 26, 0.12)"
|
|
||||||
:elevation (android-shadow-elevation-anim scroll-y)
|
|
||||||
:background-color colors/white}
|
|
||||||
platform/ios?
|
|
||||||
(assoc :opacity (ios-shadow-opacity-anim scroll-y))))
|
|
||||||
|
|
||||||
(def flat-list
|
|
||||||
{:z-index -1})
|
|
|
@ -1,105 +0,0 @@
|
||||||
(ns status-im.ui.components.large-toolbar.view
|
|
||||||
(:require [reagent.core :as reagent]
|
|
||||||
[status-im.ui.components.list.views :as list.views]
|
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[status-im.ui.components.toolbar.view :as toolbar]
|
|
||||||
[status-im.ui.components.large-toolbar.styles :as styles]
|
|
||||||
[status-im.ui.components.animation :as animation])
|
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
|
||||||
|
|
||||||
;; header-in-toolbar - component - small header in toolbar
|
|
||||||
;; nav-item - component/nil - if nav-item like back button is needed, else nil
|
|
||||||
;; action-items - status-im.ui.components.toolbar.view/actions
|
|
||||||
(defn minimized-toolbar [header-in-toolbar nav-item action-items anim-opacity]
|
|
||||||
(let [has-nav? (boolean nav-item)]
|
|
||||||
[toolbar/toolbar
|
|
||||||
{:transparent? true
|
|
||||||
:style styles/minimized-toolbar}
|
|
||||||
nav-item
|
|
||||||
[react/animated-view
|
|
||||||
{:style (cond-> (styles/animated-content-wrapper anim-opacity)
|
|
||||||
(false? has-nav?)
|
|
||||||
(assoc :margin-left -40 :margin-right 40))}
|
|
||||||
header-in-toolbar]
|
|
||||||
action-items]))
|
|
||||||
|
|
||||||
;; header - component that serves as large header without any top/bottom padding
|
|
||||||
;; top(4px high) and bottom(16px high and with border) padding
|
|
||||||
;; are assumed to be constant
|
|
||||||
;; this is wrapped with padding components and merged with content
|
|
||||||
;; content - vector - of the rest(from header) of the list components
|
|
||||||
;; wrapped header and content form the data prop of flat-list
|
|
||||||
;; list-ref - atom - a reference to flat-list for the purpose of invoking its
|
|
||||||
;; methods
|
|
||||||
;; scroll-y - animated value tracking the y scoll of the main content in flat-list-view
|
|
||||||
(views/defview flat-list-with-large-header [header content list-ref scroll-y]
|
|
||||||
(views/letsubs [window-width [:dimensions/window-width]]
|
|
||||||
(let [header-top-padding [react/view {:height 4}]
|
|
||||||
;; header bottom padding with border-bottom
|
|
||||||
;; fades out as it approaches toolbar shadow
|
|
||||||
header-bottom [react/animated-view
|
|
||||||
{:style (styles/flat-list-with-large-header-bottom scroll-y)}]
|
|
||||||
wrapped-data (into [header-top-padding header header-bottom] content)]
|
|
||||||
[react/view {:flex 1}
|
|
||||||
;; toolbar shadow
|
|
||||||
[react/animated-view
|
|
||||||
{:style (styles/flat-list-with-large-header-shadow window-width scroll-y)}]
|
|
||||||
|
|
||||||
[list.views/flat-list
|
|
||||||
{:style styles/flat-list
|
|
||||||
:data wrapped-data
|
|
||||||
:initial-num-to-render 3
|
|
||||||
:ref #(when % (reset! list-ref (.getNode ^js %)))
|
|
||||||
:render-fn list.views/flat-list-generic-render-fn
|
|
||||||
:key-fn (fn [item idx] (str idx))
|
|
||||||
:scrollEventThrottle 16
|
|
||||||
:on-scroll (animation/event
|
|
||||||
[{:nativeEvent {:contentOffset {:y scroll-y}}}]
|
|
||||||
{:useNativeDriver true})
|
|
||||||
:keyboard-should-persist-taps :handled}
|
|
||||||
{:animated? true}]])))
|
|
||||||
|
|
||||||
(defn generate-view
|
|
||||||
"main function which generates views.
|
|
||||||
- it will generate and return back:
|
|
||||||
- minimized-toolbar
|
|
||||||
- flat-list-with-large-header"
|
|
||||||
[header-in-toolbar nav-item toolbar-action-items header content list-ref]
|
|
||||||
(let [to-hide (reagent/atom true)
|
|
||||||
anim-opacity (animation/create-value 0)
|
|
||||||
scroll-y (animation/create-value 0)]
|
|
||||||
(animation/add-listener scroll-y (fn [^js anim]
|
|
||||||
(cond
|
|
||||||
(and (>= (.-value anim) 40) (not @to-hide))
|
|
||||||
(animation/start
|
|
||||||
(styles/minimized-toolbar-fade-in anim-opacity)
|
|
||||||
#(reset! to-hide true))
|
|
||||||
|
|
||||||
(and (< (.-value anim) 40) @to-hide)
|
|
||||||
(animation/start
|
|
||||||
(styles/minimized-toolbar-fade-out anim-opacity)
|
|
||||||
#(reset! to-hide false)))))
|
|
||||||
{:minimized-toolbar [minimized-toolbar header-in-toolbar nav-item toolbar-action-items anim-opacity]
|
|
||||||
:content-with-header [flat-list-with-large-header header content list-ref scroll-y]}))
|
|
||||||
|
|
||||||
(defn add-listener [anim-opacity scroll-y]
|
|
||||||
(let [to-hide (atom false)]
|
|
||||||
(animation/add-listener
|
|
||||||
scroll-y
|
|
||||||
(fn [^js anim]
|
|
||||||
(cond
|
|
||||||
(and (>= (.-value anim) 40) (not @to-hide))
|
|
||||||
(animation/start
|
|
||||||
(styles/minimized-toolbar-fade-in anim-opacity)
|
|
||||||
#(reset! to-hide true))
|
|
||||||
|
|
||||||
(and (< (.-value anim) 40) @to-hide)
|
|
||||||
(animation/start
|
|
||||||
(styles/minimized-toolbar-fade-out anim-opacity)
|
|
||||||
#(reset! to-hide false)))))))
|
|
||||||
|
|
||||||
(defn minimized-toolbar-handler [header-in-toolbar nav-item toolbar-action-items anim-opacity]
|
|
||||||
[minimized-toolbar header-in-toolbar nav-item toolbar-action-items anim-opacity])
|
|
||||||
|
|
||||||
(defn flat-list-with-header-handler [header content list-ref scroll-y]
|
|
||||||
[flat-list-with-large-header header content list-ref scroll-y])
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
(ns status-im.ui.components.profile-header.view
|
||||||
|
(:require [quo.core :as quo]
|
||||||
|
[quo.animated :as animated]
|
||||||
|
[quo.design-system.spacing :as spacing]
|
||||||
|
[quo.design-system.colors :as colors]
|
||||||
|
[quo.react-native :as rn]
|
||||||
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
|
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]))
|
||||||
|
|
||||||
|
(def avatar-extended-size 64)
|
||||||
|
(def avatar-minimized-size 40)
|
||||||
|
(def subtitle-margin 4)
|
||||||
|
|
||||||
|
(defn container-style [{:keys [animation minimized]}]
|
||||||
|
(merge {:flex-direction :row
|
||||||
|
:align-items :center}
|
||||||
|
(if-not minimized
|
||||||
|
(:base spacing/padding-horizontal)
|
||||||
|
{:opacity animation})))
|
||||||
|
|
||||||
|
(defn header-bottom-separator []
|
||||||
|
{:margin-bottom (:tiny spacing/spacing)
|
||||||
|
:height (:small spacing/spacing)
|
||||||
|
:border-bottom-width 1
|
||||||
|
:border-bottom-color (:ui-02 @colors/theme)})
|
||||||
|
|
||||||
|
(defn header-text []
|
||||||
|
{:padding-left (:base spacing/spacing)
|
||||||
|
:flex 1
|
||||||
|
:justify-content :center})
|
||||||
|
|
||||||
|
(defn header-subtitle [{:keys [minimized]}]
|
||||||
|
(merge {:padding-right (:large spacing/spacing)
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center}
|
||||||
|
(when-not minimized
|
||||||
|
{:padding-top subtitle-margin})))
|
||||||
|
|
||||||
|
(defn extended-header [{:keys [title photo color subtitle subtitle-icon on-press]}]
|
||||||
|
(fn [{:keys [animation minimized]}]
|
||||||
|
(let [wrapper (if on-press
|
||||||
|
[rn/touchable-opacity {:on-press on-press}]
|
||||||
|
[:<>])]
|
||||||
|
(into
|
||||||
|
wrapper
|
||||||
|
[[animated/view {:pointer-events :box-none}
|
||||||
|
[animated/view {:style (container-style {:animation animation
|
||||||
|
:minimized minimized})
|
||||||
|
:pointer-events :box-none}
|
||||||
|
[animated/view {:pointer-events :box-none}
|
||||||
|
[chat-icon.screen/profile-icon-view
|
||||||
|
photo title color nil
|
||||||
|
(if minimized avatar-minimized-size avatar-extended-size)
|
||||||
|
nil]]
|
||||||
|
[animated/view {:style (header-text)
|
||||||
|
:pointer-events :box-none}
|
||||||
|
[quo/text {:animated? true
|
||||||
|
:number-of-lines (if minimized 1 2)
|
||||||
|
:size (if minimized :base :x-large)
|
||||||
|
:weight :bold
|
||||||
|
:elipsize-mode :tail
|
||||||
|
:accessibility-role :text
|
||||||
|
:accessibility-label :default-username}
|
||||||
|
title]
|
||||||
|
(when subtitle
|
||||||
|
[animated/view {:style (header-subtitle {:minimized minimized})
|
||||||
|
:pointer-events :box-none}
|
||||||
|
(when subtitle-icon
|
||||||
|
[vector-icons/icon subtitle-icon {:color (:icon-02 @colors/theme)
|
||||||
|
:width 16
|
||||||
|
:height 16
|
||||||
|
:container-style {:margin-right 4}}])
|
||||||
|
[quo/text {:number-of-lines 1
|
||||||
|
:ellipsize-mode :middle
|
||||||
|
:size (if minimized :small :base)
|
||||||
|
:color :secondary}
|
||||||
|
subtitle]])]]
|
||||||
|
(when-not minimized
|
||||||
|
[animated/view {:pointer-events :none
|
||||||
|
:style (header-bottom-separator)}])]]))))
|
||||||
|
|
|
@ -1,103 +1,12 @@
|
||||||
(ns status-im.ui.screens.profile.components.views
|
(ns status-im.ui.screens.profile.components.views
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[re-frame.core :as re-frame]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[status-im.ui.components.common.common :as common]
|
[status-im.ui.components.common.common :as common]
|
||||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.utils.gfycat.core :as gfy]
|
|
||||||
[status-im.ui.screens.profile.user.sheet.views :as sheets]
|
|
||||||
[status-im.ui.screens.profile.components.styles :as styles]))
|
[status-im.ui.screens.profile.components.styles :as styles]))
|
||||||
|
|
||||||
(defn- names [{:keys [usernames public-key] :as contact}]
|
|
||||||
(let [generated-name (when public-key (gfy/generate-gfy public-key))]
|
|
||||||
[react/view styles/profile-header-name-container-with-subtitle
|
|
||||||
[react/text {:style styles/profile-name-text-with-subtitle
|
|
||||||
:number-of-lines 2
|
|
||||||
:ellipsize-mode :tail}
|
|
||||||
(multiaccounts/displayed-name contact)]
|
|
||||||
[react/text {:style styles/profile-three-words
|
|
||||||
:number-of-lines 1}
|
|
||||||
(if (seq usernames)
|
|
||||||
generated-name
|
|
||||||
public-key)]]))
|
|
||||||
|
|
||||||
(defn chat-key-popover [public-key ens-name]
|
|
||||||
(re-frame/dispatch [:show-popover
|
|
||||||
{:view :share-chat-key
|
|
||||||
:address public-key
|
|
||||||
:ens-name ens-name}]))
|
|
||||||
|
|
||||||
(defn- profile-header-display
|
|
||||||
[{:keys [public-key preferred-name ens-name] :as contact}
|
|
||||||
allow-icon-change? include-remove-action?]
|
|
||||||
[react/touchable-opacity
|
|
||||||
{:on-press #(chat-key-popover public-key (or ens-name
|
|
||||||
preferred-name))}
|
|
||||||
[react/view (merge styles/profile-header-display {:padding-horizontal 16})
|
|
||||||
(if allow-icon-change?
|
|
||||||
[react/view {:align-items :center
|
|
||||||
:align-self :stretch
|
|
||||||
:justify-content :center}
|
|
||||||
[react/touchable-highlight
|
|
||||||
{:accessibility-label :edit-profile-photo-button
|
|
||||||
:on-press
|
|
||||||
#(re-frame/dispatch
|
|
||||||
[:bottom-sheet/show-sheet
|
|
||||||
{:content (sheets/profile-icon-actions include-remove-action?)
|
|
||||||
:content-height (if include-remove-action? 192 128)}])}
|
|
||||||
[react/view
|
|
||||||
[react/view {:background-color colors/white
|
|
||||||
:border-radius 15
|
|
||||||
:width 30
|
|
||||||
:height 30
|
|
||||||
:justify-content :center
|
|
||||||
:align-items :center
|
|
||||||
:position :absolute
|
|
||||||
:z-index 1
|
|
||||||
:top -5
|
|
||||||
:right -5}
|
|
||||||
[react/view {:background-color colors/blue
|
|
||||||
:border-radius 12
|
|
||||||
:width 24
|
|
||||||
:height 24
|
|
||||||
:justify-content :center
|
|
||||||
:align-items :center}
|
|
||||||
[vector-icons/icon :tiny-edit {:color colors/white
|
|
||||||
:width 16
|
|
||||||
:height 16}]]]
|
|
||||||
[chat-icon.screen/my-profile-icon {:multiaccount contact
|
|
||||||
:edit? false}]]]]
|
|
||||||
;; else
|
|
||||||
[chat-icon.screen/my-profile-icon {:multiaccount contact
|
|
||||||
:edit? false}])
|
|
||||||
[names contact]]])
|
|
||||||
|
|
||||||
(defn group-header-display [{:keys [chat-name color contacts]}]
|
|
||||||
[react/view (merge styles/profile-header-display {:padding-horizontal 16})
|
|
||||||
[chat-icon.screen/profile-icon-view nil chat-name color nil 64 nil]
|
|
||||||
[react/view styles/profile-header-name-container
|
|
||||||
[react/text {:style styles/profile-name-text
|
|
||||||
:number-of-lines 2
|
|
||||||
:ellipsize-mode :tail}
|
|
||||||
chat-name]
|
|
||||||
[react/view {:style {:flex-direction :row
|
|
||||||
:align-items :center}}
|
|
||||||
[vector-icons/icon :icons/tiny-group {:color colors/gray
|
|
||||||
:width 16
|
|
||||||
:height 16
|
|
||||||
:container-style {:margin-right 4}}]
|
|
||||||
[react/text {:style {:line-height 22
|
|
||||||
:color colors/gray}}
|
|
||||||
(i18n/label :t/members-count {:count (count contacts)})]]]])
|
|
||||||
|
|
||||||
(defn profile-header
|
|
||||||
[{:keys [contact allow-icon-change? include-remove-action?]}]
|
|
||||||
[profile-header-display contact allow-icon-change? include-remove-action?])
|
|
||||||
|
|
||||||
;; settings items elements
|
;; settings items elements
|
||||||
|
|
||||||
(defn settings-item
|
(defn settings-item
|
||||||
|
|
|
@ -6,15 +6,14 @@
|
||||||
[status-im.utils.utils :as utils]
|
[status-im.utils.utils :as utils]
|
||||||
[status-im.ui.components.icons.vector-icons :as icons]
|
[status-im.ui.components.icons.vector-icons :as icons]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.large-toolbar.view :as large-toolbar]
|
|
||||||
[status-im.ui.components.toolbar.view :as toolbar]
|
|
||||||
[status-im.ui.screens.profile.components.views :as profile.components]
|
|
||||||
[status-im.ui.screens.profile.contact.styles :as styles]
|
[status-im.ui.screens.profile.contact.styles :as styles]
|
||||||
[status-im.ui.components.list-item.views :as list-item]
|
[status-im.ui.components.list-item.views :as list-item]
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
||||||
[status-im.ui.screens.profile.components.sheets :as sheets]
|
[status-im.ui.screens.profile.components.sheets :as sheets]
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
[status-im.ui.components.profile-header.view :as profile-header]
|
||||||
[status-im.multiaccounts.core :as multiaccounts])
|
[status-im.utils.gfycat.core :as gfy]
|
||||||
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
|
[quo.core :as quo])
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(defn actions
|
(defn actions
|
||||||
|
@ -89,71 +88,44 @@
|
||||||
(i18n/label :t/unblock-contact)
|
(i18n/label :t/unblock-contact)
|
||||||
(i18n/label :t/block-contact))]])
|
(i18n/label :t/block-contact))]])
|
||||||
|
|
||||||
(defn- header-in-toolbar [{:keys [public-key ens-name] :as account}]
|
|
||||||
(let [displayed-name (multiaccounts/displayed-name account)]
|
|
||||||
[react/touchable-opacity {:on-press #(profile.components/chat-key-popover public-key ens-name)
|
|
||||||
:style {:flex 1
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center
|
|
||||||
:align-self :stretch}}
|
|
||||||
;;TODO this should be done in a subscription
|
|
||||||
[photos/photo (multiaccounts/displayed-photo account)
|
|
||||||
{:size 40}]
|
|
||||||
[react/text {:style {:typography :title-bold
|
|
||||||
:line-height 21
|
|
||||||
:margin-right 40
|
|
||||||
:margin-left 16
|
|
||||||
:text-align :left}
|
|
||||||
:accessibility-label :account-name}
|
|
||||||
displayed-name]]))
|
|
||||||
|
|
||||||
(defn- header [account]
|
|
||||||
[profile.components/profile-header
|
|
||||||
{:contact account
|
|
||||||
:allow-icon-change? false
|
|
||||||
:include-remove-action? false}])
|
|
||||||
|
|
||||||
(defn- toolbar-action-items [public-key ens-name]
|
|
||||||
[toolbar/actions
|
|
||||||
[{:icon :main-icons/share
|
|
||||||
:icon-opts {:width 24
|
|
||||||
:height 24}
|
|
||||||
:handler #(profile.components/chat-key-popover public-key ens-name)}]])
|
|
||||||
|
|
||||||
;;TO-DO Rework generate-view to use 3 functions from large-toolbar
|
|
||||||
(views/defview profile []
|
(views/defview profile []
|
||||||
(views/letsubs [list-ref (reagent/atom nil)
|
(views/letsubs [{:keys [ens-verified name public-key]
|
||||||
{:keys [ens-verified name public-key] :as contact} [:contacts/current-contact]]
|
:as contact} [:contacts/current-contact]]
|
||||||
(when contact
|
(let [on-share #(re-frame/dispatch [:show-popover (merge
|
||||||
(let [ens-name (when (and ens-verified name) name)
|
{:view :share-chat-key
|
||||||
contact (cond-> contact
|
:address public-key}
|
||||||
ens-name
|
(when (and ens-verified name)
|
||||||
(assoc :usernames [ens-name]
|
{:ens-name name}))])]
|
||||||
:ens-name ens-name))
|
(when contact
|
||||||
header-in-toolbar (header-in-toolbar contact)
|
|
||||||
header (header contact)
|
|
||||||
content
|
|
||||||
[[react/view {:padding-top 12}
|
|
||||||
(for [{:keys [label subtext accessibility-label icon action disabled?]} (actions contact)]
|
|
||||||
[list-item/list-item {:theme :action
|
|
||||||
:title label
|
|
||||||
:subtitle subtext
|
|
||||||
:icon icon
|
|
||||||
:accessibility-label accessibility-label
|
|
||||||
:disabled? disabled?
|
|
||||||
:on-press action}])]
|
|
||||||
[react/view styles/contact-profile-details-container
|
|
||||||
[profile-details contact]]
|
|
||||||
[block-contact-action contact]]
|
|
||||||
generated-view (large-toolbar/generate-view
|
|
||||||
header-in-toolbar
|
|
||||||
toolbar/default-nav-back
|
|
||||||
(toolbar-action-items public-key ens-name)
|
|
||||||
header
|
|
||||||
content
|
|
||||||
list-ref)]
|
|
||||||
[react/view
|
[react/view
|
||||||
{:style
|
{:style
|
||||||
(merge {:flex 1})}
|
(merge {:flex 1})}
|
||||||
(:minimized-toolbar generated-view)
|
[quo/animated-header
|
||||||
(:content-with-header generated-view)]))))
|
{:use-insets true
|
||||||
|
:right-accessories [{:icon :main-icons/share
|
||||||
|
:on-press on-share}]
|
||||||
|
:left-accessories [{:icon :main-icons/back
|
||||||
|
:accessibility-label :back-button
|
||||||
|
:on-press #(re-frame/dispatch [:navigate-back])}]
|
||||||
|
:extended-header (profile-header/extended-header
|
||||||
|
{:on-press on-share
|
||||||
|
:title (multiaccounts/displayed-name contact)
|
||||||
|
:photo (multiaccounts/displayed-photo contact)
|
||||||
|
:subtitle (if (and ens-verified public-key)
|
||||||
|
(gfy/generate-gfy public-key)
|
||||||
|
public-key)})}
|
||||||
|
|
||||||
|
[react/view {:padding-top 12}
|
||||||
|
(for [{:keys [label subtext accessibility-label icon action disabled?]} (actions contact)]
|
||||||
|
[list-item/list-item {:theme :action
|
||||||
|
:title label
|
||||||
|
:subtitle subtext
|
||||||
|
:icon icon
|
||||||
|
:accessibility-label accessibility-label
|
||||||
|
:disabled? disabled?
|
||||||
|
:on-press action}])]
|
||||||
|
[react/view styles/contact-profile-details-container
|
||||||
|
[profile-details (cond-> contact
|
||||||
|
(and ens-verified name)
|
||||||
|
(assoc :ens-name name))]]
|
||||||
|
[block-contact-action contact]]]))))
|
||||||
|
|
|
@ -14,16 +14,9 @@
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.ui.components.list-item.views :as list-item]
|
[quo.core :as quo]
|
||||||
[status-im.ui.components.topbar :as topbar]))
|
[status-im.ui.components.profile-header.view :as profile-header]
|
||||||
|
[status-im.ui.components.list-item.views :as list-item]))
|
||||||
(defn group-chat-profile-toolbar [admin?]
|
|
||||||
[topbar/topbar
|
|
||||||
(when admin?
|
|
||||||
{:accessories
|
|
||||||
[{:icon :icons/edit
|
|
||||||
:accessibility-label :edit-button
|
|
||||||
:handler #(re-frame/dispatch [:navigate-to :edit-group-chat-name])}]})])
|
|
||||||
|
|
||||||
(defn member-sheet [chat-id member us-admin?]
|
(defn member-sheet [chat-id member us-admin?]
|
||||||
[react/view
|
[react/view
|
||||||
|
@ -92,24 +85,29 @@
|
||||||
[chat-group-members-view chat-id admin? current-pk]])
|
[chat-group-members-view chat-id admin? current-pk]])
|
||||||
|
|
||||||
(defview group-chat-profile []
|
(defview group-chat-profile []
|
||||||
(letsubs [{:keys [admins chat-id joined?] :as current-chat} [:chats/current-chat]
|
(letsubs [{:keys [admins chat-id joined? chat-name color contacts] :as current-chat} [:chats/current-chat]
|
||||||
members [:contacts/current-chat-contacts]
|
members [:contacts/current-chat-contacts]
|
||||||
changed-chat [:group-chat-profile/profile]
|
|
||||||
current-pk [:multiaccount/public-key]]
|
current-pk [:multiaccount/public-key]]
|
||||||
(when current-chat
|
(when current-chat
|
||||||
(let [shown-chat (merge current-chat changed-chat)
|
(let [admin? (get admins current-pk)
|
||||||
admin? (get admins current-pk)
|
|
||||||
allow-adding-members? (and admin? joined?
|
allow-adding-members? (and admin? joined?
|
||||||
(< (count members) constants/max-group-chat-participants))]
|
(< (count members) constants/max-group-chat-participants))]
|
||||||
[react/view profile.components.styles/profile
|
[react/view profile.components.styles/profile
|
||||||
[group-chat-profile-toolbar (and admin? joined?)]
|
[quo/animated-header
|
||||||
[react/scroll-view
|
{:use-insets true
|
||||||
|
:left-accessories [{:icon :main-icons/back
|
||||||
|
:accessibility-label :back-button
|
||||||
|
:on-press #(re-frame/dispatch [:navigate-back])}]
|
||||||
|
:right-accessories (when (and admin? joined?)
|
||||||
|
[{:icon :icons/edit
|
||||||
|
:accessibility-label :edit-button
|
||||||
|
:on-press #(re-frame/dispatch [:navigate-to :edit-group-chat-name])}])
|
||||||
|
:extended-header (profile-header/extended-header
|
||||||
|
{:title chat-name
|
||||||
|
:color color
|
||||||
|
:subtitle (i18n/label :t/members-count {:count (count contacts)})
|
||||||
|
:subtitle-icon :icons/tiny-group})}
|
||||||
[react/view profile.components.styles/profile-form
|
[react/view profile.components.styles/profile-form
|
||||||
[react/view {:style {:border-bottom-width 1
|
|
||||||
:padding-bottom 15
|
|
||||||
:margin-bottom 8
|
|
||||||
:border-bottom-color colors/gray-lighter}}
|
|
||||||
[profile.components/group-header-display shown-chat]]
|
|
||||||
(when joined?
|
(when joined?
|
||||||
[list-item/list-item
|
[list-item/list-item
|
||||||
{:theme :action
|
{:theme :action
|
||||||
|
|
|
@ -2,24 +2,22 @@
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.ui.components.button :as button]
|
[status-im.ui.components.button :as button]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]
|
||||||
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.ui.components.copyable-text :as copyable-text]
|
[status-im.ui.components.copyable-text :as copyable-text]
|
||||||
[status-im.ui.components.large-toolbar.view :as large-toolbar]
|
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.ui.components.list.views :as list.views]
|
[status-im.ui.components.list.views :as list.views]
|
||||||
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
|
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.toolbar.view :as toolbar]
|
|
||||||
[status-im.ui.screens.chat.photos :as photos]
|
|
||||||
[status-im.ui.screens.profile.components.views :as profile.components]
|
|
||||||
[status-im.ui.screens.profile.user.styles :as styles]
|
[status-im.ui.screens.profile.user.styles :as styles]
|
||||||
[status-im.utils.platform :as platform]
|
[status-im.utils.platform :as platform]
|
||||||
[status-im.utils.config :as config]
|
[status-im.utils.config :as config]
|
||||||
|
[quo.core :as quo]
|
||||||
|
[status-im.utils.gfycat.core :as gfy]
|
||||||
[status-im.utils.universal-links.core :as universal-links]
|
[status-im.utils.universal-links.core :as universal-links]
|
||||||
[status-im.ui.components.animation :as animation])
|
[status-im.ui.components.profile-header.view :as profile-header])
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(views/defview share-chat-key []
|
(views/defview share-chat-key []
|
||||||
|
@ -61,38 +59,6 @@
|
||||||
;:icon :main-icons/link
|
;:icon :main-icons/link
|
||||||
:accessibility-label :share-my-contact-code-button}]]])))
|
:accessibility-label :share-my-contact-code-button}]]])))
|
||||||
|
|
||||||
(defn- header [account photo-added?]
|
|
||||||
[profile.components/profile-header
|
|
||||||
{:contact account
|
|
||||||
;;set to true if we want to re-enable custom icon
|
|
||||||
:allow-icon-change? false
|
|
||||||
:include-remove-action? photo-added?}])
|
|
||||||
|
|
||||||
(defn- header-in-toolbar [{:keys [public-key preferred-name] :as account}]
|
|
||||||
(let [displayed-name (multiaccounts/displayed-name account)]
|
|
||||||
[react/touchable-opacity
|
|
||||||
{:on-press #(profile.components/chat-key-popover public-key preferred-name)
|
|
||||||
:style {:flex 1}}
|
|
||||||
[react/view {:style {:flex 1
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center
|
|
||||||
:align-self :stretch}}
|
|
||||||
;;TODO this should be done in a subscription
|
|
||||||
[photos/photo (multiaccounts/displayed-photo account) {:size 40}]
|
|
||||||
[react/text {:style {:typography :title-bold
|
|
||||||
:line-height 21
|
|
||||||
:margin-right 40
|
|
||||||
:margin-left 16
|
|
||||||
:text-align :left}}
|
|
||||||
displayed-name]]]))
|
|
||||||
|
|
||||||
(defn- toolbar-action-items [public-key preferred-name]
|
|
||||||
[toolbar/actions
|
|
||||||
[{:icon :main-icons/share
|
|
||||||
:icon-opts {:width 24
|
|
||||||
:height 24}
|
|
||||||
:handler #(profile.components/chat-key-popover public-key preferred-name)}]])
|
|
||||||
|
|
||||||
(defn tribute-to-talk-item
|
(defn tribute-to-talk-item
|
||||||
[opts]
|
[opts]
|
||||||
[list.views/big-list-item
|
[list.views/big-list-item
|
||||||
|
@ -204,40 +170,44 @@
|
||||||
:on-press
|
:on-press
|
||||||
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}])
|
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}])
|
||||||
|
|
||||||
(defn minimized-toolbar-handler [anim-opacity]
|
(defn content []
|
||||||
(let [{:keys [public-key preferred-name]
|
|
||||||
:as multiaccount} @(re-frame/subscribe [:multiaccount])]
|
|
||||||
[large-toolbar/minimized-toolbar-handler
|
|
||||||
(header-in-toolbar multiaccount)
|
|
||||||
nil
|
|
||||||
(toolbar-action-items public-key preferred-name)
|
|
||||||
anim-opacity]))
|
|
||||||
|
|
||||||
(defn content-with-header [list-ref scroll-y]
|
|
||||||
(let [{:keys [preferred-name
|
(let [{:keys [preferred-name
|
||||||
mnemonic
|
mnemonic
|
||||||
keycard-pairing
|
keycard-pairing
|
||||||
notifications-enabled?]
|
notifications-enabled?]}
|
||||||
:as multiaccount} @(re-frame/subscribe [:multiaccount])
|
@(re-frame/subscribe [:multiaccount])
|
||||||
|
|
||||||
active-contacts-count @(re-frame/subscribe [:contacts/active-count])
|
active-contacts-count @(re-frame/subscribe [:contacts/active-count])
|
||||||
tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile])
|
tribute-to-talk @(re-frame/subscribe [:tribute-to-talk/profile])
|
||||||
registrar @(re-frame/subscribe [:ens.stateofus/registrar])
|
registrar @(re-frame/subscribe [:ens.stateofus/registrar])]
|
||||||
photo-added? @(re-frame/subscribe [:profile/photo-added?])]
|
(flat-list-content
|
||||||
[large-toolbar/flat-list-with-header-handler
|
preferred-name registrar tribute-to-talk
|
||||||
(header multiaccount photo-added?)
|
active-contacts-count mnemonic
|
||||||
(flat-list-content
|
keycard-pairing notifications-enabled?)))
|
||||||
preferred-name registrar tribute-to-talk
|
|
||||||
active-contacts-count mnemonic
|
|
||||||
keycard-pairing notifications-enabled?)
|
|
||||||
list-ref
|
|
||||||
scroll-y]))
|
|
||||||
|
|
||||||
(defn my-profile []
|
(defn my-profile []
|
||||||
(let [list-ref (reagent/atom nil)
|
(fn []
|
||||||
anim-opacity (animation/create-value 0)
|
(let [{:keys [public-key ens-verified preferred-name]
|
||||||
scroll-y (animation/create-value 0)]
|
:as account} @(re-frame/subscribe [:multiaccount])
|
||||||
(large-toolbar/add-listener anim-opacity scroll-y)
|
on-share #(re-frame/dispatch [:show-popover
|
||||||
(fn []
|
{:view :share-chat-key
|
||||||
|
:address public-key
|
||||||
|
:ens-name preferred-name}])]
|
||||||
[react/view {:style {:flex 1}}
|
[react/view {:style {:flex 1}}
|
||||||
[minimized-toolbar-handler anim-opacity]
|
[quo/animated-header
|
||||||
[content-with-header list-ref scroll-y]])))
|
{:right-accessories [{:icon :main-icons/share
|
||||||
|
:on-press on-share}]
|
||||||
|
:use-insets true
|
||||||
|
:extended-header (profile-header/extended-header
|
||||||
|
{:on-press on-share
|
||||||
|
:title (multiaccounts/displayed-name account)
|
||||||
|
:photo (multiaccounts/displayed-photo account)
|
||||||
|
:subtitle (if (and ens-verified public-key)
|
||||||
|
(gfy/generate-gfy public-key)
|
||||||
|
public-key)})}
|
||||||
|
[list.views/flat-list
|
||||||
|
{:data (content)
|
||||||
|
:initial-num-to-render 3
|
||||||
|
:render-fn list.views/flat-list-generic-render-fn
|
||||||
|
:key-fn (fn [_ idx] (str idx))
|
||||||
|
:keyboard-should-persist-taps :handled}]]])))
|
||||||
|
|
|
@ -22,8 +22,10 @@
|
||||||
{:name :chat
|
{:name :chat
|
||||||
:component chat/chat}
|
:component chat/chat}
|
||||||
{:name :profile
|
{:name :profile
|
||||||
|
:insets {:top false}
|
||||||
:component profile.contact/profile}
|
:component profile.contact/profile}
|
||||||
{:name :group-chat-profile
|
{:name :group-chat-profile
|
||||||
|
:insets {:top false}
|
||||||
:component profile.group-chat/group-chat-profile}
|
:component profile.group-chat/group-chat-profile}
|
||||||
{:name :stickers
|
{:name :stickers
|
||||||
:component stickers/packs}
|
:component stickers/packs}
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
[stack {:initial-route-name :my-profile
|
[stack {:initial-route-name :my-profile
|
||||||
:header-mode :none}
|
:header-mode :none}
|
||||||
[{:name :my-profile
|
[{:name :my-profile
|
||||||
|
:insets {:top false}
|
||||||
:style {:padding-bottom tabbar.styles/tabs-diff}
|
:style {:padding-bottom tabbar.styles/tabs-diff}
|
||||||
:component profile.user/my-profile}
|
:component profile.user/my-profile}
|
||||||
{:name :contacts-list
|
{:name :contacts-list
|
||||||
|
@ -66,6 +67,7 @@
|
||||||
{:name :blocked-users-list
|
{:name :blocked-users-list
|
||||||
:component contacts-list/blocked-users-list}
|
:component contacts-list/blocked-users-list}
|
||||||
{:name :profile
|
{:name :profile
|
||||||
|
:insets {:top false}
|
||||||
:component profile.contact/profile}
|
:component profile.contact/profile}
|
||||||
{:name :profile-photo-capture
|
{:name :profile-photo-capture
|
||||||
:component photo-capture/profile-photo-capture}
|
:component photo-capture/profile-photo-capture}
|
||||||
|
|
|
@ -1,72 +1,29 @@
|
||||||
(ns status-im.ui.screens.wallet.accounts.styles
|
(ns status-im.ui.screens.wallet.accounts.styles
|
||||||
(:require [quo.animated :as reanimated]
|
(:require [quo.animated :as animated]
|
||||||
[status-im.ui.components.colors :as colors]
|
[status-im.ui.components.colors :as colors]))
|
||||||
[status-im.utils.platform :as platform]))
|
|
||||||
|
|
||||||
(def ^:const tabbar-height 56)
|
(defn container [{:keys [minimized]}]
|
||||||
;; TODO(Ferossgp): get layout size of total-value
|
(when-not minimized
|
||||||
(def ^:const value-height (+ 40 22 8))
|
{:padding-bottom 8
|
||||||
(def ^:const scroll-offset value-height)
|
:padding-horizontal 16}))
|
||||||
(def ^:const minimized-value-line-height 28)
|
|
||||||
|
|
||||||
(defn topbar [{:keys [value offset inset-top]}]
|
(defn value-container [{:keys [minimized animation]}]
|
||||||
(merge
|
(when minimized
|
||||||
{:flex-direction :row
|
{:opacity animation}))
|
||||||
:padding-horizontal 8
|
|
||||||
:background-color colors/white
|
|
||||||
:padding-top inset-top}
|
|
||||||
(when platform/android?
|
|
||||||
{:elevation (reanimated/interpolate
|
|
||||||
value
|
|
||||||
{:inputRange [0 offset]
|
|
||||||
:outputRange [0 4]
|
|
||||||
:extrapolate (:clamp reanimated/extrapolate)})})
|
|
||||||
(when platform/ios?
|
|
||||||
{:shadow-opacity (reanimated/interpolate
|
|
||||||
value
|
|
||||||
{:inputRange [0 offset]
|
|
||||||
:outputRange [0 1]
|
|
||||||
:extrapolate (:clamp reanimated/extrapolate)})
|
|
||||||
:shadow-radius 16
|
|
||||||
:z-index 2
|
|
||||||
:shadow-color (if (colors/dark?)
|
|
||||||
"rgba(0, 0, 0, 0.75)"
|
|
||||||
"rgba(0, 9, 26, 0.12)")
|
|
||||||
:shadow-offset {:width 0 :height 4}})))
|
|
||||||
|
|
||||||
(defn value-container [y]
|
(defn value-text [{:keys [minimized]}]
|
||||||
{:position :absolute
|
{:font-size (if minimized 20 32)
|
||||||
:left 8
|
:line-height 40
|
||||||
:top 0
|
:color colors/black})
|
||||||
:transform [{:translateY
|
|
||||||
(reanimated/interpolate
|
|
||||||
y
|
|
||||||
{:inputRange [0 scroll-offset]
|
|
||||||
:outputRange [scroll-offset
|
|
||||||
(/ (- tabbar-height
|
|
||||||
minimized-value-line-height) 2)]
|
|
||||||
:extrapolateRight (:clamp reanimated/extrapolate)})}]})
|
|
||||||
|
|
||||||
(defn value-text [y]
|
(defn accounts-mnemonic [{:keys [animation]}]
|
||||||
{:font-size (reanimated/interpolate
|
{:opacity (animated/b-interpolate animation 1 0)
|
||||||
y
|
:flex 1
|
||||||
{:inputRange [0 scroll-offset]
|
|
||||||
:outputRange [32 20]
|
|
||||||
:extrapolate (:clamp reanimated/extrapolate)})
|
|
||||||
:color colors/black
|
|
||||||
:font-weight "600"})
|
|
||||||
|
|
||||||
(defn value-helper [y]
|
|
||||||
{:opacity (reanimated/interpolate y
|
|
||||||
{:inputRange [0 scroll-offset]
|
|
||||||
:outputRange [1 0]})})
|
|
||||||
|
|
||||||
(defn accounts-mnemonic [y]
|
|
||||||
{:flex 1
|
|
||||||
:justify-content :center
|
:justify-content :center
|
||||||
:opacity (reanimated/interpolate y
|
:position :absolute
|
||||||
{:inputRange [0 scroll-offset]
|
:top 0
|
||||||
:outputRange [1 0]})})
|
:bottom 0
|
||||||
|
:left 0})
|
||||||
|
|
||||||
(defn card-common []
|
(defn card-common []
|
||||||
{:margin-vertical 16
|
{:margin-vertical 16
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im.ui.screens.wallet.accounts.views
|
(ns status-im.ui.screens.wallet.accounts.views
|
||||||
(:require [oops.core :refer [oget]]
|
(:require [quo.animated :as reanimated]
|
||||||
[quo.animated :as reanimated]
|
[quo.core :as quo]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.i18n :as i18n]
|
[status-im.i18n :as i18n]
|
||||||
|
@ -10,7 +10,6 @@
|
||||||
[status-im.ui.components.list-item.views :as list-item]
|
[status-im.ui.components.list-item.views :as list-item]
|
||||||
[status-im.ui.components.list.views :as list]
|
[status-im.ui.components.list.views :as list]
|
||||||
[status-im.ui.components.react :as react]
|
[status-im.ui.components.react :as react]
|
||||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]
|
|
||||||
[status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
[status-im.ui.screens.wallet.accounts.sheets :as sheets]
|
||||||
[status-im.ui.screens.wallet.accounts.styles :as styles]
|
[status-im.ui.screens.wallet.accounts.styles :as styles]
|
||||||
[status-im.utils.utils :as utils.utils]
|
[status-im.utils.utils :as utils.utils]
|
||||||
|
@ -94,20 +93,6 @@
|
||||||
:key-fn :name
|
:key-fn :name
|
||||||
:render-fn (render-asset (:code currency) prices-loading?)}]))
|
:render-fn (render-asset (:code currency) prices-loading?)}]))
|
||||||
|
|
||||||
(views/defview total-value [{:keys [y]}]
|
|
||||||
(views/letsubs [currency [:wallet/currency]
|
|
||||||
portfolio-value [:portfolio-value]]
|
|
||||||
[reanimated/view {:style (styles/value-container y)}
|
|
||||||
[reanimated/text {:style (styles/value-text y)}
|
|
||||||
portfolio-value
|
|
||||||
[reanimated/text {:style {:color colors/gray}}
|
|
||||||
(str " " (:code currency))]]
|
|
||||||
[reanimated/view {:style (styles/value-helper y)}
|
|
||||||
[react/text {:style {:color colors/gray
|
|
||||||
:font-size 15
|
|
||||||
:line-height 22}}
|
|
||||||
(i18n/label :t/wallet-total-value)]]]))
|
|
||||||
|
|
||||||
(defn- request-camera-permissions []
|
(defn- request-camera-permissions []
|
||||||
(let [options {:handler :wallet.send/qr-scanner-result}]
|
(let [options {:handler :wallet.send/qr-scanner-result}]
|
||||||
(re-frame/dispatch
|
(re-frame/dispatch
|
||||||
|
@ -122,58 +107,6 @@
|
||||||
(i18n/label :t/camera-access-error)))
|
(i18n/label :t/camera-access-error)))
|
||||||
50)}])))
|
50)}])))
|
||||||
|
|
||||||
(views/defview accounts-options [{:keys [y]}]
|
|
||||||
(views/letsubs [{:keys [mnemonic]} [:multiaccount]
|
|
||||||
empty-balances? [:empty-balances?]]
|
|
||||||
;; TODO(Ferossgp): Use topbar component here
|
|
||||||
[react/safe-area-consumer
|
|
||||||
(fn [insets]
|
|
||||||
(reagent/as-element
|
|
||||||
[reanimated/view {:style (styles/topbar {:inset-top (oget insets "top")
|
|
||||||
:value y
|
|
||||||
:offset styles/scroll-offset})}
|
|
||||||
[react/view {:flex 1
|
|
||||||
:height styles/tabbar-height
|
|
||||||
:padding-horizontal 8
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center}
|
|
||||||
[total-value {:y y}]
|
|
||||||
(when (and mnemonic
|
|
||||||
(not empty-balances?))
|
|
||||||
[reanimated/view {:style (styles/accounts-mnemonic y)}
|
|
||||||
[react/touchable-highlight
|
|
||||||
{:on-press #(re-frame/dispatch [:navigate-to :backup-seed])}
|
|
||||||
[react/view {:flex-direction :row :align-items :center}
|
|
||||||
[react/view {:width 14
|
|
||||||
:height 14
|
|
||||||
:background-color colors/gray
|
|
||||||
:border-radius 7
|
|
||||||
:align-items :center
|
|
||||||
:justify-content :center
|
|
||||||
:margin-right 9}
|
|
||||||
[react/text {:style {:color colors/white
|
|
||||||
:font-size 13
|
|
||||||
:font-weight "700"}}
|
|
||||||
"!"]]
|
|
||||||
[react/text {:style {:color colors/gray}
|
|
||||||
:accessibility-label :back-up-your-seed-phrase-warning}
|
|
||||||
(i18n/label :t/back-up-your-seed-phrase)]]]])]
|
|
||||||
[react/touchable-highlight
|
|
||||||
{:on-press #(request-camera-permissions)}
|
|
||||||
[react/view {:height toolbar.styles/toolbar-height
|
|
||||||
:padding-horizontal 8
|
|
||||||
:align-items :center
|
|
||||||
:justify-content :center}
|
|
||||||
[icons/icon :main-icons/qr {:accessibility-label :accounts-qr-code}]]]
|
|
||||||
[react/touchable-highlight
|
|
||||||
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
|
||||||
{:content (sheets/accounts-options mnemonic)}])}
|
|
||||||
[react/view {:height toolbar.styles/toolbar-height
|
|
||||||
:padding-horizontal 8
|
|
||||||
:align-items :center
|
|
||||||
:justify-content :center}
|
|
||||||
[icons/icon :main-icons/more {:accessibility-label :accounts-more-options}]]]]))]))
|
|
||||||
|
|
||||||
(views/defview send-button []
|
(views/defview send-button []
|
||||||
(views/letsubs [account [:multiaccount/default-account]]
|
(views/letsubs [account [:multiaccount/default-account]]
|
||||||
[react/view styles/send-button-container
|
[react/view styles/send-button-container
|
||||||
|
@ -194,17 +127,66 @@
|
||||||
[account-card account])
|
[account-card account])
|
||||||
[add-card]]]))
|
[add-card]]]))
|
||||||
|
|
||||||
|
(views/defview total-value [{:keys [animation minimized]}]
|
||||||
|
(views/letsubs [currency [:wallet/currency]
|
||||||
|
portfolio-value [:portfolio-value]
|
||||||
|
empty-balances? [:empty-balances?]
|
||||||
|
{:keys [mnemonic]} [:multiaccount]]
|
||||||
|
[reanimated/view {:style (styles/container {:minimized minimized})
|
||||||
|
:pointer-events :none}
|
||||||
|
|
||||||
|
(when (and mnemonic minimized (not empty-balances?))
|
||||||
|
[reanimated/view {:style (styles/accounts-mnemonic {:animation animation})}
|
||||||
|
[react/touchable-highlight
|
||||||
|
{:on-press #(re-frame/dispatch [:navigate-to :backup-seed])}
|
||||||
|
[react/view {:flex-direction :row :align-items :center}
|
||||||
|
[react/view {:width 14
|
||||||
|
:height 14
|
||||||
|
:background-color colors/gray
|
||||||
|
:border-radius 7
|
||||||
|
:align-items :center
|
||||||
|
:justify-content :center
|
||||||
|
:margin-right 9}
|
||||||
|
[react/text {:style {:color colors/white
|
||||||
|
:font-size 13
|
||||||
|
:font-weight "700"}}
|
||||||
|
"!"]]
|
||||||
|
[react/text {:style {:color colors/gray}
|
||||||
|
:accessibility-label :back-up-your-seed-phrase-warning}
|
||||||
|
(i18n/label :t/back-up-your-seed-phrase)]]]])
|
||||||
|
|
||||||
|
[reanimated/view {:style (styles/value-container {:minimized minimized
|
||||||
|
:animation animation})}
|
||||||
|
[reanimated/view {:style {:justify-content :center}}
|
||||||
|
[quo/text {:animated? true
|
||||||
|
:weight :semi-bold
|
||||||
|
:style (styles/value-text {:minimized minimized})}
|
||||||
|
portfolio-value
|
||||||
|
[quo/text {:animated? true
|
||||||
|
:size :inherit
|
||||||
|
:weight :inherit
|
||||||
|
:color :secondary}
|
||||||
|
(str " " (:code currency))]]]]
|
||||||
|
(when-not minimized
|
||||||
|
[reanimated/view
|
||||||
|
[quo/text {:color :secondary}
|
||||||
|
(i18n/label :t/wallet-total-value)]])]))
|
||||||
|
|
||||||
(defn accounts-overview []
|
(defn accounts-overview []
|
||||||
(let [y (reanimated/value 0)
|
(fn []
|
||||||
on-scroll (reanimated/on-scroll {:y y})]
|
(let [{:keys [mnemonic]} @(re-frame/subscribe [:multiaccount])]
|
||||||
(fn []
|
|
||||||
[react/view {:flex 1}
|
[react/view {:flex 1}
|
||||||
[accounts-options {:y y}]
|
[quo/animated-header
|
||||||
[reanimated/scroll-view {:on-scroll on-scroll
|
{:extended-header total-value
|
||||||
:style {:padding-top styles/value-height}
|
:use-insets true
|
||||||
:scrollEventThrottle 1}
|
:right-accessories [{:on-press #(request-camera-permissions)
|
||||||
[react/view {:margin-top 8}
|
:icon :main-icons/qr
|
||||||
[accounts]]
|
:accessibility-label :accounts-qr-code}
|
||||||
|
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||||
|
{:content (sheets/accounts-options mnemonic)}])
|
||||||
|
:icon :main-icons/more
|
||||||
|
:accessibility-label :accounts-more-options}]}
|
||||||
|
[accounts]
|
||||||
[assets]
|
[assets]
|
||||||
[react/view {:height 68}]]
|
[react/view {:height 68}]]
|
||||||
[send-button]])))
|
[send-button]])))
|
||||||
|
|
|
@ -104,8 +104,7 @@ class ConfirmLogoutButton(BaseButton):
|
||||||
class DefaultUserNameText(BaseText):
|
class DefaultUserNameText(BaseText):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
super(DefaultUserNameText, self).__init__(driver)
|
super(DefaultUserNameText, self).__init__(driver)
|
||||||
self.locator = self.Locator.xpath_selector(
|
self.locator = self.Locator.accessibility_id('default-username')
|
||||||
'//android.widget.ImageView[@content-desc="chat-icon"]/../android.widget.TextView')
|
|
||||||
|
|
||||||
class ENSusernames(BaseButton):
|
class ENSusernames(BaseButton):
|
||||||
def __init__(self, driver):
|
def __init__(self, driver):
|
||||||
|
|
Loading…
Reference in New Issue