[8070] feature - [Profile] My profile screens reorganisation and items design

Signed-off-by: Andrey Shovkoplyas <motor4ik@gmail.com>
This commit is contained in:
bitsikka 2019-08-23 14:57:16 +05:45 committed by Andrey Shovkoplyas
parent 58204f935b
commit 3541f636df
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
41 changed files with 1530 additions and 747 deletions

View File

@ -11,136 +11,187 @@
content]])
(defn list-items []
[react/view {:background-color colors/gray-lighter :flex 1 :padding 20 :flex-direction :row :flex-wrap :wrap}
[react/view
{:background-color colors/gray-lighter
:flex 1
:padding 20
:flex-direction :row
:flex-wrap :wrap}
[react/view {:margin-right 10}
[item "Default with Image"
[list-item/list-item {:title "George"
:on-press #()
:image [react/view {:width 40 :height 40 :border-radius 20
:background-color colors/green}]}]]
[list-item/list-item
{:title "George"
:on-press #()
:icon [react/view
{:width 40
:height 40
:border-radius 20
:background-color colors/green}]}]]
[item "Default with Image, icon"
[list-item/list-item {:title "George"
:on-press #()
:image [react/view {:width 40 :height 40 :border-radius 20
:background-color colors/green}]
:accessories [:more]}]]
[list-item/list-item
{:title "George"
:on-press #()
:icon [react/view
{:width 40
:height 40
:border-radius 20
:background-color colors/green}]
:accessories [:more]}]]
[item "With radio button (TODO!)"
[list-item/list-item {:title "George"
:on-press #()
:image [react/view {:width 40 :height 40 :border-radius 20
:background-color colors/green}]}]]]
[list-item/list-item
{:title "George"
:on-press #()
:icon [react/view
{:width 40
:height 40
:border-radius 20
:background-color colors/green}]}]]]
[react/view {:margin-right 10}
[item "Default wIth icon in circle"
[list-item/list-item {:title "Clear History"
:theme :action
:icon :main-icons/close
:on-press #()}]]
[list-item/list-item
{:title "Clear History"
:theme :action
:icon :main-icons/close
:on-press #()}]]
[item "Default wIth icon in circle, chevron"
[list-item/list-item {:title "Get a ENS username?"
:icon :main-icons/address
:on-press #()
:accessories [:chevron]}]]
[list-item/list-item
{:title "Get a ENS username?"
:icon :main-icons/address
:on-press #()
:accessories [:chevron]}]]
[item "Default wIth icon in circle, chevron and accessory"
[list-item/list-item {:title "Contacts"
:icon :main-icons/in_contacts
:on-press #()
:accessories [[react/text {:style {:color colors/gray}} "4"]
:chevron]}]]
[list-item/list-item
{:title "Contacts"
:icon :main-icons/in_contacts
:on-press #()
:accessories [[react/text {:style {:color colors/gray}} "4"]
:chevron]}]]
[item "Default wIth icon in circle, chevron and badge"
[list-item/list-item {:title "Privacy and Security"
:icon :main-icons/profile
:on-press #()
:accessories [[react/view {:width 22 :height 22 :border-radius 11
:background-color colors/blue :align-items :center
:justify-content :center}
[react/text {:style {:color colors/white :font-size 12}} "1"]]
:chevron]}]]
[list-item/list-item
{:title "Privacy and Security"
:icon :main-icons/profile
:on-press #()
:accessories
[[react/view {:width 22
:height 22
:border-radius 11
:background-color colors/blue
:align-items :center
:justify-content :center}
[react/text {:style {:color colors/white :font-size 12}} "1"]]
:chevron]}]]
[item "Default wIth icon in circle, switch (TODO!)"
[list-item/list-item {:title "Notifications"
:icon :main-icons/notification
:on-press #()
:accessories [[react/view {:width 22 :height 22 :border-radius 11
:background-color colors/blue :align-items :center
:justify-content :center}]]}]]
[list-item/list-item
{:title "Notifications"
:icon :main-icons/notification
:on-press #()
:accessories
[[react/view {:width 22
:height 22
:border-radius 11
:background-color colors/blue
:align-items :center
:justify-content :center}]]}]]
[item "Default wIth icon in circle, red"
[list-item/list-item {:title "Delete and Leave"
:theme :action-red
:icon :main-icons/delete
:on-press #()}]]]
[list-item/list-item
{:title "Delete and Leave"
:theme :action-red
:icon :main-icons/delete
:on-press #()}]]]
[react/view {:margin-right 10}
[item "Two lines with icon in circle, chevron"
[list-item/list-item {:title "alex.stateofus.eth"
:subtitle "ENS name"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[list-item/list-item
{:title "alex.stateofus.eth"
:subtitle "ENS name"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[item "Two lines with icon in circle"
[list-item/list-item {:title "alex.stateofus.eth"
:subtitle "ENS name"
:icon :main-icons/address
:on-press #()}]]
[list-item/list-item
{:title "alex.stateofus.eth"
:subtitle "ENS name"
:icon :main-icons/address
:on-press #()}]]
[item "Two lines with icon in circle, blue title"
[list-item/list-item {:title "Add or Create a Profile"
:subtitle "Requires signout"
:theme :action
:icon :main-icons/address
:on-press #()}]]
[list-item/list-item
{:title "Add or Create a Profile"
:subtitle "Requires signout"
:theme :action
:icon :main-icons/address
:on-press #()}]]
[item "Two lines with dapp icon,title and subtitle"
[list-item/list-item {:title "CryptoKitties"
:subtitle "https://cryptokitties.co"
:image [react/view {:width 40 :height 40 :border-radius 20
:background-color colors/green}]
:on-press #()}]]]
[list-item/list-item
{:title "CryptoKitties"
:subtitle "https://cryptokitties.co"
:icon [react/view {:width 40
:height 40
:border-radius 20
:background-color colors/green}]
:on-press #()}]]]
[react/view {:margin-right 10}
[item "Default Small"
[list-item/list-item {:title "Everybody"
:type :small
:on-press #()}]]
[list-item/list-item
{:title "Everybody"
:type :small
:on-press #()}]]
[item "Default Small button"
[list-item/list-item {:title "Change Passcode"
:type :small
:theme :action
:on-press #()}]]
[list-item/list-item
{:title "Change Passcode"
:type :small
:theme :action
:on-press #()}]]
[item "Default Small red button"
[list-item/list-item {:title "Delete all Contacts"
:type :small
:theme :action-red
:on-press #()}]]
[list-item/list-item
{:title "Delete all Contacts"
:type :small
:theme :action-red
:on-press #()}]]
[item "Default Small with chevron"
[list-item/list-item {:title "Recovery Phrase"
:type :small
:on-press #()
:accessories [:chevron]}]]
[list-item/list-item
{:title "Recovery Phrase"
:type :small
:on-press #()
:accessories [:chevron]}]]
[item "Default Small with chevron and accessory"
[list-item/list-item {:title "Main Currency"
:type :small
:on-press #()
:accessories [[react/text {:style {:color colors/gray}} "USD"]
:chevron]}]]
[list-item/list-item
{:title "Main Currency"
:type :small
:on-press #()
:accessories [[react/text {:style {:color colors/gray}} "USD"]
:chevron]}]]
[item "Default Small with chevron, badge"
[list-item/list-item {:title "Recovery Phrase"
:type :small
:on-press #()
:accessories [[react/view {:width 22 :height 22 :border-radius 11
:background-color colors/blue :align-items :center
:justify-content :center}
[react/text {:style {:color colors/white :font-size 12}} "1"]]
:chevron]}]]]
[list-item/list-item
{:title "Recovery Phrase"
:type :small
:on-press #()
:accessories
[[react/view
{:width 22
:height 22
:border-radius 11
:background-color colors/blue :align-items :center
:justify-content :center}
[react/text {:style {:color colors/white :font-size 12}} "1"]]
:chevron]}]]]
[react/view {:margin-right 10}
[item "Long title"
[list-item/list-item {:title "loooooooooong looooooong looooooong title"
:subtitle "ENS name"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[list-item/list-item
{:title "loooooooooong loooooooooooooong looooooong title"
:subtitle "ENS name"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[item "Long subtitle"
[list-item/list-item {:title "alex.stateofus.eth"
:subtitle "loooooooooooong loooooong looooooong subtitle"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[item "Long accessories"
[list-item/list-item {:title "From"
:type :small
:accessories ["loooooooooooongloooooonglooo00oooongaccessories"]
:on-press #()}]]]])
[list-item/list-item
{:title "alex.stateofus.eth"
:subtitle "loooooooooooooooong loooooong looooooong subtitle"
:icon :main-icons/address
:accessories [:chevron]
:on-press #()}]]
[item "Title-prefix + long title"
[list-item/list-item
{:title-prefix "From"
:title-prefix-width 45
:title "title-prefix and loooooong title really loooonglooo00oooong"
:type :small
:on-press #()}]]]])

View File

@ -11,7 +11,7 @@
:android {:height 64}})
(defnstyle action-button-icon-container [circle-color]
{:border-radius 50
{:border-radius 20
:width 40
:height 40
:align-items :center

View File

@ -131,7 +131,8 @@
:justify-content :center})
(defn counter-label [size]
{:font-size (/ size 2)
{:font-size (inc (/ size 2))
:typography :main-medium
:color colors/white
:text-align :center})

View File

@ -1,90 +1,124 @@
(ns status-im.ui.components.copyable-text
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [reagent.core :as reagent]
[status-im.ui.components.react :as react]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.ui.components.typography :as typography]))
(defn hide-cue-atom [anim-opacity anim-y cue-atom]
(animation/start
(animation/parallel
[(animation/timing anim-opacity
{:toValue 0
:duration 140
:delay 1000
:easing (.-ease (animation/easing))
:useNativeDriver true})
(animation/timing anim-y
{:toValue 0
:duration 140
:delay 1000
:easing (.-ease (animation/easing))
:useNativeDriver true})])
[(animation/timing
anim-opacity
{:toValue 0
:duration 140
:delay 1000
:easing (.-ease (animation/easing))
:useNativeDriver true})
(animation/timing
anim-y
{:toValue 0
:duration 140
:delay 1000
:easing (.-ease (animation/easing))
:useNativeDriver true})])
#(reset! cue-atom false)))
(defn show-cue-atom [anim-opacity anim-y cue-atom y]
(when @cue-atom
(animation/start
(animation/parallel
[(animation/timing anim-opacity
{:toValue 1
:duration 140
:easing (.-ease (animation/easing))
:useNativeDriver true})
(animation/timing anim-y
{:toValue y
:duration 140
:easing (.-ease (animation/easing))
:useNativeDriver true})])
[(animation/timing
anim-opacity
{:toValue 1
:duration 140
:easing (.-ease (animation/easing))
:useNativeDriver true})
(animation/timing
anim-y
{:toValue y
:duration 140
:easing (.-ease (animation/easing))
:useNativeDriver true})])
#(hide-cue-atom anim-opacity anim-y cue-atom))))
(defn copy-action-visual-cue [anim-opacity anim-y width cue-atom]
[react/animated-view {:style {:opacity anim-opacity
:transform [{:translateY anim-y}]
:height 34
:max-width @width
:position :absolute
:border-radius 8
:align-self :center
:z-index (if @cue-atom 1 -1)
:align-items :center
:justify-content :center
:shadow-offset {:width 0 :height 4}
:shadow-radius 12
:shadow-opacity 1
:shadow-color "rgba(0, 34, 51, 0.08)"
:background-color colors/white}}
[react/view {:padding-horizontal 16
:padding-vertical 7
:border-radius 8
:background-color colors/white
:shadow-offset {:width 0 :height 2}
:shadow-radius 4
:shadow-opacity 1
:shadow-color "rgba(0, 34, 51, 0.16)"}
[react/text {:style {:typography :main-medium :line-height 20 :font-size 14}}
[react/animated-view
{:style
{:opacity anim-opacity
:transform [{:translateY anim-y}]
:max-width @width
:z-index (if @cue-atom 1 -1)
:height 34
:position :absolute
:border-radius 8
:align-self :center
:align-items :center
:justify-content :center
:shadow-offset {:width 0 :height 4}
:shadow-radius 12
:elevation 8
:shadow-opacity 1
:shadow-color "rgba(0, 34, 51, 0.08)"
:background-color colors/white}}
[react/view
{:padding-horizontal 16
:padding-vertical 7
:border-radius 8
:background-color colors/white
:shadow-offset {:width 0 :height 2}
:shadow-radius 4
:shadow-opacity 1
:shadow-color "rgba(0, 34, 51, 0.16)"}
[react/text
{:style
{:typography :main-medium
;; line height specified here because of figma spec
:line-height 20
:font-size 14}}
(i18n/label :sharing-copied-to-clipboard)]]])
(defview copyable-text-view [{:keys [label copied-text]} content]
(letsubs [cue-atom (reagent/atom false)
width (reagent/atom nil)
anim-y (animation/create-value 0)
anim-opacity (animation/create-value 0)]
[react/view
[copy-action-visual-cue anim-opacity anim-y width cue-atom]
[react/touchable-opacity
{:active-opacity (if @cue-atom 1 0.7)
:style {:margin-top 12 :margin-bottom 4}
:on-press #(when (not @cue-atom)
(reset! cue-atom true)
(show-cue-atom anim-opacity anim-y cue-atom -22)
(react/copy-to-clipboard copied-text))}
[react/view
[react/text {:style {:font-size 13 :line-height 18 :font-weight "500"
:color colors/gray :margin-bottom 4}}
(i18n/label label)]
[react/view
{:on-layout #(reset! width (-> % .-nativeEvent .-layout .-width))}
content]]]]))
(defn copyable-text-view [{:keys [label copied-text container-style]}
content]
(let [cue-atom (reagent/atom false)
width (reagent/atom 0)
height (reagent/atom 0)
anim-y (animation/create-value 0)
anim-opacity (animation/create-value 0)]
(reagent/create-class
{:reagent-render
(fn [{:keys [copied-text]} _]
[react/view
{:style (if container-style container-style {})
:on-layout
#(do
(reset! width (-> % .-nativeEvent .-layout .-width))
(reset! height (-> % .-nativeEvent .-layout .-height)))}
(when label
[react/text
{:style
{:font-size 13
;; line height specified here because of figma spec
:line-height 18
:font-weight "500"
:color colors/gray
:margin-bottom 4}}
(i18n/label label)])
[copy-action-visual-cue anim-opacity anim-y width cue-atom]
[react/touchable-highlight
{:active-opacity (if @cue-atom 1 0.85)
:underlay-color colors/black
:on-press
#(when (not @cue-atom)
(reset! cue-atom true)
(show-cue-atom
anim-opacity
anim-y
cue-atom
(if (> @height 34)
(- (/ @height 2))
(- (+ 17 @height))))
(react/copy-to-clipboard copied-text))}
[react/view {:background-color colors/white}
content]]])})))

View File

@ -21,7 +21,8 @@
(defn icon
([name] (icon name nil))
([name {:keys [color container-style accessibility-label width height]
([name {:keys [color resize-mode container-style
accessibility-label width height]
:or {accessibility-label :icon}}]
^{:key name}
[react/view
@ -33,6 +34,10 @@
[react/image {:source {:uri (keyword (clojure.core/name name))}
:style (cond-> {:width (or width 24)
:height (or height 24)}
resize-mode
(assoc :resize-mode resize-mode)
color
(assoc :tint-color (match-color color)))}]]))
@ -40,4 +45,4 @@
([name] (tiny-icon name {}))
([name options]
(icon name (merge {:width 16 :height 16}
options))))
options))))

View File

@ -1,52 +1,59 @@
(ns status-im.ui.components.large-toolbar
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [reagent.core :as reagent]
[cljs-bean.core :refer [->clj ->js]]
(:require-macros [status-im.utils.views :as views])
(:require [cljs-bean.core :refer [->clj ->js]]
[reagent.core :as reagent]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list.views :as list.views]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.react :as react]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.components.toolbar.styles :as toolbar.styles]
[status-im.utils.platform :as platform]
[status-im.ui.components.animation :as animation]))
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.utils.platform :as platform]))
(def hidden (reagent/atom 0))
(def shown (reagent/atom 100))
(def minimized-header-visible? (reagent/atom false))
(def initial-on-show-done? (volatile! false))
(defview animated-content-wrapper [header-in-toolbar has-nav? show?]
(letsubs [anim-opacity (animation/create-value 0)
to-hide (reagent/atom false)]
{:component-will-update
(fn [_ [_ _ _ show?]]
(cond
(and (not @to-hide) show?)
(animation/start
(animation/timing
anim-opacity
{:toValue 1
:duration 200
:easing (.-ease (animation/easing))
:useNativeDriver true})
#(reset! to-hide true))
(defn animated-content-wrapper [header-in-toolbar has-nav? show?]
(let [anim-opacity (animation/create-value 0)
to-hide (reagent/atom false)]
(reagent/create-class
{:component-did-update
(fn [comp]
(let [new-argv (rest (reagent/argv comp))
show? (last new-argv)]
(cond
(and (not @to-hide) show?)
(animation/start
(animation/timing
anim-opacity
{:toValue 1
:duration 200
:easing (.-ease (animation/easing))
:useNativeDriver true})
#(reset! to-hide true))
(and @to-hide (not show?))
(animation/start
(animation/timing
anim-opacity
{:toValue 0
:duration 200
:easing (.-ease (animation/easing))
:useNativeDriver true})
#(reset! to-hide false))))}
[react/animated-view
{:style (cond-> {:flex 1
:align-self :stretch
:opacity anim-opacity}
(false? has-nav?)
(assoc :margin-left -40 :margin-right 40))}
header-in-toolbar]))
(and @to-hide (not show?))
(animation/start
(animation/timing
anim-opacity
{:toValue 0
:duration 200
:easing (.-ease (animation/easing))
:useNativeDriver true})
#(reset! to-hide false)))))
:reagent-render
(fn [header-in-toolbar has-nav? _]
[react/animated-view
{:style (cond-> {:flex 1
:align-self :stretch
:opacity anim-opacity}
(false? has-nav?)
(assoc :margin-left -40 :margin-right 40))}
header-in-toolbar])})))
(defn on-viewable-items-changed [threshold interporlation-step]
(fn [info]
@ -95,8 +102,8 @@
;; 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
(defview flat-list-with-large-header [header content list-ref]
(letsubs [window-width [:dimensions/window-width]]
(views/defview flat-list-with-large-header [header content list-ref]
(views/letsubs [window-width [:dimensions/window-width]]
{:component-did-mount #(do (reset! hidden 0) (reset! shown 100)
(reset! minimized-header-visible? false)
(vreset! initial-on-show-done? false))}
@ -136,7 +143,7 @@
:data wrapped-data
:initial-num-to-render 3
:ref #(reset! list-ref %)
:render-fn (fn [item idx] item)
:render-fn list.views/flat-list-generic-render-fn
:key-fn (fn [item idx] (str idx))
:on-scroll-begin-drag #(when (false? @initial-on-show-done?)
(vreset! initial-on-show-done? true))

View File

@ -25,6 +25,7 @@
[status-im.ui.components.checkbox.view :as checkbox]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.list.styles :as styles]
[status-im.ui.components.react :as react]
[status-im.ui.screens.home.animations.responder :as responder]
@ -224,6 +225,13 @@
props
{:data (wrap-data data)})])
(defn flat-list-generic-render-fn [item _]
(cond
(map? item) [list-item/list-item item]
(vector? item) item
(nil? item) nil
:else [item]))
(defn- wrap-render-section-header-fn [f]
(fn [data]
(let [section (.-section data)]

View File

@ -1,24 +1,176 @@
(ns status-im.ui.components.list-item.styles
(:require [status-im.ui.components.colors :as colors]))
(defn container [small?]
{:height (if small? 52 64)
(defn container [type theme]
{:min-height (cond
(= type :default) 64
(= type :small) 52
(= type :section-header) 40
:else 0)
:flex 1
:flex-direction :row
:justify-content :flex-start
:padding-horizontal 16
:background-color (if (= theme :blue)
colors/blue
colors/white)
:padding-top (cond
(= type :section-header) 14
:else 10)
:padding-bottom (cond
(= type :section-header) 4
:else 10)
:align-items :center})
(def icon-column-container
{:margin-right 14
:padding-vertical 2
:justify-content :flex-start
:max-width 40
:align-items :center
:flex-direction :row
:background-color :white})
:align-self :stretch})
(defn title [small? subtitle]
(merge (when-not small?
{:typography :title})
(when subtitle
{:typography :main-medium})))
(defn icon-container [color]
{:border-radius 20
:width 40
:height 40
:align-items :center
:justify-content :center
:background-color (or color colors/blue-light)})
(def subtitle
{:margin-top 4
:color colors/gray})
(defn icon [color]
{:color (or color colors/blue)
:font-size 16})
(def accessory-text
{:color colors/gray})
(defn title-column-container [accessories?]
{:margin-right (if accessories? 16 0)
:flex 1
:justify-content :center
:align-items :flex-start
:align-self :stretch})
(def title-row-container
{:min-height 22
:flex-direction :row
:justify-content :flex-start
:align-self :stretch})
(defn title-prefix-icon-container
[title-prefix-height title-prefix-width]
(merge
{:width 16
:height 16
:justify-content :center
:margin-top (if (not title-prefix-height) 4 0)
:align-items :center}
(when title-prefix-width
{:width title-prefix-width})
(when title-prefix-height
{:height title-prefix-height})))
(defn title-prefix-text [type theme icon? subtitle
content title-prefix-width disabled?]
(merge {:margin-left (if icon? 2 0)
:align-self :stretch
;; we are doing the following to achieve pixel perfection
;; as reasonably possible as it can be, and achieve the
;; intent of the design spec
:line-height 22}
(when (= type :default)
(if (or subtitle content)
{:typography :main-medium
:line-height 22}
{:typography :title
:line-height 20}))
(when title-prefix-width
{:width title-prefix-width})
(if disabled?
{:color colors/gray}
(case theme
:blue {:color colors/white}
:action-destructive {:color colors/red}
:action {:color colors/blue}
{}))))
(defn title [type theme icon? title-prefix subtitle
content title-row-accessory disabled?
title-color-override]
(merge {:margin-left (if icon? 2 0)
:flex 1
:align-self :stretch
;; we are doing the following to achieve pixel perfection
;; as reasonably possible as it can be, and achieve the
;; intent of the design spec
:line-height 22}
(when (= type :default)
(if (or subtitle content)
{:typography :main-medium
:line-height 22}
{:typography :title
:line-height 20}))
(when title-prefix
{:margin-left (if (string? title-prefix) 0 2)})
(when title-row-accessory
{:margin-right 16})
(if (or disabled? (= :section-header type))
{:color colors/gray}
;; else
(if title-color-override
{:color title-color-override}
;; else
(case theme
:blue {:color colors/white}
:action-destructive {:color colors/red}
:action {:color colors/blue}
{})))))
(def title-row-accessory-container
{:margin-top 2
:align-self :stretch})
(def subtitle-row-container
{:min-height 22
:flex-direction :row
:justify-content :flex-start
:align-self :stretch})
(defn subtitle [icon? theme subtitle-row-accessory]
(cond-> {:margin-left (if icon? 2 0)
:flex 1
:align-self :stretch
:color colors/gray
;; we are doing the following to achieve pixel perfection
;; as reasonably possible as it can be, and achieve the
;; intent of the design spec
:line-height 22}
(= :blue theme)
(assoc :color (colors/alpha colors/blue-light 0.6))
subtitle-row-accessory
(assoc :margin-right 16)))
(def subtitle-row-accessory-container
{:justify-content :flex-end
:align-self :stretch})
(def accessories-container
{:align-self :stretch
:flex-direction :row
:align-items :center
:justify-content :flex-start})
(defn accessory-text [theme]
{:color (if (= theme :blue)
(colors/alpha colors/blue-light 0.6)
colors/gray)
;; we are doing the following to achieve pixel perfection
;; as reasonably possible as it can be, and achieve the
;; intent of the design spec
:line-height 22})
(defn radius [size] (/ size 2))

View File

@ -1,81 +1,378 @@
(ns status-im.ui.components.list-item.views
(:require [status-im.ui.components.colors :as colors]
(:require [clojure.string :as string]
[reagent.core :as reagent]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.react :as react]
[status-im.ui.components.list-item.styles :as styles]
[status-im.utils.image :as utils.image]
[status-im.ui.components.tooltip.views :as tooltip]
[status-im.ui.components.action-button.styles :as st]))
[status-im.ui.screens.profile.db :as profile.db]))
; type - optional :default , :small
(def divider
[react/view {:height 1 :background-color colors/gray-lighter}])
; accessories - optional vector of :chevron, :check, :more or component or string
(defn stringify [keyword-or-number]
(cond
(string? keyword-or-number)
keyword-or-number
; theme - optional :default, :wallet, :action, :action-red
(and (qualified-keyword? keyword-or-number)
(= "t" (namespace keyword-or-number)))
(i18n/label keyword-or-number)
(defn list-item [{:keys [title subtitle accessories image image-path icon type theme on-press error content] :or {type :default theme :default}}]
(let [small? (= :small type)]
[react/touchable-highlight {:on-press on-press :disabled (not on-press)}
[react/view {:style (styles/container small?)}
;;Image
(when image
[react/view {:margin-left 16}
(if (vector? image)
image
[image])])
;;Icon
(when icon
[react/view {:margin-left 16}
[react/view (st/action-button-icon-container (when (= theme :action-red) colors/red-transparent-10))
[icons/icon icon (if (= theme :action-red) st/action-button-label-red st/action-button-label)]]])
(when image-path
[react/view {:margin-left 16}
[react/image {:source (utils.image/source image-path)
:style (styles/photo 40)}]])
;;Title
(when title
[react/view {:style {:margin-left 16 :margin-right 16 :flex 1 :min-width 50}}
[react/text {:style (merge (styles/title small? subtitle)
(when (= theme :action) st/action-button-label)
(when (= theme :action-red) st/action-button-label-red))
:number-of-lines 1
:ellipsize-mode :tail}
title]
;;Subtitle
(when subtitle
[react/text {:style styles/subtitle
:number-of-lines 1
(and (qualified-keyword? keyword-or-number)
(not= "t" (namespace keyword-or-number)))
(str (namespace keyword-or-number) "/" (name keyword-or-number))
(simple-keyword? keyword-or-number)
(name keyword-or-number)
(number? keyword-or-number)
(str keyword-or-number)
:else nil))
(defn- icon-column [icon theme disabled?]
[react/view styles/icon-column-container
(cond
(vector? icon)
icon
(and (qualified-keyword? icon)
(= "main-icons" (namespace icon)))
(let [colors
(if disabled?
{:container colors/gray-lighter
:icon colors/gray-transparent-40}
(case theme
:action-destructive
{:container colors/red-light
:icon colors/red}
:blue
{:container colors/white-transparent-10
:icon colors/white}
{:container nil
:icon nil}))]
[react/view (styles/icon-container (:container colors))
[icons/icon icon (styles/icon (:icon colors))]])
(and (string? icon)
(profile.db/base64-encoded-image-path? icon))
[react/image {:source {:uri icon}
:resize-mode :cover
:style (styles/photo 40)}]
:else [icon])])
(defn- title-row [{:keys [title title-color-override title-prefix title-prefix-width
title-prefix-height title-row-accessory]}
type icon? disabled? theme subtitle content accessories]
[react/view styles/title-row-container
(when title-prefix
(cond
(and (qualified-keyword? title-prefix)
(= "main-icons" (namespace title-prefix)))
[icons/icon title-prefix
(merge
{:color colors/gray
:width 16
:height 16
:container-style
(styles/title-prefix-icon-container
title-prefix-height title-prefix-width)}
(when title-prefix-width
{:width title-prefix-width})
(when title-prefix-height
{:height title-prefix-height}))]
(or (string? title-prefix)
(number? title-prefix)
(keyword? title-prefix))
[react/text {:number-of-lines 1
:ellipsize-mode :tail
:style
(styles/title-prefix-text
type theme icon? subtitle content
title-prefix-width disabled?)}
(if title-prefix-width
(stringify title-prefix)
(str (stringify title-prefix) " "))]
(vector? title-prefix)
title-prefix
:else
[title-prefix]))
(cond
(or (string? title) (keyword? title) (number? title))
[react/text {:number-of-lines 1
:ellipsize-mode :tail
:style
(styles/title
type theme icon? title-prefix subtitle
content title-row-accessory disabled?
title-color-override)}
(stringify title)]
(vector? title)
[react/view {:flex 1}
title]
:else
[react/view {:flex 1}
[title]])
(when title-row-accessory
[react/view styles/title-row-accessory-container title-row-accessory])])
(defn subtitle-row [{:keys [subtitle subtitle-max-lines subtitle-row-accessory]}
icon? theme]
(let [subtitle-row-accessory-width (reagent/atom 0)]
(reagent/create-class
{:render
(fn []
[react/view styles/subtitle-row-container
(cond
(or (string? subtitle) (keyword? subtitle) (number? subtitle))
[react/text {:style
(merge
(styles/subtitle
icon? theme (pos? @subtitle-row-accessory-width)))
:number-of-lines subtitle-max-lines
:ellipsize-mode :tail}
subtitle])])
;;Content
(when content
(if (vector? content)
content
[content]))
;;Accessories
(for [accessory accessories]
(when-not (nil? accessory)
(with-meta
(cond
(= :chevron accessory)
[react/view {:margin-right 8}
[icons/icon :main-icons/next {:color colors/gray-transparent-40}]]
(= :check accessory)
[react/view {:margin-right 16}
[icons/icon :main-icons/check {:color colors/gray}]]
(= :more accessory)
[react/view {:margin-right 16}
[icons/icon :main-icons/more]]
:else
[react/view {:margin-right 16 :flex-shrink 1}
(cond
(string? accessory)
[react/text {:style styles/accessory-text :number-of-lines 1}
accessory]
(vector? accessory)
accessory
:else
[accessory])])
{:key accessory})))
(when error
[tooltip/tooltip error styles/error])]]))
(stringify subtitle)]
(vector? subtitle)
[react/view
(styles/subtitle icon? theme (pos? @subtitle-row-accessory-width))
subtitle]
:else
[react/view
(styles/subtitle icon? theme (pos? @subtitle-row-accessory-width))
[subtitle]])
(when subtitle-row-accessory
[react/view
{:style styles/subtitle-row-accessory-container
:on-layout #(reset!
subtitle-row-accessory-width
(-> % .-nativeEvent .-layout .-width))}
;; We do this so that the bottom of the component is 12 device px
;; from bottom of the touchable container, instead of 10.
[react/view {:transform [{:translateY -2}]}
subtitle-row-accessory]])])})))
(defn- title-column [{:keys [title] :as title-row-elements}
{:keys [subtitle] :as subtitle-row-elements}
type icon? disabled? theme content accessories]
[react/view (styles/title-column-container accessories)
(when title
[title-row
title-row-elements type icon? disabled?
theme subtitle content accessories])
(when (and subtitle (= :default type))
[subtitle-row subtitle-row-elements icon? theme])
(when content
[react/view {:margin-left (if icon? 2 0)}
(if (vector? content)
content
[content])])])
(defn- accessories-column [accessories theme]
(let [last-accessory (peek accessories)
last-accessory-is-component (and (not (stringify last-accessory))
(not= :chevron last-accessory))
second-last-accessory (peek (pop accessories))]
(into
[react/view styles/accessories-container]
(for [accessory accessories]
(when-not (nil? accessory)
(with-meta
(cond
(= :chevron accessory)
[icons/icon :main-icons/next
{:container-style {:width 10
:height 16
:align-items :center
:justify-content :center}
:resize-mode :center
:color (if (= theme :blue)
(colors/alpha colors/white 0.4)
colors/gray-transparent-40)}]
(= :check accessory)
[icons/icon :main-icons/check
{:color (if (= theme :blue)
(colors/alpha colors/white 0.4)
colors/gray)}]
(= :more accessory)
[icons/icon :main-icons/more
{:color (if (= theme :blue)
(colors/alpha colors/white 0.4)
colors/black)}]
:else
[react/view (cond-> {:margin-right (if (= accessory last-accessory) 0 16)}
;; `:chevron` container is 10px wide (see up)
;; but the chevron icon itself is 9px aligned in the
;; container to the right - so 1px white-space on left
;; that 1px + 15px margin makes 16px
;; as intended in design spec
(= last-accessory :chevron)
(assoc :margin-right 15))
(cond
(or (string? accessory) (keyword? accessory) (number? accessory))
[react/text {:style (styles/accessory-text theme)
:number-of-lines 1}
(stringify accessory)]
(vector? accessory)
accessory
:else nil)])
{:key accessory}))))))
;; every key is optional - use as needed
;; combination of around 4 related keys are enough for most cases
;; type
;; :default (default), :small, or :section-header
;; - :section-header
;; specifying only these is sufficient
;; {:title "Section title" :type :section-header}
;; optionally set `container-margin-top/bottom`
;; theme
;; :default(default), :blue, :action, :action-destructive
;; container-margin-top
;; container-margin-bottom
;; number - 0 by default
;; usually the first item has top margin
;; the last item has bottom margin
;; icon
;; any one of keyword representing :main-icon/icon, photo-path, component
;; if component make sure to make it 40x40 size
;; title-prefix
;; any one of keyword representing an vector-icon/icon,
;; :main-icons/tiny-icons(16x16) are preferred(when it has 4px :margin-top)
;; any other vector-icon/icon is accepted though(when it is better to
;; specify height(best to keep it <= 20) see related height/width below
;; string, keyword(gets converted to string),
;; number(gets converted to string), or component
;; title-prefix-width
;; title-prefix-height
;; optional width/height for when title/prefix is not a tiny-icon
;; i.e. when icon height/height > 16, or when component
;; do not specify if title-prefix is tiny-icon
;; title
;; any one of string, keyword representing translated string in the form of
;; :t/{translation-key-in-translation-files},
;; keyword(gets converted to string),
;; number(gets converted to string), or
;; component - when component is used best to keep the style similar
;; to `styles/title-row-container` and/or `styles/title`
;; title-color-override
;; colors/color - only occasionally needed, self-explanatory
;; title-row-accessory
;; component - especially made for chat list item, but may serve other
;; purpose in the unlikely future. Wrapper already has 2px :margin-top
;; best to keep it <= 18px high
;; subtitle
;; any one of string, keyword representing translated string in the form of
;; :t/{translation-key-in-translation-files},
;; keyword(gets converted to string),
;; number(gets converted to string), or
;; component - when component is used best to keep the style similar
;; to `styles/subtitle-title-row-container` and/or `styles/subtitle`
;; subtitle-max-lines
;; integer - 1 by default - self-explanatory
;; subtitle-row-accessory
;; component
;; made specially for chat-list to hold unread messages counter
;; content
;; component - to replace entire title-column area
;; TODO - consider removing, as it is redundant now that
;; title/subtitle elements can be component as well
;; just make sure to keep in mind the note made on
;; component case on those keys above
;; accessories
;; vector of :chevron, :check, :more, string, number, keyword or component
;; on-press/on-long-press
;; function - self explanatory
;; error
;; string - error tooltip
;; accessibility-label
;; :keyword - self explanatory
;; disabled?
;; boolean - false by default - self explanatory
(defn list-item
[{:keys [type theme container-margin-top container-margin-bottom
icon title-prefix title-prefix-width title-prefix-height
title title-color-override title-row-accessory
subtitle subtitle-max-lines subtitle-row-accessory
content accessories on-press on-long-press
error accessibility-label disabled?]
:or {type :default
theme :default
disabled? false
container-margin-top 0
container-margin-bottom 0
subtitle-max-lines 1}}]
(let [title-row-elements
{:title title
:title-color-override title-color-override
:title-prefix title-prefix
:title-prefix-width title-prefix-width
:title-prefix-height title-prefix-height
:title-row-accessory title-row-accessory}
subtitle-row-elements
{:subtitle subtitle
:subtitle-max-lines subtitle-max-lines
:subtitle-row-accessory subtitle-row-accessory}]
[react/view {:margin-top container-margin-top
:margin-bottom container-margin-bottom}
[react/touchable-highlight
(cond-> {:on-press on-press
:on-long-press on-long-press
:underlay-color colors/black
:disabled (or (not on-press) disabled?)}
accessibility-label
(assoc :accessibility-label accessibility-label))
[react/view {:style (styles/container type theme)}
(when icon
[icon-column icon theme disabled?])
(when (or title subtitle content)
[title-column
title-row-elements subtitle-row-elements
type icon disabled? theme content accessories])
(when accessories
[accessories-column accessories theme])]]
(when error
[tooltip/tooltip error styles/error])]))

View File

@ -44,6 +44,11 @@
:installations {:type :main}
:transactions-history {:type :main}
:dapps-permissions {:type :main}
:privacy-and-security {:type :main}
:language-settings {:type :main}
:notifications-settings {:type :main}
:sync-settings {:type :main}
:advanced-settings {:type :main}
:help-center {:type :main}
:about-app {:type :main}
:offline-messaging-settings {:type :main}

View File

@ -1,109 +1,39 @@
(ns status-im.ui.screens.about-app.views
(:require-macros [status-im.utils.views :as views]
[status-im.utils.views :refer [defview letsubs]])
(:require [status-im.ui.components.toolbar.view :as toolbar]
(:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.icons.vector-icons :as vector-icons]
[status-im.ui.screens.about-app.styles :as styles]
[status-im.i18n :as i18n]
[status-im.transport.utils :as transport.utils]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.profile.components.views :as profile.components]
[re-frame.core :as re-frame]))
[status-im.ui.components.toolbar.view :as toolbar]))
(defn app-info->json [app-version peers mailserver node-info node-version]
(js/JSON.stringify
(clj->js
{:client {:app-version app-version
:mailserver mailserver
:node-info node-info
:node-version node-version}
:peers peers})
nil
4))
(defview learn-more-sheet []
(letsubs [{:keys [title content]} [:bottom-sheet/options]]
[react/view {:style {:padding 16}}
[react/view {:style {:align-items :center :flex-direction :row :margin-bottom 16}}
[vector-icons/icon :main-icons/info {:color colors/blue
:container-style {:margin-right 13}}]
[react/text {:style styles/learn-more-title} title]]
[react/text {:style styles/learn-more-text} content]]))
(def learn-more
{:content learn-more-sheet
:content-height 180})
(defn peer-view [{:keys [enode]}]
(let [[enode-id ip-address port] (transport.utils/extract-url-components enode)]
^{:key enode}
[react/touchable-highlight {:style styles/peer-view
:on-press #(react/copy-to-clipboard enode)}
[react/view
[react/view
[react/text {:style styles/peer-text} (str "id: " enode-id)]]
[react/view
[react/text {:style styles/peer-text} (str "ip: " ip-address)]]
[react/view
[react/text {:style styles/peer-text} (str "port: " port)]]]]))
(defn peers-summary-section [peers]
(mapv peer-view peers))
(defn- data [app-version node-version]
[{:type :small
:title (i18n/label :t/privacy-policy)
:accessibility-label :privacy-policy
:on-press
#(re-frame/dispatch
[:privacy-policy/privacy-policy-button-pressed])
:accessories [:chevron]}
[copyable-text/copyable-text-view
{:copied-text (str app-version "; " node-version)}
[list-item/list-item
{:type :small
:title (i18n/label :t/version)
:accessibility-label :version
:accessories [(str app-version "; " node-version)]}]]])
(views/defview about-app []
(views/letsubs [app-version [:get-app-short-version]
peers [:peers-summary]
mailserver [:mailserver/current-id]
node-info [:about-app/node-info]
node-version [:get-app-node-version]]
[react/view {:flex 1}
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar (i18n/label :t/about-app)]
[react/scroll-view
[react/view
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/privacy-policy
:accessibility-label :privacy-policy
:action-fn #(re-frame/dispatch [:privacy-policy/privacy-policy-button-pressed])}]
(when status-im.utils.platform/ios?
[profile.components/settings-item-separator])
[profile.components/settings-item
{:item-text (i18n/label :t/version {:version app-version})
:action-fn #(react/copy-to-clipboard app-version)
:accessibility-label :version
:hide-arrow? true}]
(when status-im.utils.platform/ios?
[profile.components/settings-item-separator])
[profile.components/settings-item
{:item-text node-version
:action-fn #(react/copy-to-clipboard node-version)
:accessibility-label :version
:hide-arrow? true}]
[profile.components/settings-item
{:item-text mailserver
:action-fn #(react/copy-to-clipboard (str mailserver))
:accessibility-label :mailserver
:hide-arrow? true}]
[profile.components/settings-item
{:item-text (i18n/label :t/copy-info)
:action-fn #(react/copy-to-clipboard
(app-info->json
app-version
peers
mailserver
node-info
node-version))
:accessibility-label :copy-to-clipboard
:hide-arrow? true}]
[react/view {:style styles/about-title}
[react/text {:style styles/about-title-text} (i18n/label :t/node-info)]]
[peer-view {:enode (:enode node-info)}]
[react/view {:style styles/about-title}
[react/text {:style styles/about-title-text} (i18n/label :t/peers)]]
[react/view
(map peer-view peers)]]]]))
[toolbar/simple-toolbar
(i18n/label :t/about-app)]
[list/flat-list
{:data (data app-version node-version)
:key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]]))

View File

@ -0,0 +1,173 @@
(ns status-im.ui.screens.advanced-settings.views
(:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn- normal-mode-settings-data [network-name current-log-level
current-fleet dev-mode?]
[{:type :small
:title :t/network
:accessibility-label :network-button
:container-margin-top 8
:on-press
#(re-frame/dispatch [:navigate-to :network-settings])
:accessories [network-name :chevron]}
;; TODO - uncomment when implemented
;; {:type :small
;; :title :t/les-ulc
;; :accessibility-label :log-level-settings-button
;; :accessories [:t/ulc-enabled :chevron]}
{:type :small
:title :t/log-level
:accessibility-label :log-level-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :log-level-settings])
:accessories [current-log-level :chevron]}
{:type :small
:title :t/fleet
:accessibility-label :fleet-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :fleet-settings])
:accessories [current-fleet :chevron]}
{:type :small
:title :t/bootnodes
:accessibility-label :bootnodes-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :bootnodes-settings])
:accessories [:chevron]}
{:type :small
:title :t/dev-mode
:accessibility-label :dev-mode-settings-switch
:container-margin-bottom 8
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/dev-mode-switched (not dev-mode?)])
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value dev-mode?
:on-value-change
#(re-frame/dispatch
[:multiaccounts.ui/dev-mode-switched (not dev-mode?)])
:disabled false}]]}
list-item/divider])
(defn- dev-mode-settings-data [settings chaos-mode? supported-biometric-auth]
[{:container-margin-top 8
:type :section-header
:title :t/dev-mode-settings}
{:type :small
:title :t/datasync
:accessibility-label :datasync-settings-switch
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value (boolean (:datasync? settings))
:on-value-change
#(re-frame/dispatch [:multiaccounts.ui/toggle-datasync %])
:disabled false}]]
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/toggle-datasync
((complement boolean) (:datasync? settings))])}
{:type :small
:title :t/v1-messages
:accessibility-label :v1-messages-settings-switch
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value (boolean (:v1-messages? settings))
:on-value-change
#(re-frame/dispatch [:multiaccounts.ui/toggle-v1-messages %])
:disabled false}]]
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/toggle-v1-messages
((complement boolean) (:v1-messages? settings))])}
{:type :small
:title :t/disable-discovery-topic
:accessibility-label :discovery-topic-settings-switch
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value (boolean (:disable-discovery-topic? settings))
:on-value-change
#(re-frame/dispatch [:multiaccounts.ui/toggle-disable-discovery-topic %])
:disabled false}]]
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/toggle-disable-discovery-topic
((complement boolean) (:disable-discovery-topic? settings))])}
{:type :small
:title :t/chaos-mode
:accessibility-label :chaos-mode-settings-switch
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/chaos-mode-switched (not chaos-mode?)])
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value chaos-mode?
:on-value-change
#(re-frame/dispatch
[:multiaccounts.ui/chaos-mode-switched (not chaos-mode?)])
:disabled false}]]}
{:type :small
:title :t/biometric-auth-setting-label
:container-margin-bottom 8
:accessibility-label :biometric-auth-settings-switch
:disabled? (not (some? supported-biometric-auth))
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value (boolean (:biometric-auth? settings))
:on-value-change
#(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched %])
:disabled (not (some? supported-biometric-auth))}]]
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/biometric-auth-switched
((complement boolean) (:biometric-auth? settings))])}
[react/view {:height 24}]])
(defn- flat-list-data [network-name current-log-level current-fleet
dev-mode? settings chaos-mode? supported-biometric-auth]
(if dev-mode?
(into
(normal-mode-settings-data
network-name current-log-level current-fleet dev-mode?)
(dev-mode-settings-data
settings chaos-mode? supported-biometric-auth))
;; else
(normal-mode-settings-data
network-name current-log-level current-fleet dev-mode?)))
(views/defview advanced-settings []
(views/letsubs [{:keys
[chaos-mode?
dev-mode?
settings]
:as current-multiaccount} [:multiaccount]
settings [:multiaccount-settings]
network-name [:network-name]
current-log-level [:settings/current-log-level]
current-fleet [:settings/current-fleet]
supported-biometric-auth [:supported-biometric-auth]]
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/advanced)]
[list/flat-list
{:data (flat-list-data
network-name current-log-level
current-fleet dev-mode? settings
chaos-mode? supported-biometric-auth)
:key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]]))

View File

@ -27,8 +27,8 @@
[list-item/list-item
{:on-press #(re-frame/dispatch [:browser.ui/browser-item-selected browser-id])
:title name
:subtitle (or url (i18n/label :t/dapp))
:image [react/view styles/browser-icon-container
:subtitle (or url :t/dapp)
:icon [react/view styles/browser-icon-container
[vector-icons/icon :main-icons/browser {:color colors/gray}]]}]])
(def dapp-image-data {:image (resources/get-image :dapp-store) :width 768 :height 333})

View File

@ -21,12 +21,12 @@
{:title dapp
:accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :manage-dapps-permissions {:dapp dapp :permissions permissions}])
:image d-icon})
:icon d-icon})
(defn prepare-items-manage [permission]
{:title (case permission
constants/dapp-permission-web3 (i18n/label :t/wallet)
constants/dapp-permission-contact-code (i18n/label :t/contact-code))
constants/dapp-permission-web3 :t/wallet
constants/dapp-permission-contact-code :t/contact-code)
:type :small
:accessories [:check]})

View File

@ -1,35 +1,46 @@
(ns status-im.ui.screens.help-center.views
(:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.screens.help-center.styles :as styles]
[status-im.utils.platform :as platform]
[status-im.ui.screens.profile.components.views :as profile.components]))
[status-im.ui.components.list.views :as list]
[status-im.ui.components.colors :as colors]
[status-im.utils.platform :as platform]))
(views/defview help-center []
[react/view styles/wrapper
(def data
[{:type :small
:title :t/faq
:accessibility-label :faq-button
:on-press
#(.openURL (react/linking)
(if platform/desktop?
"https://status.im/docs/FAQ-desktop.html"
"https://status.im/docs/FAQs.html"))
:accessories [:chevron]}
{:type :small
:title :t/submit-bug
:accessibility-label :submit-bug-button
:on-press
#(re-frame/dispatch [:logging.ui/send-logs-pressed])
:accessories [:chevron]}
{:type :small
:title :t/request-feature
:accessibility-label :request-a-feature-button
:on-press
#(re-frame/dispatch [:chat.ui/start-public-chat
(if platform/desktop?
"status-desktop"
"status")
{:navigation-reset? false}])
:accessories [:chevron]}])
(defn help-center []
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/help-center)]
[react/scroll-view
[react/view
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/faq
:accessibility-label :faq-button
:action-fn #(.openURL (react/linking)
(if platform/desktop?
"https://status.im/docs/FAQ-desktop.html"
"https://status.im/docs/FAQs.html"))}]
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/ask-in-status
:accessibility-label :submit-bug-button
:action-fn #(re-frame/dispatch [:chat.ui/start-public-chat
(if platform/desktop?
"status-desktop"
"status")
{:navigation-reset? false}])}]]]])
(i18n/label :t/need-help)]
[list/flat-list
{:data data
:key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]])

View File

@ -0,0 +1,12 @@
(ns status-im.ui.screens.language-settings.views
(:require [status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn language-settings []
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/language)]])

View File

@ -0,0 +1,13 @@
(ns status-im.ui.screens.notifications-settings.views
(:require [status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn notifications-settings []
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/notifications)]])

View File

@ -0,0 +1,83 @@
(ns status-im.ui.screens.privacy-and-security-settings.views
(:require-macros [status-im.utils.views :as views])
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn- list-data [show-backup-seed? settings]
[{:type :section-header
:title :t/security
:container-margin-top 6}
{:type :small
:title :t/back-up-seed-phrase
:accessibility-label :back-up-recovery-phrase-button
;; TODO - remove container bottom margin
;; when items below are implemented
:container-margin-bottom 8
:on-press
#(re-frame/dispatch [:navigate-to :backup-seed])
:accessories
[(when show-backup-seed? [components.common/counter {:size 22} 1])
:chevron]}
;; TODO - uncomment when implemented
;; {:type :small
;; :title :t/change-password
;; :accessories [:chevron]}
;; {:type :small
;; :title :t/change-passcode
;; :accessories [:chevron]
;; :container-margin-bottom 8}
list-item/divider
{:container-margin-top 8
:type :section-header
:title :t/privacy}
{:type :small
:title :t/set-dapp-access-permissions
:on-press #(re-frame/dispatch [:navigate-to :dapps-permissions])
:accessibility-label :dapps-permissions-button
:accessories [:chevron]}
{:type :small
:title :t/hide-content-when-switching-apps
:accessories
[[react/switch
{:track-color #js {:true colors/blue :false nil}
:value (boolean (boolean (:preview-privacy? settings)))
:on-value-change
#(re-frame/dispatch
[:multiaccounts.ui/preview-privacy-mode-switched %])
:disabled false}]]
:on-press
#(re-frame/dispatch
[:multiaccounts.ui/preview-privacy-mode-switched
((complement boolean) (:preview-privacy? settings))])
:container-margin-bottom 8}
list-item/divider
;; TODO - uncomment when implemented
(comment
{:container-margin-top 8
:type :small
:title :t/delete-my-account
:container-margin-bottom 24
:theme :action-destructive})])
(views/defview privacy-and-security []
(views/letsubs [{:keys [seed-backed-up? mnemonic]} [:multiaccount]
settings [:multiaccount-settings]]
(let [show-backup-seed? (and (not seed-backed-up?)
(not (string/blank? mnemonic)))
data (list-data show-backup-seed? settings)]
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/privacy-and-security)]
[list/flat-list
{:data data
:key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]])))

View File

@ -15,9 +15,9 @@
:justify-content :center})
(defstyle profile-name-text
{:typography :header
:line-height 28
:text-align :left})
{:typography :header
:line-height 28
:text-align :left})
(defstyle profile-name-text-with-subtitle
{:margin-vertical 5

View File

@ -34,7 +34,10 @@
[react/view (if with-subtitle? styles/profile-header-name-container-with-subtitle
styles/profile-header-name-container)
[react/text {:style (if with-subtitle? styles/profile-name-text-with-subtitle
styles/profile-name-text)}
styles/profile-name-text)
:number-of-lines 2
:ellipsize-mode :tail}
(multiaccounts/displayed-name contact)]
(when with-subtitle?
[react/text {:style styles/profile-three-words

View File

@ -1,16 +1,18 @@
(ns status-im.ui.screens.profile.user.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require-macros [status-im.utils.views :as views])
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.i18n :as i18n]
[status-im.ethereum.stateofus :as stateofus]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.bottom-bar.styles :as tabs.styles]
[status-im.ui.components.button.view :as button]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.large-toolbar :as large-toolbar]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.list.views :as list.views]
[status-im.ui.components.qr-code-viewer.views :as qr-code-viewer]
@ -20,16 +22,13 @@
[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.utils.config :as config]
[status-im.utils.identicon :as identicon]
[status-im.utils.platform :as platform]
[status-im.utils.universal-links.core :as universal-links]
[status-im.ethereum.stateofus :as stateofus]))
[status-im.utils.universal-links.core :as universal-links]))
(defview share-chat-key []
(letsubs [{:keys [address]} [:popover/popover]
window-width [:dimensions/window-width]
{:keys [names preferred-name]} [:ens.main/screen]]
(views/defview share-chat-key []
(views/letsubs [{:keys [address]} [:popover/popover]
window-width [:dimensions/window-width]
{:keys [names preferred-name]} [:ens.main/screen]]
(let [username (stateofus/username preferred-name)
qr-width (- window-width 128)
name (or username preferred-name)
@ -40,8 +39,9 @@
(when (seq names)
[react/view
[copyable-text/copyable-text-view
{:label :t/ens-usernames
:copied-text preferred-name}
{:label :t/ens-usernames
:container-style {:margin-top 12 :margin-bottom 4}
:copied-text preferred-name}
[react/nested-text
{:style {:line-height 22 :font-size 15
:font-family "monospace"}
@ -51,8 +51,9 @@
[react/view {:height 1 :margin-top 12 :margin-horizontal -16
:background-color colors/gray-lighter}]])
[copyable-text/copyable-text-view
{:label :t/chat-key
:copied-text address}
{:label :t/chat-key
:container-style {:margin-top 12 :margin-bottom 4}
:copied-text address}
[react/text {:number-of-lines 1
:ellipsize-mode :middle
:accessibility-label :chat-key
@ -67,195 +68,6 @@
:style {:height 44 :margin-horizontal 0}
:accessibility-label :share-my-contact-code-button}]]]])))
(defn- my-profile-settings [{:keys [seed-backed-up? mnemonic]}
{:keys [settings]}
logged-in?]
(let [show-backup-seed? (and (not seed-backed-up?) (not (string/blank? mnemonic)))]
[react/view
[profile.components/settings-title (i18n/label :t/settings)]
(when (and config/hardwallet-enabled?
platform/android?)
[profile.components/settings-item {:label-kw :t/status-keycard
:accessibility-label :keycard-button
:action-fn #(re-frame/dispatch [:profile.ui/keycard-settings-button-pressed])}])
[profile.components/settings-item {:label-kw :t/notifications
:accessibility-label :notifications-button
:action-fn #(.openURL (react/linking) "app-settings://notification/status-im")}]
[profile.components/settings-item-separator]
[profile.components/settings-item {:label-kw :t/mobile-network-settings
:accessibility-label :notifications-button
:action-fn #(re-frame/dispatch [:navigate-to :mobile-network-settings])}]
(when show-backup-seed?
[profile.components/settings-item-separator])
(when show-backup-seed?
[profile.components/settings-item
{:label-kw :t/backup-your-recovery-phrase
:accessibility-label :back-up-recovery-phrase-button
:action-fn #(re-frame/dispatch [:navigate-to :backup-seed])
:icon-content [components.common/counter {:size 22} 1]}])
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/devices
:action-fn #(re-frame/dispatch [:navigate-to :installations])
:accessibility-label :pairing-settings-button}]
[profile.components/settings-item-separator]
[profile.components/settings-switch-item
{:label-kw :t/preview-privacy
:value (boolean (:preview-privacy? settings))
:action-fn #(re-frame/dispatch [:multiaccounts.ui/preview-privacy-mode-switched %])}]
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/dapps-permissions
:accessibility-label :dapps-permissions-button
:action-fn #(re-frame/dispatch [:navigate-to :dapps-permissions])}]
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/need-help
:accessibility-label :help-button
:action-fn #(re-frame/dispatch [:navigate-to :help-center])}]
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/about-app
:accessibility-label :about-button
:action-fn #(re-frame/dispatch [:navigate-to :about-app])}]
[profile.components/settings-item-separator]
[react/view styles/my-profile-settings-logout-wrapper
[react/view styles/my-profile-settings-logout
[profile.components/settings-item {:label-kw :t/logout
:accessibility-label :log-out-button
:destructive? true
:hide-arrow? true
:active? logged-in?
:action-fn #(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}]]]]))
(defview advanced-settings
[{:keys [chaos-mode? dev-mode? settings]} network-name on-show supported-biometric-auth]
{:component-did-mount on-show}
[react/view
(when dev-mode?
[profile.components/settings-item
{:label-kw :t/network
:value network-name
:action-fn #(re-frame/dispatch [:navigate-to :network-settings])
:accessibility-label :network-button}])
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/offline-messaging
:action-fn #(re-frame/dispatch [:navigate-to :offline-messaging-settings])
:accessibility-label :offline-messages-settings-button}]
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/log-level
:action-fn #(re-frame/dispatch [:navigate-to :log-level-settings])
:accessibility-label :log-level-settings-button}]
(when dev-mode?
[react/view styles/my-profile-settings-send-logs-wrapper
[react/view styles/my-profile-settings-send-logs
[profile.components/settings-item {:label-kw :t/send-logs
:destructive? true
:hide-arrow? true
:action-fn #(re-frame/dispatch [:logging.ui/send-logs-pressed])}]]])
[profile.components/settings-item-separator]
[profile.components/settings-item
{:label-kw :t/fleet
:action-fn #(re-frame/dispatch [:navigate-to :fleet-settings])
:accessibility-label :fleet-settings-button}]
(when config/bootnodes-settings-enabled?
[profile.components/settings-item-separator])
(when config/bootnodes-settings-enabled?
[profile.components/settings-item
{:label-kw :t/bootnodes
:action-fn #(re-frame/dispatch [:navigate-to :bootnodes-settings])
:accessibility-label :bootnodes-settings-button}])
(when dev-mode?
[profile.components/settings-item-separator])
(when dev-mode?
[profile.components/settings-switch-item
{:label-kw :t/datasync
:value (:datasync? settings)
:action-fn #(re-frame/dispatch [:multiaccounts.ui/toggle-datasync %])}])
(when dev-mode?
[profile.components/settings-item-separator])
(when dev-mode?
[profile.components/settings-switch-item
{:label-kw :t/v1-messages
:value (:v1-messages? settings)
:action-fn #(re-frame/dispatch [:multiaccounts.ui/toggle-v1-messages %])}])
(when dev-mode?
[profile.components/settings-item-separator])
(when dev-mode?
[profile.components/settings-switch-item
{:label-kw :t/disable-discovery-topic
:value (:disable-discovery-topic? settings)
:action-fn #(re-frame/dispatch [:multiaccounts.ui/toggle-disable-discovery-topic %])}])
[profile.components/settings-item-separator]
[profile.components/settings-switch-item
{:label-kw :t/dev-mode
:value dev-mode?
:action-fn #(re-frame/dispatch [:multiaccounts.ui/dev-mode-switched %])}]
[profile.components/settings-item-separator]
[profile.components/settings-switch-item
{:label-kw :t/chaos-mode
:value chaos-mode?
:action-fn #(re-frame/dispatch [:multiaccounts.ui/chaos-mode-switched %])}]
(when dev-mode?
[profile.components/settings-item-separator]
[profile.components/settings-switch-item
{:label-kw :t/biometric-auth-setting-label
:value (:biometric-auth? settings)
:active? (some? supported-biometric-auth)
:action-fn #(re-frame/dispatch [:multiaccounts.ui/biometric-auth-switched %])}])])
(defview advanced [multiaccount network-name on-show]
(letsubs [advanced? [:my-profile/advanced?]
supported-biometric-auth [:supported-biometric-auth]]
{:component-will-unmount #(re-frame/dispatch [:set :my-profile/advanced? false])}
[react/view {:padding-bottom 16}
[react/touchable-highlight {:on-press #(re-frame/dispatch [:set :my-profile/advanced? (not advanced?)])
:style styles/advanced-button}
[react/view {:style styles/advanced-button-container}
[react/view {:style styles/advanced-button-container-background}
[react/view {:style styles/advanced-button-row}
[react/text {:style styles/advanced-button-label}
(i18n/label :t/advanced)]
[icons/icon (if advanced? :main-icons/dropdown-up :main-icons/dropdown) {:color colors/blue}]]]]]
(when advanced?
[advanced-settings multiaccount network-name on-show supported-biometric-auth])]))
(defn contacts-list-item [active-contacts-count]
[list.views/big-list-item
{:text (i18n/label :t/contacts)
:icon :main-icons/in-contacts
:accessibility-label :notifications-button
:accessory-value active-contacts-count
:action-fn #(re-frame/dispatch [:navigate-to :contacts-list])}])
(defn- ens-item [name {:keys [registrar] :as props}]
[react/view {:style {:margin-top 8}}
[list.views/big-list-item
(let [enabled? (not (nil? registrar))]
(merge
{:text (or name (i18n/label :t/ens-usernames))
:subtext (if enabled?
(if name (i18n/label :t/ens-your-your-name) (i18n/label :t/ens-usernames-details))
(i18n/label :t/ens-network-restriction))
:icon :main-icons/username
:accessibility-label :ens-button}
(if enabled?
{:action-fn #(re-frame/dispatch [:navigate-to :ens-main props])}
{:icon-color colors/gray
:active? false
:hide-chevron? (not enabled?)})))]])
(defn tribute-to-talk-item
[opts]
[list.views/big-list-item
(merge {:text (i18n/label :t/tribute-to-talk)
:accessibility-label :notifications-button
:action-fn #(re-frame/dispatch
[:tribute-to-talk.ui/menu-item-pressed])}
opts)])
(defn- header [{:keys [public-key photo-path] :as account}]
[profile.components/profile-header
{:contact account
@ -283,37 +95,115 @@
:height 24}
:handler #(re-frame/dispatch [:show-popover {:view :share-chat-key :address public-key}])}]])
(defview my-profile []
(letsubs [list-ref (reagent/atom nil)
{:keys [public-key photo-path preferred-name]
:as current-multiaccount} [:multiaccount]
network-name [:network-name]
changed-multiaccount [:my-profile/profile]
currency [:wallet/currency]
login-data [:multiaccounts/login]
active-contacts-count [:contacts/active-count]
tribute-to-talk [:tribute-to-talk/profile]
stateofus-registrar [:ens.stateofus/registrar]]
(let [shown-multiaccount (merge current-multiaccount changed-multiaccount)
;; We scroll on the component once rendered. setTimeout is necessary,
;; likely to allow the animation to finish.
on-show-advanced
(fn [] (js/setTimeout #(.scrollToEnd @list-ref {:animated false}) 300))
(defn tribute-to-talk-item
[opts]
[list.views/big-list-item
(merge {:text (i18n/label :t/tribute-to-talk)
:accessibility-label :notifications-button
:action-fn #(re-frame/dispatch
[:tribute-to-talk.ui/menu-item-pressed])}
opts)])
;; toolbar-contents
header-in-toolbar (header-in-toolbar shown-multiaccount)
toolbar-action-items (toolbar-action-items public-key)
(defn- flat-list-content [preferred-name registrar tribute-to-talk
active-contacts-count show-backup-seed?]
[(cond-> {:title (or preferred-name :t/ens-usernames)
:subtitle (if (boolean registrar)
(if preferred-name
:t/ens-your-your-name
:t/ens-usernames-details)
:t/ens-network-restriction)
:subtitle-max-lines (if (boolean registrar)
(if preferred-name 1 2)
1)
:accessibility-label :ens-button
:container-margin-top 8
:disabled? (if (boolean registrar)
false
((complement boolean) preferred-name))
:accessories [:chevron]
:icon :main-icons/username}
(or (boolean registrar) preferred-name)
(assoc :on-press #(re-frame/dispatch [:navigate-to :ens-main registrar])))
;; TODO replace this with list-item config map
;; left it as it is because not sure how to enable it for testing
(when tribute-to-talk [tribute-to-talk-item tribute-to-talk])
{:title :t/contacts
:icon :main-icons/in-contacts
:accessibility-label :contacts-button
:accessories [(if (pos? active-contacts-count)
(str active-contacts-count)
:t/none)
:chevron]
:on-press #(re-frame/dispatch [:navigate-to :contacts-list])}
{:type :section-header
:accessibility-label :settings-section
:container-margin-top 16
:title :t/settings}
{:icon :main-icons/security
:title :t/privacy-and-security
:accessibility-label :privacy-and-security-settings-button
:accessories
[(when show-backup-seed?
[components.common/counter {:size 22} 1]) :chevron]
:on-press #(re-frame/dispatch [:navigate-to :privacy-and-security])}
{:icon :main-icons/notification
:title :t/notifications
:accessibility-label :notifications-button
;; TODO commented out for now, uncomment when notifications-settings view
;; is populated. Then remove :on-press below
;; :on-press #(re-frame/dispatch [:navigate-to :notifications-settings])
:on-press #(.openURL (react/linking) "app-settings://notification/status-im")
:accessories [:chevron]}
{:icon :main-icons/mobile
:title :t/sync-settings
:accessibility-label :sync-settings-button
:accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :sync-settings])}
{:icon :main-icons/settings-advanced
:title :t/advanced
:accessibility-label :advanced-button
:accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :advanced-settings])}
{:icon :main-icons/help
:title :t/need-help
:accessibility-label :help-button
:accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :help-center])}
{:icon :main-icons/info
:title :t/about-app
:accessibility-label :about-button
:accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :about-app])}
{:icon :main-icons/log_out
:title :t/sign-out
:accessibility-label :log-out-button
:container-margin-top 24
:container-margin-bottom 24
:theme :action-destructive
:on-press
#(re-frame/dispatch [:multiaccounts.logout.ui/logout-pressed])}])
;; flatlist contents
header (header shown-multiaccount)
content
[[ens-item preferred-name {:registrar stateofus-registrar}]
[contacts-list-item active-contacts-count]
(when tribute-to-talk [tribute-to-talk-item tribute-to-talk])
[my-profile-settings current-multiaccount shown-multiaccount
currency (nil? login-data)]
(when (nil? login-data) [advanced shown-multiaccount network-name on-show-advanced])]]
[(react/safe-area-view) {:style {:flex 1}}
(views/defview my-profile []
(views/letsubs [list-ref (reagent/atom nil)
{:keys [public-key
preferred-name
seed-backed-up?
mnemonic]
:as multiaccount} [:multiaccount]
active-contacts-count [:contacts/active-count]
tribute-to-talk [:tribute-to-talk/profile]
registrar [:ens.stateofus/registrar]]
(let [show-backup-seed? (and (not seed-backed-up?)
(not (string/blank? mnemonic)))
content (flat-list-content
preferred-name registrar tribute-to-talk
active-contacts-count show-backup-seed?)]
[(react/safe-area-view) {:style {:flex 1
:margin-bottom tabs.styles/tabs-diff}}
[status-bar/status-bar {:type :main}]
[large-toolbar/minimized-toolbar header-in-toolbar nil toolbar-action-items]
[large-toolbar/flat-list-with-large-header header content list-ref]])))
[large-toolbar/minimized-toolbar
(header-in-toolbar multiaccount)
nil
(toolbar-action-items public-key)]
[large-toolbar/flat-list-with-large-header
(header multiaccount) content list-ref]])))

View File

@ -11,14 +11,19 @@
:ens-name-details
:blocked-users-list
:profile-photo-capture
:about-app
:bootnodes-settings
:installations
:edit-bootnode
:offline-messaging-settings
:edit-mailserver
:help-center
:dapps-permissions
:privacy-and-security
:language-settings
:notifications-settings
:sync-settings
:advanced-settings
:help-center
:about-app
:manage-dapps-permissions
:network-settings
:network-details

View File

@ -17,6 +17,11 @@
[status-im.ui.screens.contacts-list.views :as contacts-list]
[status-im.ui.screens.currency-settings.views :as currency-settings]
[status-im.ui.screens.dapps-permissions.views :as dapps-permissions]
[status-im.ui.screens.privacy-and-security-settings.views :as privacy-and-security]
[status-im.ui.screens.language-settings.views :as language-settings]
[status-im.ui.screens.notifications-settings.views :as notifications-settings]
[status-im.ui.screens.sync-settings.views :as sync-settings]
[status-im.ui.screens.advanced-settings.views :as advanced-settings]
[status-im.ui.screens.fleet-settings.views :as fleet-settings]
[status-im.ui.screens.group.views :as group]
[status-im.ui.screens.hardwallet.authentication-method.views
@ -157,14 +162,19 @@
:ens-name-details ens/name-details
:blocked-users-list contacts-list/blocked-users-list
:profile-photo-capture photo-capture/profile-photo-capture
:about-app about-app/about-app
:bootnodes-settings bootnodes-settings/bootnodes-settings
:installations pairing/installations
:edit-bootnode edit-bootnode/edit-bootnode
:offline-messaging-settings offline-messaging-settings/offline-messaging-settings
:edit-mailserver edit-mailserver/edit-mailserver
:help-center help-center/help-center
:dapps-permissions dapps-permissions/dapps-permissions
:privacy-and-security privacy-and-security/privacy-and-security
:language-settings language-settings/language-settings
:notifications-settings notifications-settings/notifications-settings
:sync-settings sync-settings/sync-settings
:advanced-settings advanced-settings/advanced-settings
:help-center help-center/help-center
:about-app about-app/about-app
:manage-dapps-permissions dapps-permissions/manage
:network-settings network/network-settings-view
:network-details network/network-details-view

View File

@ -21,9 +21,6 @@
(def message
{:background-color :white
:flex-grow 1
:flex-shrink 1
:flex-basis 600
:border-top-right-radius 16
:border-top-left-radius 16
:padding-bottom 40})
@ -42,4 +39,4 @@
{:background-color :white
:border-top-right-radius 16
:border-top-left-radius 16
:padding-bottom 40})
:padding-bottom 40})

View File

@ -8,6 +8,7 @@
[reagent.core :as reagent]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.button.view :as button]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.wallet.utils :as wallet.utils]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.chat-icon.screen :as chat-icon]
@ -56,23 +57,40 @@
(:address contact)))
(defn contact-item [title contact]
[list-item/list-item {:type :small
:title title
:accessories [[react/text {:ellipsize-mode :middle :number-of-lines 1 :style {:flex-wrap :wrap}}
(displayed-name contact)]]}])
[list-item/list-item
{:title-prefix title
:title-prefix-width 45
:type :small
:title
[copyable-text/copyable-text-view
{:copied-text (displayed-name contact)}
[react/text
{:ellipsize-mode :middle
:number-of-lines 1
:style {:color colors/gray
:font-family "monospace"
;; since this goes in list-item title
;; which has design constraints
;; specified in figma spec,
;; better to do this
:line-height 22}}
(displayed-name contact)]]}])
(defn token-item [{:keys [icon color] :as token} display-symbol]
(when token
[react/view
[list-item/list-item
{:type :small :title (i18n/label :t/wallet-asset)
:accessories [[acc-text (:name token) display-symbol]
(if icon
[list/item-image (assoc icon
:style {:background-color colors/gray-lighter
:border-radius 16}
:image-style {:width 32 :height 32})]
[chat-icon/custom-icon-view-list (:name token) color 32])]}]
{:type :small
:title :t/wallet-asset
:accessories
[display-symbol
(if icon
[list/item-image
(assoc icon
:style {:background-color colors/gray-lighter
:border-radius 16}
:image-style {:width 24 :height 24})]
[chat-icon/custom-icon-view-list (:name token) color 32])]}]
[separator]]))
(defn header [{:keys [in-progress?] :as sign} {:keys [contact amount token approve?] :as tx} display-symbol fee fee-display-symbol]
@ -227,17 +245,25 @@
[token-item token display-symbol]
(when-not approve?
[react/view
[list-item/list-item {:type :small :title (i18n/label :t/send-request-amount)
:error amount-error
:accessories [[acc-text (if amount (str amount) "0")
(or display-symbol fee-display-symbol)]]}]
[list-item/list-item
{:type :small
:title :t/send-request-amount
:error amount-error
:accessories
[[acc-text (if amount (str amount) "0")
(or display-symbol fee-display-symbol)]]}]
[separator]])
[list-item/list-item
{:type :small :title (i18n/label :t/network-fee) :error gas-error
{:type :small
:title :t/network-fee
:error gas-error
:accessories [[acc-text fee fee-display-symbol] :chevron]
:on-press #(re-frame/dispatch [:signing.ui/open-fee-sheet
{:content (fn [] [sheets/fee-bottom-sheet fee-display-symbol])
:content-height 270}])}]
:on-press
#(re-frame/dispatch
[:signing.ui/open-fee-sheet
{:content
(fn [] [sheets/fee-bottom-sheet fee-display-symbol])
:content-height 270}])}]
[react/view {:align-items :center :margin-top 16 :margin-bottom 40}
(if keycard-multiaccount?
[sign-with-keycard-button amount-error gas-error]
@ -276,10 +302,10 @@
[react/keyboard-avoiding-view {:style {:position :absolute :top 0 :bottom 0 :left 0 :right 0}}
[react/view {:flex 1}
[react/animated-view {:flex 1 :background-color :black :opacity alpha-value}]
[react/animated-view {:style {:position :absolute :bottom 0 :top -40 :left 0 :right 0
:transform [{:translateY bottom-anim-value}]}}
[react/animated-view {:style {:position :absolute
:transform [{:translateY bottom-anim-value}]
:bottom 0 :left 0 :right 0}}
[react/view {:flex 1}
[react/view {:flex-shrink 2.5 :flex-grow 2.5 :flex-basis 600}]
(if (:message @current-tx)
[message-sheet]
[sheet @current-tx])]]]]))})))

View File

@ -0,0 +1,52 @@
(ns status-im.ui.screens.sync-settings.views
(:require-macros [status-im.utils.views :as views])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.view :as toolbar]))
(defn- list-data [mailserver-id use-mobile-data?]
(let [mobile-data-usage-state (if use-mobile-data?
:t/mobile-network-use-mobile
:t/mobile-network-use-wifi)]
[{:container-margin-top 8
:type :section-header
:title :t/message-syncing}
{:type :small
:title :t/mobile-network-settings
:accessibility-label :notifications-button
:on-press
#(re-frame/dispatch [:navigate-to :mobile-network-settings])
:accessories [mobile-data-usage-state :chevron]}
{:type :small
:title :t/offline-messaging
:accessibility-label :offline-messages-settings-button
:on-press
#(re-frame/dispatch [:navigate-to :offline-messaging-settings])
:accessories [mailserver-id :chevron]
:container-margin-bottom 8}
list-item/divider
{:container-margin-top 8
:type :section-header
:title :t/device-syncing}
{:type :small
:title :t/devices
:accessibility-label :pairing-settings-button
:on-press #(re-frame/dispatch [:navigate-to :installations])
:accessories [:chevron]}]))
(views/defview sync-settings []
(views/letsubs [{:keys [syncing-on-mobile-network?]} [:multiaccount]
mailserver-id [:mailserver/current-id]]
[react/view {:flex 1 :background-color colors/white}
[status-bar/status-bar]
[toolbar/simple-toolbar
(i18n/label :t/sync-settings)]
[list/flat-list
{:data (list-data mailserver-id syncing-on-mobile-network?)
:key-fn (fn [_ i] (str i))
:render-fn list/flat-list-generic-render-fn}]]))

View File

@ -50,9 +50,6 @@
(= view :public-chat-actions)
(merge home.sheet/public-chat-actions)
(= view :learn-more)
(merge about-app/learn-more)
(= view :keycard.login/more)
(merge keycard/more-sheet)

View File

@ -71,30 +71,25 @@
(defn render-asset [currency]
(fn [{:keys [icon decimals amount color value] :as token}]
[list-item/list-item
{:content [react/view {:style {:margin-horizontal 16 :justify-content :center :flex-shrink 1}}
[react/view {:flex-direction :row}
[react/text {:style {:font-weight "500" :flex-shrink 0.5} :number-of-lines 1 :ellipsize-mode :tail}
(wallet.utils/format-amount amount decimals)]
[react/text {:style {:font-weight "500" :color colors/gray :margin-left 6}
:number-of-lines 1}
(wallet.utils/display-symbol token)]]
(when value
[react/text {:style {:color colors/gray}} (str value " " currency)])]
:image (if icon
[list/item-image icon]
[chat-icon/custom-icon-view-list (:name token) color])}]))
{:title-prefix (wallet.utils/format-amount amount decimals)
:title (wallet.utils/display-symbol token)
:title-color-override colors/gray
:subtitle (str (if value value 0) " " currency)
:icon (if icon
[list/item-image icon]
[chat-icon/custom-icon-view-list (:name token) color])}]))
(defn render-collectible [{:keys [name icon amount] :as collectible}]
(let [items-number (money/to-fixed amount)
details? (pos? items-number)]
[react/touchable-highlight
(when details?
{:on-press #(re-frame/dispatch [:show-collectibles-list collectible])})
[list-item/list-item
{:title (wallet.utils/display-symbol collectible)
:subtitle name
:image [list/item-image icon]
:accessories [items-number :chevron]}]]))
[list-item/list-item
{:title (wallet.utils/display-symbol collectible)
:subtitle name
:icon [list/item-image icon]
:on-press (when details?
#(re-frame/dispatch
[:show-collectibles-list collectible]))
:accessories [items-number :chevron]}]))
(views/defview assets-and-collections []
(views/letsubs [{:keys [tokens nfts]} [:wallet/all-visible-assets-with-values]

View File

@ -6,7 +6,6 @@
[status-im.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list-header.views :as list-header]
[status-im.ui.components.list-item.views :as list-item]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.icons.vector-icons :as icons]
@ -27,10 +26,17 @@
[react/text {:style {:color colors/gray :text-align :center :margin-top 16 :line-height 22}}
(i18n/label :t/add-account-description)]]
[react/view {:height 52}]
[list-header/list-header (i18n/label :t/default)]
[list-item/list-item {:title (i18n/label :t/generate-a-new-account) :theme :action
:icon :main-icons/add :accessories [:chevron]
:on-press #(re-frame/dispatch [:navigate-to :add-new-account-password])}]]])
[list-item/list-item
{:type :section-header
:title :t/default}]
[list-item/list-item
{:title :t/generate-a-new-account
:theme :action
:icon :main-icons/add
:accessories [:chevron]
:on-press
#(re-frame/dispatch
[:navigate-to :add-new-account-password])}]]])
(defview colors-popover [selected-color]
(letsubs [width [:dimensions/window-width]]
@ -124,4 +130,4 @@
:on-press #(re-frame/dispatch
[:wallet.accounts/generate-new-account @entered-password])
:disabled? (not (spec/valid? ::multiaccounts.db/password @entered-password))
:forward? true}]]]]))
:forward? true}]]]]))

View File

@ -215,6 +215,7 @@
"removed": "removed",
"empty-topic": "Empty topic",
"message": "Message",
"message-syncing": "Message syncing",
"image-source-title": "Edit picture",
"left": "left",
"to": "To",
@ -467,6 +468,8 @@
"start-chat": "Start chat",
"wallet-onboarding-title": "Simple and secure cryptocurrency wallet",
"logout": "Log out",
"sign-out": "Sign out",
"delete-my-account": "Delete my account",
"status-not-sent-tap": "Not confirmed. Tap for options",
"status-not-sent-click": "Not confirmed. Click for options",
"send-logs": "Report a bug",
@ -597,6 +600,11 @@
"currency-display-name-czk": "Czech Koruna",
"currency-display-name-bob": "Bolivia Bolíviano",
"privacy-policy": "Privacy Policy",
"privacy-and-security": "Privacy and security",
"language": "Language",
"sync-settings": "Sync settings",
"security": "Security",
"privacy": "Privacy",
"currency-display-name-lak": "Laos Kip",
"recipient-code": "Enter recipient address",
"fleet": "Fleet",
@ -645,6 +653,7 @@
"at": "at",
"off": "Off",
"dev-mode": "Development mode",
"dev-mode-settings": "Development mode settings",
"chaos-mode": "Chaos mode",
"intro-text-description": "A community-powered platform to securely chat and transact on the Ethereum blockchain",
"currency-display-name-kwd": "Kuwaiti Dinar",
@ -752,7 +761,7 @@
"your-contact-code": "Granting access authorizes this DApp to retrieve your contact code",
"password-placeholder": "At least 6 characters",
"clear-history-action": "Clear",
"version": "Version {{version}}",
"version": "Version",
"specify-mailserver-address": "Specify a mailserver address",
"scan-qr-code": "Scan a QR code with a wallet address",
"wallet-total-value": "Total value",
@ -760,6 +769,8 @@
"mailserver-address": "Mailserver address",
"add": "Add",
"bootnodes-settings": "Bootnodes settings",
"les-ulc": "LES/ULC",
"ulc-enabled": "ULC enabled",
"allowing-authorizes-this-dapp": "Allowing authorizes this DApp to retrieve your wallet address and enable Web3",
"currency-display-name-srd": "Suriname Dollar",
"transaction-request": "Transaction Request",
@ -832,6 +843,7 @@
"currency-display-name-uah": "Ukraine Hryvnia",
"web3-opt-in": "Browser privacy mode",
"preview-privacy": "Preview privacy mode",
"hide-content-when-switching-apps": "Hide content when switching apps",
"recover-password-invalid": "This multiaccount already exists but passwords do not match",
"recover-keycard-multiaccount-not-supported": "Recovering keycard multiaccount with password is not supported",
"members-active-none": "no members",
@ -901,6 +913,7 @@
"puk-and-pairing-codes-displayed": "PUK and pairing codes displayed",
"begin-keycard-setup-confirmation-text": "Setup will erase your card including the keys already stored on your card. Would you like to continue?",
"device-pairing": "Device pairing",
"device-syncing": "Device syncing",
"something-went-wrong": "Something went wrong",
"try-again": "Try again",
"taking-long-hold-phone-connected": "This will take a few seconds.\n Hold card connected to the phone.",
@ -915,6 +928,8 @@
"login-pin-description": "Enter your PIN code to login\nto your multiaccount",
"new-pin-description": "Enter new PIN code",
"change-pin": "Change PIN",
"change-password": "Change Password",
"change-passcode": "Change Passcode",
"enter-pin": "Enter PIN",
"enter-pin-description": "Enter your PIN code to login\n to your multiaccount",
"create-pin": "Create PIN",
@ -1041,6 +1056,7 @@
"mailserver-error-title": "Error connecting to mailserver",
"mailserver-error-content": "The mailserver you selected couldn't be reached.",
"dapps-permissions": "DApp permissions",
"set-dapp-access-permissions": "Set DApp access permissions",
"revoke-access": "Revoke access",
"extensions-camera-send-picture": "Send picture",
"extensions-network-not-found": "network not found for the given chain-id",
@ -1061,6 +1077,7 @@
"waiting-for-wifi-change": "Change",
"mobile-network-settings": "Mobile data",
"mobile-network-use-mobile": "Use mobile data",
"mobile-network-use-wifi": "Wi-Fi only",
"mobile-network-use-mobile-details": "Status tends to use a lot of data when syncing chats. You can choose not to sync when on mobile network",
"mobile-network-ask-me": "Ask me when on mobile network",
"mobile-network-go-to-settings": "Go to settings",
@ -1198,6 +1215,7 @@
"add-account" : "Add account",
"add-an-account" : "Add an account",
"back-up-your-seed-phrase" : "Back up your recovery phrase",
"back-up-seed-phrase" : "Back up Seed phrase",
"add-a-watch-account" : "Add a watch-only account",
"account-settings" : "Account settings",
"export-account" : "Export account",

View File

@ -35,6 +35,8 @@
"bootnode-address": "Dirección de bootnode",
"bootnode-details": "Detalles de Bootnode",
"bootnodes": "Bootnodes",
"les-ulc": "LES/ULC",
"ulc-enabled": "ULC enabled",
"bootnodes-enabled": "Bootnodes activados",
"bootnodes-settings": "Ajustes de bootnode",
"browser": "Navegador",
@ -630,7 +632,7 @@
"use-valid-qr-code": "Este código QR no contiene un enlace universal, código de contacto o nombre de usuario válido: {{data}}",
"validation-amount-invalid-number": "El importe no es un número válido",
"validation-amount-is-too-precise": "La cantidad es muy precisa. La cantidad máxima de decimales es {{decimals}} .",
"version": "Versión {{version}}",
"version": "Versión",
"view-cryptokitties": "Ver en CryptoKitties",
"view-cryptostrikers": "Ver en CryptoStrikers",
"view-etheremon": "Ver en Etheremon",

View File

@ -635,7 +635,7 @@
"use-valid-qr-code": "این کد QR حاوی لینک جهانی، کد تماس یا نام کاربری معتبری نیست: {{data}}",
"validation-amount-invalid-number": "مقدار وارد شده صحیح نیست",
"validation-amount-is-too-precise": "مقدار را بیش از حد دقیق وارد کرده اید. حداکثر تعداد اعشار {{decimals}} است.",
"version": "نسخه {{version}}",
"version": "نسخه",
"view-cryptokitties": "مشاهده در CryptoKitties",
"view-cryptostrikers": "مشاهده در CryptoStrikers",
"view-etheremon": "مشاهده در Etheremon",

View File

@ -1180,7 +1180,7 @@
"v1-messages-warning-title": "Attention, fonctionnalité expérimentale",
"validation-amount-invalid-number": "Le montant n'est pas un nombre valide",
"validation-amount-is-too-precise": "Le montant est trop précis. Le nombre maximum de décimales est {{decimals}} .",
"version": "Version {{version}}",
"version": "Version",
"view-cryptokitties": "Voir dans CryptoKitties",
"view-cryptostrikers": "Afficher dans CryptoStrikers",
"view-etheremon": "Voir dans Etheremon",

View File

@ -1183,7 +1183,7 @@
"v1-messages-warning-title": "警告、これは実験的な機能です",
"validation-amount-invalid-number": "金額が正しくありません",
"validation-amount-is-too-precise": "金額が細かすぎます。小数点以下を{{decimals}}桁以下にしてください。",
"version": "バージョン{{version}}",
"version": "バージョン",
"view-cryptokitties": "CryptoKittiesで表示",
"view-cryptostrikers": "CryptoStrikersで表示",
"view-etheremon": "Etheremonで表示",

View File

@ -1179,7 +1179,7 @@
"v1-messages-warning-title": "경고, 테스트 중인 기능임",
"validation-amount-invalid-number": "잘못된 수량입니다",
"validation-amount-is-too-precise": "액수가 너무 정확합니다. 최대 소수점 자리수는 {{decimals}}입니다.",
"version": "버전 {{version}}",
"version": "버전",
"view-cryptokitties": "CryptoKitties에서 보기",
"view-cryptostrikers": "CryptoStrikers에서보기",
"view-etheremon": "Etheremon에서보기",

View File

@ -683,7 +683,7 @@
"use-valid-qr-code": "Kod QR ini tidak mengandungi pautan sejagat, kod pengenalan atau nama pengguna yang sah: {{data}}",
"validation-amount-invalid-number": "Jumlah bukan nombor yang sah",
"validation-amount-is-too-precise": "Jumlah terlalu banyak. Jumlah maksimum perpuluhan adalah {{decimals}} .",
"version": "Versi {{version}}",
"version": "Versi",
"view-cryptokitties": "Lihat di CryptoKitties",
"view-cryptostrikers": "Lihat di CryptoStrikers",
"view-etheremon": "Lihat di Etheremon",

View File

@ -659,7 +659,7 @@
"use-valid-qr-code": "Kod QR ini tidak mengandungi pautan sejagat, kod pengenalan atau nama pengguna yang sah: {{data}}",
"validation-amount-invalid-number": "राशि वैध संख्या होइन",
"validation-amount-is-too-precise": "Jumlah terlalu banyak. Jumlah maksimum perpuluhan adalah {{decimals}} .",
"version": "Versi {{version}}",
"version": "Version",
"view-cryptokitties": "CryptoKitties मा हेर्नुहोस्",
"view-cryptostrikers": "Lihat di CryptoStrikers",
"view-etheremon": "Etheremon मा हेर्नुहोस्",

View File

@ -615,7 +615,7 @@
"use-valid-qr-code": "Ten kod QR nie zawiera prawidłowego linku, kodu kontaktowego lub nazwy użytkownika: {{data}}",
"validation-amount-invalid-number": "Kwota nie jest prawidłową liczbą",
"validation-amount-is-too-precise": "Kwota jest zbyt dokładna. Maksymalna liczba miejsc po przecinku wynosi {{decimals}}.",
"version": "Wersja {{version}}",
"version": "Wersja",
"view-cryptokitties": "Zobacz w CryptoKitties",
"view-cryptostrikers": "Zobacz w CryptoStrikers",
"view-etheremon": "Zobacz w Etheremon",

View File

@ -1211,7 +1211,7 @@
"v1-messages-warning-title": "Предупреждение, экспериментальная функция",
"validation-amount-invalid-number": "Сумма недействительна",
"validation-amount-is-too-precise": "Слишком много чисел после запятой. {{decimals}} - это максимальное допустимое количество знаков после запятой.",
"version": "Версия {{version}}",
"version": "Версия",
"view-cryptokitties": "Посмотреть в CryptoKitties",
"view-cryptostrikers": "Посмотреть в CryptoStrikers",
"view-etheremon": "Посмотреть в Etheremon",

View File

@ -1187,7 +1187,7 @@
"v1-messages-warning-title": "警告,实验性功能",
"validation-amount-invalid-number": "金额不是一个有效的数字",
"validation-amount-is-too-precise": "金额过于精确所能发送的最小单位是1 Wei (1x10^-18 ETH)",
"version": "{{version}} 版本",
"version": "版本",
"view-cryptokitties": "在CryptoKitties中查看",
"view-cryptostrikers": "在 CryptoStrikers 中查看",
"view-etheremon": "在Etheremon中查看",

View File

@ -1131,7 +1131,7 @@
"use-valid-qr-code": "此二维码未包含有效的通用链接,联系人代码或用户名: {{data}}",
"validation-amount-invalid-number": "金额不是一个有效的数字",
"validation-amount-is-too-precise": "金额过于精确所能发送的最小单位是1 Wei (1x10^-18 ETH)",
"version": "{{version}} 版本",
"version": "版本",
"view-cryptokitties": "在CryptoKitties中查看",
"view-cryptostrikers": "在 CryptoStrikers 中查看",
"view-etheremon": "在Etheremon中查看",