Compare commits

..
Author SHA1 Message Date
Volodymyr Kozieiev 6239ab7b9d Added component desciription 2023-08-29 16:04:32 +01:00
Volodymyr Kozieiev b84cc6c54e Wallet activity component 2023-08-25 13:40:43 +01:00
Ulises M bc168cb94e Add issue for wroing text style 2023-08-14 16:49:54 -06:00
Ulises M 294913c05b Add issue for multinetwork variant 2023-08-14 16:30:18 -06:00
Ulises M 1b42c9d58e Update use of group-avatar api 2023-08-14 13:52:33 -06:00
Ulises M 3c6e6e19c7 Fix code style 2023-08-14 12:49:30 -06:00
Ulises M e7b8f188e1 add map style argument to style/container 2023-08-14 12:47:27 -06:00
Ulises M b8d51a404e Remove unused require 2023-08-14 12:45:04 -06:00
Ulises M 027f35906b Lint fix 2023-08-14 12:44:06 -06:00
Ulises M d513690290 Remove theme/provider alias 2023-08-14 12:44:06 -06:00
Ulises M 7101be0dac Rename alias 2023-08-14 12:44:05 -06:00
Ulises M 7d12f75977 remove nil nil params 2023-08-14 12:44:05 -06:00
Ulises M 35b2cc582d Updates context-tag previous uses 2023-08-14 12:44:04 -06:00
Ulises M ca648e7153 Add missing context-tags variants and fix the API to match figma 2023-08-14 12:36:15 -06:00
Ulises M e12a0d1596 Add size 20 for preview-list 2023-08-14 12:36:15 -06:00
Ulises M 7a8c0ab724 Add icon-name to group avatar 2023-08-14 12:35:54 -06:00
Ulises M 8f9d78d359 Add size 28 for user-avatar 2023-08-14 12:32:55 -06:00
108 changed files with 2608 additions and 1947 deletions
+5 -5
View File
@@ -95,11 +95,11 @@ status-im.hardwallet.simulated-keycard/sign-typed-data
status-im.utils.core/safe-read-message-content
status-im.ui.components.react/native-modules
status-im.ui.components.react/progress-bar
react-native.fs/move-file
react-native.fs/read-dir
react-native.fs/mkdir
react-native.fs/unlink
react-native.fs/file-exists?
status-im.utils.fs/move-file
status-im.utils.fs/read-dir
status-im.utils.fs/mkdir
status-im.utils.fs/unlink
status-im.utils.fs/file-exists?
quo.animated/code
quo.animated/eq
quo.animated/neq
+5 -3
View File
@@ -16,7 +16,7 @@ The responsibilities of the team are to implement the new wallet UI, with the su
## Decision
The team members for the initial wallet team are:
Some team members have already expressed interest and some have been asked and accepted to join the wallet team, these team members are:
- @rasom
- @OmarBasem
@@ -25,5 +25,7 @@ The team members for the initial wallet team are:
- @briansztamfater
- @smohamedjavid
- @ulisesmac
- @erikseppanen
- @mmilad75
# Follow-up Actions
- We still need 3/4 team members to join the wallet team
+1 -1
View File
@@ -33,7 +33,7 @@ The people identified for each sections are as follow:
- Messaging @flexsurfer, followed by @alwx
- Syncing & Onboarding @siddarthkay
- Communities @ilmotta, followed by @ajayesivan
- Communities @ilmotta
- Activity Center & Shell @J-Son89, followed by @Parveshdhull
- Wallet (once the vertical team is created) @J-Son89, followed by @briansztamfater
Binary file not shown.

After

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

+1 -2
View File
@@ -90,8 +90,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
:configureNext (fn [])}
:requireNativeComponent (fn [] {:propTypes ""})
:Appearance {:getColorScheme (fn [])
:addChangeListener (fn [])}
:PixelRatio {:get (fn [])}}))
:addChangeListener (fn [])}}))
(set! js/ReactNative react-native)
@@ -3,12 +3,12 @@
(defn container
[{:keys [container-size customization-color theme]}]
{:width container-size
:height container-size
:align-items :center
:justify-content :center
:border-radius (/ container-size 2)
:overflow :hidden
:background-color (colors/theme-colors (colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme)})
{:width container-size
:height container-size
:align-items :center
:justify-content :center
:border-radius (/ container-size 2)
:background-color
(colors/theme-colors (colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme)})
@@ -1,35 +1,43 @@
(ns quo2.components.avatars.group-avatar.view
(:require [quo2.components.icon :as icon]
[quo2.theme :as theme]
[quo2.theme :as quo.theme]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[quo2.components.avatars.group-avatar.style :as style]))
(def sizes
{20 {:icon 12}
28 {:icon 16}
32 {:icon 16}
48 {:icon 20}
80 {:icon 32}})
{:icon {:x-small 12
:small 16
:medium 16
:large 20
:x-large 32}
:container {:x-small 20
:small 28
:medium 32
:large 48
:x-large 80}})
(defn- view-internal
[_]
(fn [{:keys [size theme customization-color picture]
:or {size 20
customization-color :blue}}]
(let [icon-size (get-in sizes [size :icon])]
(fn [{:keys [size theme customization-color picture icon-name]
:or {size :x-small
customization-color :blue
picture nil
icon-name :i/group}}]
(let [container-size (get-in sizes [:container size])
icon-size (get-in sizes [:icon size])]
[rn/view
{:style (style/container {:container-size size
{:style (style/container {:container-size container-size
:customization-color customization-color
:theme theme})}
(if picture
[fast-image/fast-image
{:source picture
:style {:width size
:height size}}]
[icon/icon :i/members
:style {:width container-size
:height container-size}}]
[icon/icon icon-name
{:size icon-size
:color colors/white-opa-70}])])))
(def view (theme/with-theme view-internal))
(def view (quo.theme/with-theme view-internal))
@@ -2,9 +2,14 @@
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
[test-helpers.component :as h]))
(defonce mock-picture {:uri (js/require "../resources/images/mock2/user_picture_male4.png")})
(defonce mock-picture (js/require "../resources/images/mock2/user_picture_male4.png"))
(h/describe "user avatar"
(h/test "Default render"
(h/render [user-avatar/user-avatar])
(h/is-truthy (h/get-by-label-text :user-avatar))
(h/is-truthy (h/get-by-text "EN")))
(h/describe "Profile picture"
(h/test "Renders"
(h/render
@@ -13,5 +18,124 @@
(h/test "Renders even if `:full-name` is passed"
(h/render
[user-avatar/user-avatar {:profile-picture mock-picture}])
(h/is-truthy (h/get-by-label-text :profile-picture)))))
[user-avatar/user-avatar
{:profile-picture mock-picture
:full-name "New User1"}])
(h/is-truthy (h/get-by-label-text :profile-picture))
(h/is-null (h/query-by-label-text :initials-avatar)))
(h/describe "Status indicator"
(h/test "Render"
(h/render
[user-avatar/user-avatar
{:profile-picture mock-picture
:status-indicator? true}])
(h/is-truthy (h/get-by-label-text :profile-picture))
(h/is-truthy (h/get-by-label-text :status-indicator)))
(h/test "Do not render"
(h/render
[user-avatar/user-avatar
{:profile-picture mock-picture
:status-indicator? false}])
(h/is-truthy (h/get-by-label-text :profile-picture))
(h/is-null (h/query-by-label-text :status-indicator)))))
(h/describe "Initials Avatar"
(h/describe "Render initials"
(letfn [(user-avatar-component [size]
[user-avatar/user-avatar
{:full-name "New User"
:size size}])]
(h/describe "Two letters"
(h/test "Size :big"
(h/render (user-avatar-component :big))
(h/is-truthy (h/get-by-text "NU")))
(h/test "Size :medium"
(h/render (user-avatar-component :medium))
(h/is-truthy (h/get-by-text "NU")))
(h/test "Size :small"
(h/render (user-avatar-component :small))
(h/is-truthy (h/get-by-text "NU")))
(h/test "Two letters with excess whitespace"
(h/render [user-avatar/user-avatar
{:full-name "New User"
:size :big}])
(h/is-truthy (h/get-by-text "NU")))
(h/test "Two letters with leading whitespace"
(h/render [user-avatar/user-avatar
{:full-name " New User"
:size :big}])
(h/is-truthy (h/get-by-text "NU"))))
(h/describe "One letter"
(h/test "Size :xs"
(h/render (user-avatar-component :xs))
(h/is-truthy (h/get-by-text "N")))
(h/test "Size :xxs"
(h/render (user-avatar-component :xxs))
(h/is-truthy (h/get-by-text "N")))
(h/test "Size :xxxs"
(h/render (user-avatar-component :xxxs))
(h/is-truthy (h/get-by-text "N"))))))
(h/describe "Render ring"
(letfn [(user-avatar-component [size]
[user-avatar/user-avatar
{:full-name "New User"
:ring-background mock-picture
:size size}])]
(h/describe "Passed and drawn"
(h/test "Size :big"
(h/render (user-avatar-component :big))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-truthy (h/get-by-label-text :ring-background)))
(h/test "Size :medium"
(h/render (user-avatar-component :medium))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-truthy (h/get-by-label-text :ring-background)))
(h/test "Size :small"
(h/render (user-avatar-component :small))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-truthy (h/get-by-label-text :ring-background))))
(h/describe "Passed and not drawn (because of invalid size for ring)"
(h/test "Size :xs"
(h/render (user-avatar-component :xs))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-null (h/query-by-label-text :ring-background)))
(h/test "Size :xxs"
(h/render (user-avatar-component :xxs))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-null (h/query-by-label-text :ring-background)))
(h/test "Size :xxxs"
(h/render (user-avatar-component :xxxs))
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-null (h/query-by-label-text :ring-background))))))
(h/describe "Status indicator"
(h/test "Render"
(h/render
[user-avatar/user-avatar
{:full-name "Test User"
:status-indicator? true}])
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-truthy (h/get-by-label-text :status-indicator)))
(h/test "Do not render"
(h/render
[user-avatar/user-avatar
{:full-name "Test User"
:status-indicator? false}])
(h/is-truthy (h/get-by-label-text :initials-avatar))
(h/is-null (h/query-by-label-text :status-indicator))))))
@@ -2,61 +2,97 @@
(:require [quo2.foundations.colors :as colors]))
(def sizes
{:big {:dimensions 80
{:big {:outer 80
:inner 72
:status-indicator 20
:status-indicator-border 4
:font-size :heading-1}
:medium {:dimensions 48
:medium {:outer 48
:inner 44
:status-indicator 12
:status-indicator-border 2
:font-size :heading-2}
:small {:dimensions 32
:small {:outer 32
:inner 28
:status-indicator 12
:status-indicator-border 2
:font-size :paragraph-2}
:xs {:dimensions 24
28 {:outer 28
:inner 28
:status-indicator 0
:status-indicator-border 0
:font-size :paragraph-2}
:xxs {:dimensions 20
:xs {:outer 24
:inner 24
:status-indicator 0
:status-indicator-border 0
:font-size :paragraph-2}
:xxs {:outer 20
:inner 20
:status-indicator 0
:status-indicator-border 0
:font-size :label}
:xxxs {:dimensions 16
:xxxs {:outer 16
:inner 16
:status-indicator 0
:status-indicator-border 0
:font-size :label}})
(defn outer
[size]
(let [dimensions (get-in sizes [size :outer])]
{:width dimensions
:height dimensions
:border-radius dimensions}))
(defn initials-avatar
[size customization-color theme]
(let [dimensions (get-in sizes [size :dimensions])]
[size draw-ring? customization-color theme]
(let [outer-dimensions (get-in sizes [size :outer])
inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])]
{:position :absolute
:top 0
:left 0
:width dimensions
:height dimensions
:border-radius dimensions
:top (/ (- outer-dimensions inner-dimensions) 2)
:left (/ (- outer-dimensions inner-dimensions) 2)
:width inner-dimensions
:height inner-dimensions
:border-radius inner-dimensions
:justify-content :center
:align-items :center
:background-color (colors/custom-color-by-theme customization-color 50 60 nil nil theme)}))
(def indicator-color
{:online colors/success-50
:offline colors/neutral-40})
(defn outer
[size static-profile-picture?]
(let [dimensions (get-in sizes [size :dimensions])
outer-style {:width dimensions
:height dimensions}
outer-style-with-border-radius (assoc outer-style :border-radius dimensions)]
(if static-profile-picture?
outer-style-with-border-radius
outer-style)))
(defn customization-color
[color-id theme]
(colors/custom-color-by-theme color-id 50 60 nil nil theme))
(def initials-avatar-text
{:color colors/white-opa-70})
(defn inner-dot
[size online?]
(let [background (if online? colors/success-50 colors/neutral-40)
dimensions (get-in sizes [size :status-indicator])]
{:width (- dimensions 4)
:height (- dimensions 4)
:border-radius (- dimensions 4)
:background-color background}))
(defn dot
[size ring? theme]
(let [dimensions (get-in sizes [size :status-indicator])
border-width (get-in sizes [size :status-indicator-border])
right (case size
:big 2
:medium 0
:small -2
0)
bottom (case size
:big (if ring? -1 2)
:medium (if ring? 0 -2)
:small -2
0)]
{:position :absolute
:justify-content :center
:align-items :center
:bottom bottom
:right right
:width dimensions
:height dimensions
:border-width border-width
:border-radius dimensions
:background-color (colors/theme-colors colors/white colors/neutral-100 theme)
:border-color (colors/theme-colors colors/white colors/neutral-100 theme)}))
@@ -1,104 +1,64 @@
(ns quo2.components.avatars.user-avatar.view
(:require
[quo2.components.avatars.user-avatar.style :as style]
[quo2.components.common.no-flicker-image :as no-flicker-image]
[quo2.components.markdown.text :as text]
[quo2.theme]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
utils.string))
(:require [quo2.components.avatars.user-avatar.style :as style]
[quo2.components.markdown.text :as text]
[quo2.theme :as quo.theme]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
utils.string))
(defn initials-avatar
[{:keys [full-name size customization-color theme]}]
[{:keys [full-name size draw-ring? customization-color theme]}]
(let [font-size (get-in style/sizes [size :font-size])
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)]
[rn/view
{:accessibility-label :initials-avatar
:style (style/initials-avatar size customization-color theme)}
:style (style/initials-avatar size draw-ring? customization-color theme)}
[text/text
{:style style/initials-avatar-text
:size font-size
:weight :semi-bold}
(utils.string/get-initials full-name amount-initials)]]))
(defn user-avatar-internal
"Render user avatar with `profile-picture`
`profile-picture` should be one of {:uri profile-picture-uri} or {:fn profile-picture-fn}
(def valid-ring-sizes #{:big :medium :small})
`profile-picture-fn` should return an image URI, there's helper fn to generate
it in `utils.image-server`
params for `profile-picture-fn`
{:length initials' length
:full-name used to generate initials
:font-size initials font size
:indicator-size status indicator outer radius, set to nil or 0 when no indicator
:indicator-border `indicator-size`-`indicator-border` is the inner radius
:indicator-color color for status indicator
:override-theme override theme for ring
:background-color intials avatar background color
:color intials avatar text color
:size intials avatar radius
:ring? render ident ring around avatar?}
supported color formats:
#RRGGBB
#RRGGBBAA
rgb(255,255,255)
rgba(255,255,255,0.1) note alpha is 0-1
the reason we use the `profile-picture-fn` here is to separate
logic (pubkey, key-uid... in subs) and style (color, size... in this component)"
[{:keys [full-name size profile-picture customization-color static?
status-indicator? online? ring? theme]
:or {size :big
status-indicator? true
(defn- user-avatar-internal
"If no `profile-picture` is given, draws the initials based on the `full-name` and
uses `ring-background` to display the ring behind the initials when given. Otherwise,
shows the `profile-picture` which already comes with the ring drawn."
[{:keys [full-name status-indicator? online? size profile-picture ring-background
customization-color static? muted? theme ring?]
:or {status-indicator? true
online? true
ring? true
customization-color :turquoise}
:as props}]
(let [full-name (or full-name "Your Name")
;; image generated with profile-picture-fn is round cropped
;; no need to add border-radius for them
outer-styles (style/outer size (not (:fn profile-picture)))
;; Once image is loaded, fast image re-renders view with the help of reagent atom,
size :big
customization-color :turquoise}}]
(let [full-name (or full-name "empty name")
draw-ring? (and ring? (when-not muted? (and ring-background (valid-ring-sizes size))))
outer-styles (style/outer size)
;; Once image is loaded, fast image rerenders view with the help of reagent atom,
;; But dynamic updates don't work when user-avatar is used inside hole-view
;; https://github.com/status-im/status-mobile/issues/15553
image-view (if static? no-flicker-image/image fast-image/fast-image)
font-size (get-in style/sizes [size :font-size])
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)
sizes (get style/sizes size)
indicator-color (get style/indicator-color (if online? :online :offline))
profile-picture-fn (:fn profile-picture)]
image-view (if static? rn/image fast-image/fast-image)]
[rn/view {:style outer-styles :accessibility-label :user-avatar}
(if (and full-name (not (or profile-picture-fn profile-picture)))
;; this is for things that's not user-avatar
;; but are currently using user-avatar to render the initials
;; e.g. community avatar
[initials-avatar props]
;; The `profile-picture` already has the ring in it
(when-let [image (or profile-picture ring-background)]
[image-view
{:accessibility-label :profile-picture
:style outer-styles
:source
(cond profile-picture-fn
{:uri (profile-picture-fn
{:length amount-initials
:full-name full-name
:font-size (:font-size (text/text-style {:size
font-size}))
:indicator-size (when status-indicator?
(:status-indicator sizes))
:indicator-border (when status-indicator?
(:status-indicator-border sizes))
:indicator-color indicator-color
:override-theme theme
:background-color (style/customization-color customization-color theme)
:color (:color style/initials-avatar-text)
:size (:width outer-styles)
:ring? ring?})}
(:uri profile-picture)
profile-picture
:else {:uri profile-picture})}])]))
{:accessibility-label (if draw-ring? :ring-background :profile-picture)
:style outer-styles
:source image}])
(when-not profile-picture
[initials-avatar
{:full-name full-name
:size size
:draw-ring? draw-ring?
:customization-color customization-color
:theme theme}])
(when status-indicator?
[rn/view
{:accessibility-label :status-indicator
:style (style/dot size draw-ring? theme)}
[rn/view
{:accessibility-label :inner-status-indicator-dot
:style (style/inner-dot size online?)}]])]))
(def user-avatar (quo2.theme/with-theme user-avatar-internal))
(def user-avatar (quo.theme/with-theme user-avatar-internal))
@@ -1,49 +0,0 @@
(ns quo2.components.common.no-flicker-image
(:require
[oops.core :as oops]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]))
(def cached-sources (js/Set. (js/Array.)))
(defn- caching-image
[_ on-source-loaded]
(let [this (reagent/current-component)]
(reagent/create-class
{:component-did-update
(fn []
(let [source (-> this reagent/props :source)]
(when (oops/ocall cached-sources "has" source)
(on-source-loaded source))))
:reagent-render
(fn [{:keys [source] :as props}]
[rn/image
(assoc props
;; hide the cache image under the real one
;; have to render it for the on-load event
:style {:width 1
:height 1
:left "50%"
:top "50%"
:position :absolute}
:on-load
(fn [_]
(when-not (oops/ocall cached-sources "has" source)
(oops/ocall cached-sources "add" source)
(on-source-loaded source)))
:on-error js/console.error)])})))
(defn image
"Same as rn/image but cache the image source in a js/Set, so the image won't
flicker when re-render on android"
[]
(let [loaded-source (reagent/atom nil)
on-source-loaded #(reset! loaded-source %)]
(fn [props]
(if platform/ios?
[rn/image props]
[:<>
[rn/image (assoc props :source @loaded-source)]
[caching-image props on-source-loaded]]))))
@@ -3,6 +3,23 @@
[test-helpers.component :as h]))
(h/describe "Profile Input"
(h/test "renders user avatar with placeholder name if no value is specified"
(h/render [profile-input/profile-input
{:placeholder "Your Name"
:image-picker-props {:full-name "Your Name"}}])
(-> (js/expect (h/get-by-text "YN"))
(.toBeTruthy)))
(h/test "renders user avatar with full name if a value is specified"
(let [event (h/mock-fn)]
(h/render [profile-input/profile-input
{:on-change event
:placeholder "Your Name"
:image-picker-props {:full-name "Test Name"}}])
(h/fire-event :change (h/get-by-text "TN"))
(-> (js/expect (h/get-by-text "TN"))
(.toBeTruthy))))
(h/test "on press event fires"
(let [event (h/mock-fn)]
(h/render [profile-input/profile-input
@@ -1,7 +1,7 @@
(ns quo2.components.inputs.profile-input.view
(:require
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.buttons.button.view :as buttons]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.inputs.profile-input.style :as style]
[quo2.components.inputs.title-input.view :as title-input]
[react-native.core :as rn]
@@ -13,40 +13,38 @@
on-press
title-input-props
image-picker-props]}]
(let [full-name (:full-name image-picker-props)]
[rn/view
{:style (style/container customization-color)}
[rn/view
[hole-view/hole-view
;; Force re-render hole view when props are changed
;; https://github.com/status-im/status-mobile/issues/15577
{:key (hash
(if (:profile-picture image-picker-props)
(:profile-picture image-picker-props)
image-picker-props))
:holes [{:x 33
:y 24
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(assoc image-picker-props
:static? true
:status-indicator? false
:full-name (if (seq full-name) full-name placeholder)
:size :medium)]]
[buttons/button
{:accessibility-label :select-profile-picture-button
:type :grey
:background :blur
:on-press on-press
:size 24
:icon-only? true
:container-style style/button
:inner-style style/button-inner} :i/camera]]
[rn/view {:style style/input-container}
[title-input/title-input
(merge title-input-props
{:blur? true
:placeholder placeholder
:customization-color customization-color})]]]))
[rn/view
{:style (style/container customization-color)}
[rn/view
[hole-view/hole-view
;; Force re-render hole view when props are changed
;; https://github.com/status-im/status-mobile/issues/15577
{:key (hash
(if (:profile-picture image-picker-props)
(:profile-picture image-picker-props)
image-picker-props))
:holes [{:x 33
:y 24
:width 24
:height 24
:borderRadius 12}]}
[user-avatar/user-avatar
(assoc image-picker-props
:static? true
:status-indicator? false
:size :medium)]]
[buttons/button
{:accessibility-label :select-profile-picture-button
:type :grey
:background :blur
:on-press on-press
:size 24
:icon-only? true
:container-style style/button
:inner-style style/button-inner} :i/camera]]
[rn/view {:style style/input-container}
[title-input/title-input
(merge title-input-props
{:blur? true
:placeholder placeholder
:customization-color customization-color})]]])
@@ -21,6 +21,12 @@
:hole-size 26
:hole-x 19
:hole-y -1}
20 {:border-radius {:circular 11 :rounded 8}
:hole-radius {:circular 10 :rounded 9}
:margin-left -4
:hole-size 22
:hole-x 15
:hole-y -1}
16 {:border-radius {:circular 8 :rounded 8}
:hole-radius {:circular 9 :rounded 9}
:margin-left -4
@@ -38,6 +44,7 @@
:size (case size
32 :small
24 :xs
20 :xxs
16 :xxxs)}
item)]
(:photo :collectible) [fast-image/fast-image
@@ -47,11 +54,10 @@
:border-radius border-radius}}]))
(defn list-item
[index type size item list-size margin-left
hole-size hole-radius hole-x hole-y border-radius]
(let [last-item? (= index (- list-size 1))]
[index type size item list-size margin-left hole-size hole-radius hole-x hole-y border-radius]
(let [last-item? (= index (dec list-size))]
[hole-view/hole-view
{:style {:margin-left (if (= index 0) 0 margin-left)}
{:style {:margin-left (if (zero? index) 0 margin-left)}
:holes (if last-item?
[]
[{:x hole-x
@@ -122,8 +128,7 @@
items preview list items (only 4 items is required for preview)
"
[{:keys [type size list-size transparent? theme more-than-99-label]} items]
(let [items-arr (into [] items)
list-size (or list-size (count items))
(let [list-size (or list-size (count items))
margin-left (get-in params [size :margin-left])
hole-size (get-in params [size :hole-size])
border-radius (get-in params [size :border-radius (border-type type)])
@@ -133,7 +138,7 @@
[rn/view {:style {:flex-direction :row}}
(for [index (range (if (> list-size 4) 3 list-size))]
^{:key (str index list-size)}
[list-item index type size (get items-arr index) list-size
[list-item index type size (get (vec items) index) list-size
margin-left hole-size hole-radius hole-x hole-y border-radius])
(when (> list-size 4)
[overflow-label
+10 -9
View File
@@ -1,11 +1,11 @@
(ns quo2.components.list-items.user-list
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.icon :as icons]
(:require [react-native.core :as rn]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.markdown.text :as text]
[quo2.components.messages.author.view :as author]
[quo2.components.selectors.selectors.view :as selectors]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]))
[quo2.components.messages.author.view :as author]
[quo2.components.selectors.selectors.view :as selectors]))
(def container-style
{:margin-horizontal 8
@@ -45,10 +45,11 @@
:on-press (when on-press on-press)
:on-long-press (when on-long-press on-long-press)}
[user-avatar/user-avatar
{:full-name primary-name
:profile-picture photo-path
:online? online?
:size :small}]
{:full-name primary-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small}]
[rn/view {:style {:margin-left 8}}
[author/author
{:primary-name primary-name
+10 -6
View File
@@ -1,12 +1,12 @@
(ns quo2.components.markdown.list.view
(:require [react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.counter.step.view :as step]
[quo2.components.markdown.list.style :as style]
(:require [quo2.components.counter.step.view :as step]
[quo2.components.icon :as icon]
[quo2.components.markdown.list.style :as style]
[quo2.components.markdown.text :as text]
[quo2.components.tags.context-tag.view :as context-tag]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[quo2.components.tags.context-tag.view :as context-tag]))
[react-native.core :as rn]))
(defn get-colors
[theme blur?]
@@ -27,7 +27,11 @@
:size :paragraph-2}
description]
[rn/view {:style {:margin-left 4}}
[context-tag/context-tag {:blur? blur?} tag-picture tag-name]]
[context-tag/view
{:blur? blur?
:size 24
:profile-picture tag-picture
:full-name tag-name}]]
[text/text
{:style {:margin-left 4}
:accessibility-label :list-item-description-after-tag
@@ -1,9 +1,9 @@
(ns quo2.components.profile.select-profile.view
(:require
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.markdown.text :as text]
[quo2.components.profile.select-profile.style :as style]
[react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[reagent.core :as reagent]))
(defn- on-change-handler
@@ -24,27 +24,31 @@
(let [internal-selected? (reagent/atom (or default-selected? false))]
(fn [{:keys [selected?
profile-picture
ring-background
name
customization-color
on-change]
:or {customization-color :turquoise}}]
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
(reset! internal-selected? selected?))
[rn/touchable-opacity
{:style (style/container customization-color @internal-selected?)
:on-press #(on-change-handler internal-selected? on-change)
:active-opacity 1
:accessibility-label :select-profile}
[rn/view {:style style/header}
[user-avatar/user-avatar
{:full-name name
:status-indicator? false
:size :medium
:profile-picture profile-picture}]
[rn/view {:style (style/select-radio @internal-selected?)}
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
[text/text
{:size :heading-2
:weight :semi-bold
:style style/profile-name}
name]])))
(let [avatar-image-key (if profile-picture :profile-picture :ring-background)
picture (or profile-picture ring-background)]
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
(reset! internal-selected? selected?))
[rn/touchable-opacity
{:style (style/container customization-color @internal-selected?)
:on-press #(on-change-handler internal-selected? on-change)
:active-opacity 1
:accessibility-label :select-profile}
[rn/view {:style style/header}
[user-avatar/user-avatar
{:full-name name
:status-indicator? false
:size :medium
avatar-image-key picture}]
[rn/view {:style (style/select-radio @internal-selected?)}
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
[text/text
{:size :heading-2
:weight :semi-bold
:style style/profile-name}
name]]))))
+87 -37
View File
@@ -1,31 +1,11 @@
(ns quo2.components.tags.context-tag.style
(:require [quo2.foundations.colors :as colors]))
(defn base-tag
[override-theme blur?]
{:border-radius 100
:padding-vertical 3
:flex-direction :row
:padding-right 8
:padding-left 8
:background-color (if blur?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 override-theme)
(colors/theme-colors colors/neutral-10 colors/neutral-90 override-theme))})
(defn context-tag-icon-color
[blur?]
[theme blur?]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40)
(colors/theme-colors colors/neutral-50 colors/neutral-40)))
(def context-tag-text-container
{:align-items :center
:margin-left 4
:flex-direction :row})
(def audio-tag-container
{:padding-left 2
:padding-vertical 2})
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(def audio-tag-icon-container
{:width 20
@@ -37,21 +17,91 @@
(def audio-tag-icon-color colors/white)
(defn audio-tag-text-color
[override-theme]
(colors/theme-colors colors/neutral-100 colors/white override-theme))
(defn container
[{:keys [theme type size state blur? customization-color]}]
(let [background-color (if blur?
(colors/theme-colors colors/neutral-80-opa-5 colors/white-opa-5 theme)
(colors/theme-colors colors/neutral-10 colors/neutral-90 theme))
border-radius (cond
(not (#{:account :collectible} type)) 16
(= size 24) 8
:else 10)
border-color (colors/theme-colors
(colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme)]
(cond-> {:padding 2
:flex-direction :row
:align-items :center
:height size
:background-color background-color
:border-radius border-radius}
(= state :selected) (assoc :height (+ size 2)
:border-color border-color
:border-width 1))))
(def community-tag
{:padding-vertical 2
:padding-left 2})
(def community-tag-text-container
{:margin-left 4
:flex 1
(defn tag-container
[size]
{:margin-right (if (= size 24) 6 10)
:flex-direction :row
:align-items :center})
(defn community-tag-text
[override-theme]
{:margin-left 2
:color (colors/theme-colors colors/neutral-100 colors/white override-theme)})
(defn tag-spacing
[size]
{:margin-left (if (= size 24) 4 8)})
(defn text
[theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
(defn circle-logo
[size]
(if (= size 24)
{:width 20 :height 20 :border-radius 10}
{:width 28 :height 28 :border-radius 14}))
(defn rounded-logo
[size]
(if (= size 24)
{:width 20
:height 20
:border-radius 6}
{:width 28
:height 28
:border-radius 8}))
(defn address
[size]
(if (= size 24)
{:margin-horizontal 6
:margin-vertical 1
:flex-direction :row
:align-items :center}
{:margin-horizontal 10
:margin-vertical 3
:flex-direction :row
:align-items :center}))
(defn icon
[size]
(if (= size 24)
{:margin-horizontal 6
:margin-vertical 1
:flex-direction :row
:align-items :center}
{:margin-left 8
:margin-right 10
:margin-vertical 3
:flex-direction :row
:align-items :center}))
(defn icon-spacing
[size]
(if (= size 24)
{:margin-left 4}
{:margin-left 2}))
(def audio
{:margin-right 6
:flex-direction :row
:align-items :center})
+197 -91
View File
@@ -1,106 +1,212 @@
(ns quo2.components.tags.context-tag.view
(:require [quo2.components.avatars.group-avatar.view :as group-avatar]
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
(:require [quo2.components.avatars.account-avatar.view :as account-avatar]
[quo2.components.avatars.group-avatar.view :as group-avatar]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.icon :as icons]
[quo2.components.list-items.preview-list :as preview-list]
[quo2.components.markdown.text :as text]
[quo2.components.tags.context-tag.style :as style]
[quo2.foundations.colors :as colors]
[quo2.theme :as quo.theme]
[react-native.core :as rn]))
(defn trim-public-key
(defn- tag-skeleton
[{:keys [theme size text] :or {size 24}} logo-component]
[rn/view {:style (style/tag-container size)}
logo-component
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
text]]])
(defn- communities-tag
[{:keys [theme size community-logo community-name blur? channel? channel-name]}]
(let [text-size (if (= size 24) :paragraph-2 :paragraph-1)
icon-size (if (= size 24) 16 20)]
[rn/view {:style (style/tag-container size)}
[rn/image {:style (style/circle-logo size) :source community-logo}]
[rn/view {:style (style/tag-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size text-size}
community-name]]
(when channel?
[:<>
[icons/icon :i/chevron-right
{:color (style/context-tag-icon-color theme blur?)
:size icon-size}]
[text/text
{:style (style/text theme)
:weight :medium
:size text-size}
(str "# " channel-name)]])]))
(defn- trim-public-key
[pk]
(str (subs pk 0 6) "..." (subs pk (- (count pk) 3))))
(str (subs pk 0 5) "..." (subs pk (- (count pk) 3))))
(defn base-tag
[{:keys [override-theme style blur?]} & children]
(into
[rn/view {:style (merge (style/base-tag override-theme blur?) style)}]
children))
(defn group-avatar-tag
[label opts]
[base-tag
(-> opts
(select-keys [:override-theme :style :blur?])
(assoc-in [:style :padding-left] 3)
(assoc-in [:style :padding-vertical] 2))
[group-avatar/view opts]
(defn- address-tag
[{:keys [theme size address]}]
[rn/view {:style (style/address size)}
[text/text
{:weight :medium
:size :paragraph-2
:style (:text-style opts)}
(str " " label)]])
{:style (style/text theme)
:weight :monospace ;; TODO: fix this style (issue #17009)
:size (if (= size 24) :paragraph-2 :paragraph-1)}
(trim-public-key address)]])
(defn public-key-tag
[params public-key]
[base-tag params
[text/text
{:weight :monospace
:size :paragraph-2}
(trim-public-key public-key)]])
(defn- icon-tag
[{:keys [theme size icon blur? context]}]
[rn/view {:style (style/icon size)}
[icons/icon icon
{:color (style/context-tag-icon-color theme blur?)
:size (if (= size 24) 12 20)}]
[rn/view {:style (style/icon-spacing size)}
[text/text
{:style (style/text theme)
:weight :medium
:size (if (= size 24) :paragraph-2 :paragraph-1)}
context]]])
(defn context-tag
[{:keys [text-style blur? no-avatar-placeholder? text-container-style ellipsize-text? ring?]
:as props}
photo
name
channel-name]
(let [text-props {:weight :medium
:size :paragraph-2
:style (assoc text-style :justify-content :center)
:number-of-lines 1
:ellipsize-mode :tail}
empty-photo? (nil? photo)
avatar-size :xxs
avatar-outer-size (get-in user-avatar.style/sizes [avatar-size :outer])]
[base-tag (update-in props [:style :padding-left] #(or % 3))
(if (and empty-photo? no-avatar-placeholder?)
[rn/view {:style {:width avatar-outer-size}}]
[user-avatar/user-avatar
{:full-name name
:profile-picture photo
:size avatar-size
:ring? ring?
:status-indicator? false}])
[rn/view {:style (or text-container-style style/context-tag-text-container)}
(if ellipsize-text?
[rn/view {:style {:flex 1}}
[text/text text-props name]]
[text/text text-props (str " " name)])
(when channel-name
[:<>
[icons/icon
:i/chevron-right
{:color (style/context-tag-icon-color blur?)
:size 16}]
[text/text text-props (str "# " channel-name)]])]]))
(defn- view-internal
[{:keys [theme type size state blur? customization-color profile-picture full-name users
group-name token-logo amount token-name network-logo network-name networks
account-name emoji collectible collectible-name collectible-number duration]
:or {customization-color :blue
type :default
state :default}
:as props}]
[rn/view
{:style (style/container {:theme theme
:type type
:size size
:state state
:blur? blur?
:customization-color customization-color})}
(case type
:default
[tag-skeleton {:theme theme :size size :text full-name}
[user-avatar/user-avatar
{:full-name full-name
:profile-picture profile-picture
:size (if (= size 24) :xxs 28)
:status-indicator? false}]]
(defn user-avatar-tag
[params username photo]
[context-tag params photo username])
:multiuser
[preview-list/preview-list {:type :user :size 20}
users]
(defn audio-tag
[duration params]
[base-tag (merge {:style style/audio-tag-container} params)
[rn/view {:style style/audio-tag-icon-container}
[icons/icon
:i/play
{:color style/audio-tag-icon-color
:size 12}]]
[text/text
{:weight :medium
:size :paragraph-2
:style {:margin-left 4
:color (style/audio-tag-text-color (:override-theme params))}}
duration]])
:multinetwork ;; TODO: use multinetwork preview-list type when available (issue #17008)
[preview-list/preview-list {:type :user :size 20}
(map #(hash-map :profile-picture %) networks)]
(defn community-tag
[avatar community-name {:keys [override-theme] :as params}]
[context-tag
(merge {:style style/community-tag
:text-style (style/community-tag-text override-theme)
:text-container-style style/community-tag-text-container
:ellipsize-text? true}
params)
avatar
community-name])
:audio
[tag-skeleton {:theme theme :text (str duration)}
[rn/view {:style style/audio-tag-icon-container}
[icons/icon :i/play {:color style/audio-tag-icon-color :size 12}]]]
:group
[tag-skeleton {:theme theme :size size :text group-name}
[group-avatar/view
{:icon-name :i/members
:size (if (= size 24) :x-small :small)
:customization-color (colors/custom-color :purple 50)}]]
(:channel :community)
[communities-tag (assoc props :channel? (= type :channel))]
:token
[tag-skeleton {:theme theme :size size :text (str amount " " token-name)}
[rn/image {:style (style/circle-logo size) :source token-logo}]]
:network
[tag-skeleton {:theme theme :size size :text network-name}
[rn/image {:style (style/circle-logo size) :source network-logo}]]
:collectible
[tag-skeleton
{:theme theme
:size size
:text (str collectible-name " #" collectible-number)}
[rn/image {:style (style/rounded-logo size) :source collectible}]]
:account
[tag-skeleton {:theme theme :size size :text account-name}
[account-avatar/view {:emoji emoji :size (if (= size 24) 20 28)}]]
:address
[address-tag props]
:icon
[icon-tag props]
nil)])
(def view
"Properties:
type, state, blur? & customization-color
Depending on the `type` selected, different properties are accepted:
- `:default` or `nil`:
- size
- profile-picture
- full-name
- `:multiuser`:
- users (vector of {:profile-picture pic, :full-name \"a name\"})
- `:group`
- size
- group-name
- `:community`
- size
- community-logo (valid rn/image :source value)
- community-name
- `:channel`
- size
- community-logo (valid rn/image :source value)
- community-name
- channel-name
- `:token`
- size
- token-logo (valid rn/image :source value)
- amount
- token-name
- `:network`
- size
- network-logo (valid rn/image :source value)
- network-name
- `:multinetworks`
- networks (vector of {:network-logo pic, :network-name \"a name\"})
- `:account`
- size
- account-name
- emoji (string containing an emoji)
- `:collectible`
- size
- collectible (valid rn/image :source value)
- collectible-name
- collectible-number
- `:address`
- size
- address (string)
- `:icon`
- size
- icon
- context (string)
- `:audio`
- duration (string)
"
(quo.theme/with-theme view-internal))
@@ -0,0 +1,19 @@
(ns quo2.components.wallet.wallet-activity.component-spec
(:require [quo2.components.wallet.wallet-activity.view :as wallet-activity]
[test-helpers.component :as h]))
(def props
{})
(h/describe "Wallet activity"
(h/test "default render"
(h/render [wallet-activity/view props])
(h/is-truthy (h/query-by-label-text :wallet-activity)))
(h/test "Should call :on-press"
(let [on-press (h/mock-fn)]
(h/render [wallet-activity/view
(assoc props :on-press on-press)])
(h/is-truthy (h/query-by-label-text :wallet-activity))
(h/fire-event :press (h/query-by-label-text :wallet-activity))
(h/was-called on-press))))
@@ -0,0 +1,83 @@
(ns quo2.components.wallet.wallet-activity.style
(:require [quo2.foundations.colors :as colors]))
(defn wallet-activity-container
[{:keys [pressed?
theme
blur?]}]
(merge
{:border-radius 16
:padding-top 8
:padding-left 12
:padding-right 12
:padding-bottom 12}
(when pressed?
{:background-color (if blur?
colors/white-opa-5
(colors/theme-colors colors/neutral-5 colors/neutral-90 theme))})))
(def transaction-header-container
{:flex-direction :row
:align-items :center})
(defn transaction-header
[theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)
:margin-right 4})
(defn transaction-counter
[theme]
{:color (colors/theme-colors colors/neutral-100 colors/white theme)})
(defn transaction-counter-container
[theme blur?]
{:border-width 1
:border-radius 6
:margin-right 8
:padding-horizontal 2
:border-color (if-not blur?
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
colors/white-opa-10)})
(defn timestamp
[theme blur?]
{:color (if-not blur?
(colors/theme-colors colors/neutral-40 colors/neutral-50 theme)
colors/white-opa-40)})
(defn prop-text
[theme]
{:margin-right 4
:color (colors/theme-colors colors/neutral-100 colors/white theme)})
(def icon-container
{:width 32
:height 32
:margin-top 8})
(def content-container
{:margin-left 8})
(def content-line
{:flex-direction :row :margin-top 2 :align-items :center})
(defn icon-hole-view
[theme blur?]
{:width 32
:height 32
:border-width 1
:border-color (if-not blur?
(colors/theme-colors colors/neutral-20 colors/neutral-80 theme)
colors/white-opa-5)
:border-radius 16
:align-items :center
:justify-content :center})
(defn icon-color
[theme]
(colors/theme-colors colors/neutral-100 colors/white theme))
(def icon-status-container
{:position :absolute :bottom 0 :right 0})
@@ -0,0 +1,169 @@
(ns quo2.components.wallet.wallet-activity.view
(:require [quo2.theme :as quo.theme]
[quo2.components.wallet.wallet-activity.style :as style]
[react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.icon :as icon]
[quo2.components.tags.context-tag.view :as context-tag]
[react-native.hole-view :as hole-view]
[utils.i18n :as i18n]
[reagent.core :as reagent]))
(def transaction-translation
{:receive [i18n/label :t/receive]
:send [i18n/label :t/send]
:swap [i18n/label :t/swap]
:bridge [i18n/label :t/bridge]
:buy [i18n/label :t/buy]
:destroy [i18n/label :t/destroy]
:mint [i18n/label :t/mint]})
(def transaction-icon
{:receive :i/receive
:send :i/send
:swap :i/swap
:bridge :i/bridge
:buy :i/buy
:destroy :i/destroy
:mint :i/mint})
(def status-icon
{:pending :i/pending-state
:confirmed :i/positive-state
:finalised :i/diamond-blue
:failed :i/negative-state})
(defn transaction-header
[{:keys [transaction
timestamp
counter
theme
blur?]
:or {transaction :receive
counter 1}}]
[rn/view
{:style style/transaction-header-container}
[text/text
{:weight :semi-bold
:size :paragraph-1
:style (style/transaction-header theme)}
(transaction transaction-translation)]
(when (> counter 1)
[rn/view (style/transaction-counter-container theme blur?)
[text/text
{:weight :medium
:size :label
:style (style/transaction-counter theme)}
(str "x" counter "")]])
[rn/view
[text/text
{:weight :regular
:size :label
:style (style/timestamp theme blur?)}
timestamp]]])
(defn transaction-icon-view
[{:keys [theme blur? transaction status]
:or {transaction :receive
status :pending}}]
[rn/view {:style style/icon-container}
[hole-view/hole-view
{:style (style/icon-hole-view theme blur?)
:holes [{:x 20
:y 20
:right 0
:width 12
:height 12
:borderRadius 6}]}
[icon/icon (transaction-icon transaction)
{:color (style/icon-color theme)}]]
[rn/view {:style style/icon-status-container}
[icon/icon (status-icon status)
{:size 12
:no-color :true}]]])
(defn prop-text
[label theme]
[text/text
{:weight :regular
:size :paragraph-2
:style (style/prop-text theme)}
[i18n/label label]])
(defn prop-tag
[props]
[rn/view {:style {:margin-right 4}}
[context-tag/view (merge {:size 24} props)]])
(defn- view-internal
[_]
(let [pressed? (reagent/atom false)]
(fn
[{:keys [state theme blur?
on-press
first second third fourth
second-prefix third-prefix fourth-prefix]
:as props}]
[rn/pressable
{:style (style/wallet-activity-container {:pressed? @pressed?
:theme theme
:blur? blur?})
:accessibility-label :wallet-activity
:disabled (= state :disabled)
:on-press on-press
:on-press-in (fn [] (reset! pressed? true))
:on-press-out (fn [] (reset! pressed? false))}
[rn/view
{:style {:flex-direction :row}}
[transaction-icon-view props]
[rn/view ;content
{:style style/content-container}
[transaction-header props]
[rn/view {:style style/content-line}
(when first [prop-tag first])
(when second-prefix [prop-text second-prefix theme])
(when second [prop-tag second])]
[rn/view {:style style/content-line}
(when third-prefix [prop-text third-prefix theme])
(when third [prop-tag third])
(when fourth-prefix [prop-text fourth-prefix theme])
(when fourth [prop-tag fourth])]]]])))
(def view
"Properties:
- :transaction - type of transaction`. Possible values:
- :receive
- :send
- :swap
- :bridge
- :buy
- :destroy
- :mint
- :status - transaction status. Possible values:
- :pending
- :confirmed
- :finalised
- :failed
- :counter - amount of transactions shown by instance of the component
- :timestamp - when transaction occured (string)
- :blur?
- :first - props for context tag component that will be first on the first line
- :second - props for context tag component that will be second on the first line
- :third - props for context tag component that will be first on the second line
- :fourth - props for context tag component that will be second on the second line
- :second-prefix - translation keyword to be used with label before second context tag
- :third-prefix - translation keyword to be used with label before third context tag
- :fourth-prefix - translation keyword to be used with label before fourth context tag
"
(quo.theme/with-theme view-internal))
+5 -6
View File
@@ -114,7 +114,8 @@
quo2.components.wallet.progress-bar.view
quo2.components.wallet.summary-info.view
quo2.components.wallet.token-input.view
quo2.components.wallet.wallet-overview.view))
quo2.components.wallet.wallet-overview.view
quo2.components.wallet.wallet-activity.view))
(def separator quo2.components.common.separator.view/separator)
@@ -301,11 +302,8 @@
(def permission-tag quo2.components.tags.permission-tag/tag)
(def status-tag quo2.components.tags.status-tags/status-tag)
(def token-tag quo2.components.tags.token-tag/tag)
(def user-avatar-tag quo2.components.tags.context-tag.view/user-avatar-tag)
(def context-tag quo2.components.tags.context-tag.view/context-tag)
(def group-avatar-tag quo2.components.tags.context-tag.view/group-avatar-tag)
(def audio-tag quo2.components.tags.context-tag.view/audio-tag)
(def community-tag quo2.components.tags.context-tag.view/community-tag)
(def context-tag quo2.components.tags.context-tag.view/view)
;;;; Title
(def title quo2.components.text-combinations.title.view/title)
@@ -319,3 +317,4 @@
(def summary-info quo2.components.wallet.summary-info.view/view)
(def token-input quo2.components.wallet.token-input.view/view)
(def wallet-overview quo2.components.wallet.wallet-overview.view/view)
(def wallet-activity quo2.components.wallet.wallet-activity.view/view)
+2 -1
View File
@@ -59,4 +59,5 @@
[quo2.components.wallet.progress-bar.component-spec]
[quo2.components.wallet.summary-info.component-spec]
[quo2.components.wallet.token-input.component-spec]
[quo2.components.wallet.wallet-overview.component-spec]))
[quo2.components.wallet.wallet-overview.component-spec]
[quo2.components.wallet.wallet-activity.component-spec]))
+4
View File
@@ -28,3 +28,7 @@
{:ethereum (js/require "../resources/images/tokens/mainnet/ETH-network.png")
:optimism (js/require "../resources/images/tokens/mainnet/OP.png")
:arbitrum (js/require "../resources/images/tokens/mainnet/ARB.png")})
(defn get-network
[n]
(get networks n))
-8
View File
@@ -42,11 +42,3 @@
(defn cache-dir
[]
(.-CachesDirectoryPath ^js react-native-fs))
(defn copy-assets
[src dest]
(.copyFileAssets ^js react-native-fs src dest))
(defn main-bundle-path
[]
(.-MainBundlePath ^js react-native-fs))
+2 -8
View File
@@ -1,6 +1,6 @@
(ns status-im.contact.core
(:require [status-im2.navigation.events :as navigation]
[utils.re-frame :as rf]))
(:require [utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]))
(rf/defn open-contact-toggle-list
{:events [:contact.ui/start-group-chat-pressed]}
@@ -10,9 +10,3 @@
:group/selected-contacts #{}
:new-chat-name "")}
(navigation/navigate-to :contact-toggle-list nil)))
(defn displayed-photo
[{:keys [images]}]
(or (:large images)
(:thumbnail images)
(first images)))
+9 -10
View File
@@ -1,13 +1,13 @@
(ns status-im.multiaccounts.logout.core
(:require [native-module.core :as native-module]
[re-frame.core :as re-frame]
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[native-module.core :as native-module]
[status-im.notifications.core :as notifications]
[utils.re-frame :as rf]
[status-im.wallet.core :as wallet]
[status-im2.common.keychain.events :as keychain]
[status-im2.db :as db]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[status-im2.db :as db]))
(re-frame/reg-fx
::logout
@@ -15,15 +15,14 @@
(native-module/logout)))
(rf/defn initialize-app-db
[{{:keys [keycard initials-avatar-font-file]
[{{:keys [keycard]
:biometric/keys [supported-type]
:network/keys [type]}
:db}]
{:db (assoc db/app-db
:network/type type
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometric/supported-type supported-type)})
:network/type type
:keycard (dissoc keycard :secrets :pin :application-info)
:biometric/supported-type supported-type)})
(rf/defn logout-method
{:events [::logout-method]}
+5 -8
View File
@@ -1,6 +1,5 @@
(ns status-im.multiaccounts.update.core
(:require [status-im.ethereum.ens :as ens]
[status-im.utils.types :as types]
(:require [status-im.utils.types :as types]
[status-im2.constants :as constants]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
@@ -20,12 +19,10 @@
display-name]} (:profile/profile db)
account (some #(and (= (:key-uid %) key-uid) %) raw-multiaccounts-from-status-go)]
(when-let [new-name (and account (or preferred-name display-name name))]
(rf/merge
cofx
{:db (assoc-in db [:profile/profile :ens-name?] (ens/is-valid-eth-name? new-name))
:json-rpc/call [{:method "multiaccounts_updateAccount"
:params [(assoc account :name new-name)]
:on-success #(log/debug "sent multiaccount update")}]}))))
(rf/merge cofx
{:json-rpc/call [{:method "multiaccounts_updateAccount"
:params [(assoc account :name new-name)]
:on-success #(log/debug "sent multiaccount update")}]}))))
(rf/defn multiaccount-update
"Takes effects (containing :db) + new multiaccount fields, adds all effects necessary for multiaccount update.
@@ -2,11 +2,8 @@
(:require [clojure.string :as string]
[quo.design-system.colors :as colors]
[quo.react-native :as rn]
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
[quo2.core :as quo]
[quo2.theme :as theme]
[re-frame.core :as re-frame.core]
[status-im.ethereum.ens :as ens]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.chat-icon.styles :as styles]
[status-im.ui.components.icons.icons :as icons]
@@ -50,7 +47,7 @@
[rn/text {:style (:default-chat-icon-text styles)} emoji]]))
(defn profile-photo-plus-dot-view
[{:keys [public-key full-name customization-color photo-container photo-path community?]}]
[{:keys [public-key photo-container photo-path community?]}]
(let [photo-container (if (nil? photo-container)
styles/container-chat-list
photo-container)
@@ -58,28 +55,11 @@
dot-styles (visibility-status-utils/icon-visibility-status-dot
public-key
size)
dot-accessibility-label (:accessibility-label dot-styles)
text-style (styles/default-chat-icon-text size)]
dot-accessibility-label (:accessibility-label dot-styles)]
[rn/view
{:style photo-container
:accessibility-label :profile-photo}
(if (:fn photo-path)
;; temp support new media server avatar for old component
[photos/photo
{:uri ((:fn photo-path)
{:size size
:full-name full-name
:font-size (get text-style :font-size)
:background-color (user-avatar.style/customization-color customization-color
(theme/get-theme))
:indicator-size 0
:indicator-border 0
:indicator-color "#000000"
:color (get text-style :color)
:length 2
:ring? (not (ens/is-valid-eth-name? full-name))})}
{:size size}]
[photos/photo photo-path {:size size}])
[photos/photo photo-path {:size size}]
(when-not community?
[rn/view
{:style dot-styles
@@ -199,28 +179,14 @@
(defn profile-icon-view
[photo-path name color emoji edit? size override-styles public-key community?]
(let [styles (merge {:container {:width size :height size}
:size size
:chat-icon styles/chat-icon-profile
:default-chat-icon (styles/default-chat-icon-profile color size)
:default-chat-icon-text (if (string/blank? emoji)
(styles/default-chat-icon-text size)
(styles/emoji-chat-icon-text size))}
override-styles)
photo-path (if (:fn photo-path)
;; temp support new media server avatar for old component
{:uri ((:fn photo-path)
{:size size
:full-name name
:font-size (get-in styles [:default-chat-icon-text :font-size])
:background-color (get-in styles [:default-chat-icon :background-color])
:indicator-size 0
:indicator-border 0
:indicator-color "#000000"
:color (get-in styles [:default-chat-icon-text :color])
:length 2
:ring? (not (ens/is-valid-eth-name? name))})}
photo-path)]
(let [styles (merge {:container {:width size :height size}
:size size
:chat-icon styles/chat-icon-profile
:default-chat-icon (styles/default-chat-icon-profile color size)
:default-chat-icon-text (if (string/blank? emoji)
(styles/default-chat-icon-text size)
(styles/emoji-chat-icon-text size))}
override-styles)]
[rn/view (:container styles)
(if (and photo-path (seq photo-path))
[profile-photo-plus-dot-view
@@ -2,25 +2,23 @@
(:require [quo.core :as quo]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.list.views :as list.views]
[status-im.ui.components.react :as react]
[utils.i18n :as i18n])
[status-im.ui.components.react :as react])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn contacts-list-item
[{:keys [public-key] :as contact}]
(let [{:keys [primary-name secondary-name customization-color]} contact]
(let [{:keys [primary-name secondary-name]} contact]
[quo/list-item
{:title primary-name
:subtitle secondary-name
:icon [chat-icon.screen/profile-photo-plus-dot-view
{:public-key public-key
:full-name primary-name
:customization-color (or customization-color :primary)
:photo-path (multiaccounts/displayed-photo contact)}]
{:public-key public-key
:photo-path (multiaccounts/displayed-photo contact)}]
:chevron true
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
@@ -3,10 +3,9 @@
[quo.components.list.item :as list-item]
[quo.core :as quo]
[quo.design-system.colors :as colors]
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
[quo2.theme :as theme]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.profile-header.view :as profile-header]
@@ -14,9 +13,8 @@
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.profile.components.sheets :as sheets]
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[status-im2.constants :as constants]))
(defn actions
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
@@ -181,11 +179,9 @@
:as contact}
@(re-frame/subscribe
[:contacts/current-contact])
muted? @(re-frame/subscribe [:chats/muted
public-key])
{:keys [primary-name secondary-name customization-color]} contact
customization-color (or customization-color :primary)
{:keys [primary-name secondary-name]} contact
on-share #(re-frame/dispatch
[:show-popover
(merge
@@ -205,17 +201,14 @@
:on-press #(re-frame/dispatch [:navigate-back])}]}]
[:<>
[(profile-header/extended-header
{:on-press on-share
{:on-press on-share
:bottom-separator false
:title primary-name
:color
(user-avatar.style/customization-color customization-color
(theme/get-theme))
:photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified)
:subtitle secondary-name
:compressed-key compressed-key
:public-key public-key})]
:title primary-name
:photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified)
:subtitle secondary-name
:compressed-key compressed-key
:public-key public-key})]
[react/view
{:height 1 :background-color colors/gray-lighter :margin-top 8}]
[nickname-settings contact]
@@ -2,16 +2,16 @@
(:require [quo.core :as quo]
[quo.design-system.colors :as colors]
[quo.design-system.spacing :as spacing]
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
[quo2.theme :as theme]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.ethereum.stateofus :as stateofus]
[utils.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.copyable-text :as copyable-text]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.profile-header.view :as profile-header]
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
[status-im.ui.components.react :as react]
[status-im.ui.screens.profile.user.edit-picture :as edit]
[status-im.ui.screens.profile.user.styles :as styles]
@@ -19,9 +19,7 @@
[status-im.utils.gfycat.core :as gfy]
[status-im.utils.universal-links.utils :as universal-links]
[status-im.utils.utils :as utils]
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
[status-im2.config :as config]
[utils.i18n :as i18n])
[status-im2.config :as config])
(:require-macros [status-im.utils.views :as views]))
(views/defview share-chat-key
@@ -192,12 +190,9 @@
(let [{:keys [public-key
compressed-key
ens-verified
preferred-name
key-uid]
preferred-name]
:as account}
@(re-frame/subscribe [:profile/multiaccount])
customization-color (or (:color @(re-frame/subscribe [:onboarding-2/profile]))
@(re-frame/subscribe [:profile/customization-color key-uid]))
on-share #(re-frame/dispatch [:show-popover
{:view :share-chat-key
:address (or compressed-key
@@ -218,8 +213,6 @@
:on-edit #(re-frame/dispatch [:bottom-sheet/show-sheet-old
{:content (edit/bottom-sheet
has-picture)}])
:color (user-avatar.style/customization-color customization-color
(theme/get-theme))
:title (multiaccounts/displayed-name account)
:photo (multiaccounts/displayed-photo account)
:monospace (not ens-verified)
+3 -3
View File
@@ -101,7 +101,7 @@
[react/nested-text
{:style {:color colors/gray}
:ellipsize-mode :middle
:number-of-lines 1} (i18n/label :t/to) " "
:number-of-lines 1} (i18n/label :t/To) " "
[{:style {:color colors/black}} (displayed-name contact)]]
[react/text {:style {:margin-top 6 :color colors/gray}}
(str fee " " fee-display-symbol " " (string/lower-case (i18n/label :t/network-fee)))])]
@@ -497,9 +497,9 @@
[react/view
[network-item]
[separator]])
[contact-item (i18n/label :t/from) from]
[contact-item (i18n/label :t/From) from]
[separator]
[contact-item (i18n/label :t/to) contact]
[contact-item (i18n/label :t/To) contact]
(when-not cancel?
[separator])
(when-not cancel?
@@ -138,7 +138,7 @@
:align-items :center
:margin-vertical 16}]
[quo/list-header
(i18n/label :t/from)]
(i18n/label :t/From)]
[react/view {:flex-direction :row :flex 1 :align-items :center}
[react/view {:flex 1}
[render-account from nil ::commands/set-selected-account]]]
@@ -204,7 +204,7 @@
[fiat-value amount-text token prices wallet-currency]
[components/separator]
[quo/list-header
(i18n/label :t/to)]
(i18n/label :t/To)]
[react/view {:flex-direction :row :flex 1 :align-items :center}
[react/view {:flex 1}
[render-account from token :wallet.request/set-field]]]]]
@@ -280,12 +280,12 @@
(when-not (or request? from-chat?)
[set-max token])
[components/separator]
[quo/list-header (i18n/label :t/from)]
[quo/list-header (i18n/label :t/From)]
[react/view {:flex-direction :row :flex 1 :align-items :center}
[react/view {:flex 1}
[render-account from token :wallet.send/set-field]]]
[quo/list-header
(i18n/label :t/to)]
(i18n/label :t/To)]
[react/view {:flex-direction :row :flex 1 :align-items :center}
[react/view {:flex 1}
[render-contact to from-chat?]]]]]
@@ -245,13 +245,13 @@
[react/view {:style styles/details-block}
[details-list-row :t/block block]
[details-list-row :t/hash hash]
[details-list-row :t/from
[details-list-row :t/From
[{:accessibility-label (if from-wallet :sender-name-text :sender-address-text)}
(or from-wallet from-contact from)]
(when (or from-wallet from-contact)
[{:accessibility-label :sender-address-text}
from])]
[details-list-row :t/to
[details-list-row :t/To
[{:accessibility-label (if to-wallet :recipient-name-text :recipient-address-text)}
(or to-wallet to-contact to)]
(when (or to-wallet to-contact)
-4
View File
@@ -1,4 +0,0 @@
(ns status-im.utils.pixel-ratio
(:require ["react-native" :as rn]))
(def ratio (rn/PixelRatio.get))
@@ -1,9 +1,9 @@
(ns status-im2.common.confirmation-drawer.view
(:require [quo2.core :as quo]
(:require [utils.i18n :as i18n]
[quo2.core :as quo]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.confirmation-drawer.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn avatar
@@ -13,10 +13,10 @@
{:customization-color color
:size :x-small}]
[quo/user-avatar
{:full-name display-name
:profile-picture photo-path
:size :xxs
:status-indicator? false}]))
{:full-name display-name
:profile-picture photo-path
:size :xxs
:status-indicator false}]))
(defn extra-action-view
[extra-action extra-text extra-action-selected?]
@@ -41,7 +41,12 @@
(= contact-name-by-identity
nil) name
:else contact-name-by-identity)
photo-path (or profile-picture (rf/sub [:chats/photo-path id]))]
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address
id]))
photo-path (or profile-picture
(when-not (empty? (:images contact))
(rf/sub [:chats/photo-path id])))]
[rn/view
{:style {:margin-horizontal 20}
:accessibility-label accessibility-label}
-17
View File
@@ -1,17 +0,0 @@
(ns status-im2.common.font
(:require
[clojure.string :as string]
[re-frame.core :as re-frame]
utils.image-server
[utils.re-frame :as rf]))
(re-frame/reg-fx
:font/get-font-file-for-initials-avatar
(fn [callback]
(utils.image-server/get-font-file-ready callback)))
(rf/defn init-abs-root-path
{:events [:font/init-font-file-for-initials-avatar]}
[{:keys [db]} initials-avatar-font-file]
(when-not (string/blank? initials-avatar-font-file)
{:db (assoc db :initials-avatar-font-file initials-avatar-font-file)}))
+4 -1
View File
@@ -60,7 +60,10 @@
{:accessibility-label :open-profile
:style style/left-section}
[quo/user-avatar
(merge {:size :small :online? online?} avatar)]]]))
(merge {:status-indicator? true
:size :small
:online? online?}
avatar)]]]))
(defn connectivity-sheet
[]
@@ -16,11 +16,11 @@
[rn/view {:padding-horizontal 20}
[quo/text {:size :heading-1 :weight :semi-bold}
(i18n/label :t/enter-password)]
[quo/user-avatar-tag
{:size :small
:style {:margin-top 8 :margin-bottom 20}}
(multiaccounts/displayed-name account)
(multiaccounts/displayed-photo account)]
[rn/view {:style {:margin-top 8 :margin-bottom 20}}
[quo/context-tag
{:size 24
:profile-picture (multiaccounts/displayed-photo account)
:full-name (multiaccounts/displayed-name account)}]]
[quo/input
{:type :password
:label (i18n/label :t/profile-password)
+3 -10
View File
@@ -11,17 +11,10 @@
(defn toast
[toast-id]
(let [{:keys [type user-public-key] :as toast-opts} (rf/sub [:toasts/toast toast-id])
profile-picture (when user-public-key
(rf/sub [:chats/photo-path user-public-key]))
toast-opts-with-profile-picture (if profile-picture
(assoc-in toast-opts
[:user :profile-picture]
profile-picture)
toast-opts)]
(let [{:keys [type] :as toast-opts} (rf/sub [:toasts/toast toast-id])]
(if (= type :notification)
[quo/notification toast-opts-with-profile-picture]
[quo/toast toast-opts-with-profile-picture])))
[quo/notification toast-opts]
[quo/toast toast-opts])))
(defn f-container
[toast-id]
-8
View File
@@ -345,11 +345,3 @@
(def ^:const onboarding-modal-animation-duration 300)
(def ^:const onboarding-modal-animation-delay 400)
(def ^:const initials-avatar-font-conf
"we pass absolute font file path and uppercase ratio to status-go for media
server to serve initials avatar image
`:uppercase-ratio` is uppercase-height/line-height for Inter-Medium"
{:ios "Inter-Medium.otf"
:android "Inter-Medium.ttf"
:uppercase-ratio 0.603861228044709})
@@ -2,9 +2,10 @@
(:require
[clojure.string :as string]
[quo2.core :as quo]
[react-native.clipboard :as clipboard]
[react-native.core :as rn]
[react-native.clipboard :as clipboard]
[reagent.core :as reagent]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.qr-scanner.core :as qr-scanner]
[status-im2.contexts.add-new-contact.style :as style]
[utils.debounce :as debounce]
@@ -14,8 +15,8 @@
(defn found-contact
[public-key]
(let [{:keys [primary-name compressed-key]} (rf/sub [:contacts/contact-by-identity public-key])
photo-path (rf/sub [:chats/photo-path public-key])]
(let [{:keys [primary-name compressed-key]
:as contact} (rf/sub [:contacts/contact-by-identity public-key])]
(when primary-name
[rn/view style/found-user
[quo/text (style/text-description)
@@ -23,7 +24,7 @@
[rn/view (style/found-user-container)
[quo/user-avatar
{:full-name primary-name
:profile-picture photo-path
:profile-picture (multiaccounts/displayed-photo contact)
:size :small
:status-indicator? false}]
[rn/view style/found-user-text
@@ -1,16 +1,16 @@
(ns status-im2.contexts.chat.composer.reply.view
(:require [clojure.string :as string]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.composer.constants :as constants]
[utils.i18n :as i18n]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[react-native.reanimated :as reanimated]
[status-im.ethereum.stateofus :as stateofus]
[status-im2.constants :as constant]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im.ethereum.stateofus :as stateofus]
[utils.re-frame :as rf]
[status-im2.contexts.chat.composer.reply.style :as style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[react-native.linear-gradient :as linear-gradient]))
(defn get-quoted-text-with-mentions
[parsed-text]
@@ -63,7 +63,8 @@
(defn reply-from
[{:keys [from contact-name current-public-key]}]
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
photo-path (rf/sub [:chats/photo-path from])]
contact (rf/sub [:contacts/contact-by-address from])
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))]
[rn/view {:style style/reply-from}
[quo/user-avatar
{:full-name display-name
@@ -41,6 +41,7 @@
(reanimated/animate opacity (if hide-shell? 0 1))
(reanimated/animate y-shell (if hide-shell? 35 0)))
[@focused? @messages.list/show-floating-scroll-down-button])
(rn/use-effect #(reanimated/animate y-container neg-y) [reply edit])
[reanimated/view
{:style (style/shell-container height y-container)}
[reanimated/view
@@ -1,16 +1,16 @@
(ns status-im2.contexts.chat.home.chat-list-item.view
(:require [clojure.string :as string]
[quo2.components.icon :as icons]
[quo2.core :as quo]
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[status-im2.common.home.actions.view :as actions]
[status-im2.constants :as constants]
[status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.datetime :as datetime]
[utils.debounce :as debounce]
[status-im2.common.home.actions.view :as actions]
[status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.re-frame :as rf]
[status-im2.constants :as constants]
[clojure.string :as string]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[quo2.components.icon :as icons]))
(def max-subheader-length 50)
@@ -201,14 +201,14 @@
[{:keys [contact chat-id full-name color muted?]}]
(if contact ; `contact` is passed when it's not a group chat
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])
photo-path (rf/sub [:chats/photo-path chat-id])]
photo-path (rf/sub [:chats/photo-path chat-id])
image-key (if (seq (:images contact)) :profile-picture :ring-background)]
[quo/user-avatar
(cond-> {:full-name full-name
:size :small
:online? online?
:profile-picture photo-path}
muted?
(assoc :ring? false))])
{:full-name full-name
:size :small
:online? online?
image-key photo-path
:muted? muted?}])
[quo/group-avatar
{:customization-color color
:size :small}]))
@@ -1,19 +1,21 @@
(ns status-im2.contexts.chat.messages.avatar.view
(:require [quo2.core :as quo]
(:require [utils.re-frame :as rf]
[react-native.core :as rn]
[utils.re-frame :as rf]))
[quo2.core :as quo]))
(defn avatar
[public-key size]
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
photo-path (rf/sub [:chats/photo-path public-key])
contact (rf/sub [:contacts/contact-by-address public-key])
photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path public-key]))
online? (rf/sub [:visibility-status-updates/online? public-key])]
[rn/view {:style {:padding-top 2}}
[rn/touchable-opacity
{:active-opacity 1
:on-press #(rf/dispatch [:chat.ui/show-profile public-key])}
[quo/user-avatar
{:full-name display-name
:profile-picture photo-path
:online? online?
:size size}]]]))
{:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? online?
:size size}]]]))
@@ -28,7 +28,9 @@
on-long-press-fn]
(let [;; deleted message with nil deleted-by is deleted by (:from message)
display-name (first (rf/sub [:contacts/contact-two-names-by-identity (or deleted-by from)]))
photo-path (rf/sub [:chats/photo-path (or deleted-by from)])]
contact (rf/sub [:contacts/contact-by-address (or deleted-by from)])
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path (or deleted-by from)]))]
[quo/system-message
{:type :deleted
:timestamp timestamp-str
@@ -1,24 +1,24 @@
(ns status-im2.contexts.chat.messages.list.view
(:require [oops.core :as oops]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.background-timer :as background-timer]
[react-native.core :as rn]
[react-native.hooks :as hooks]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]
[status-im.ui.screens.chat.group :as chat.group]
[status-im.ui.screens.chat.message.gap :as message.gap]
[status-im2.constants :as constants]
[status-im2.contexts.chat.composer.constants :as composer.constants]
[status-im2.contexts.chat.messages.content.view :as message]
[status-im2.contexts.chat.messages.list.state :as state]
[status-im2.contexts.chat.messages.list.style :as style]
[status-im2.contexts.chat.messages.navigation.style :as navigation.style]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[status-im2.contexts.chat.composer.constants :as composer.constants]
[utils.re-frame :as rf]
[utils.i18n :as i18n]))
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
(defonce ^:const loading-indicator-extra-spacing 250)
@@ -203,7 +203,8 @@
online? (rf/sub [:visibility-status-updates/online? chat-id])
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address chat-id]))
photo-path (rf/sub [:chats/photo-path chat-id])
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path chat-id]))
border-animation (reanimated/interpolate scroll-y
[30 125]
[14 0]
@@ -5,15 +5,15 @@
[re-frame.db]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[status-im2.common.home.actions.view :as actions]
[status-im2.config :as config]
[status-im2.constants :as constants]
[react-native.reanimated :as reanimated]
[react-native.platform :as platform]
[status-im2.contexts.chat.messages.navigation.style :as style]
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
[status-im2.constants :as constants]
[utils.re-frame :as rf]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[status-im2.common.home.actions.view :as actions]))
(defn f-view
[{:keys [scroll-y]}]
@@ -27,7 +27,10 @@
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
(str emoji " " chat-name))
online? (rf/sub [:visibility-status-updates/online? chat-id])
photo-path (rf/sub [:chats/photo-path chat-id])
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address chat-id]))
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path chat-id]))
opacity-animation (reanimated/interpolate scroll-y
[style/navigation-bar-height
(+ style/navigation-bar-height 30)]
@@ -12,6 +12,6 @@
:align-items :center
:justify-content :space-between})
(def context-tag
(def community-tag
{:margin-right :auto
:margin-top 8})
@@ -14,7 +14,10 @@
:weight :semi-bold
:size :heading-1}
title]]
[quo/context-tag
{:style style/context-tag}
(:thumbnail images) name]
[rn/view {:style style/community-tag}
[quo/context-tag
{:type :community
:size 24
:community-logo (:thumbnail images)
:community-name name}]]
children]))
@@ -37,11 +37,12 @@
:weight :semi-bold
:size :heading-1}
(request-to-join-text open?)]]
[quo/context-tag
{:style
{:margin-right :auto
:margin-top 8}}
(:thumbnail images) name]
[rn/view {:style {:margin-right :auto :margin-top 8}}
[quo/context-tag
{:type :community
:size 24
:community-logo (:thumbnail images)
:community-name name}]]
[quo/text
{:style {:margin-top 24}
:accessibility-label :communities-rules-title
@@ -256,7 +256,7 @@
[description]
[quo/text
{:accessibility-label :community-description-text
:number-of-lines 4
:number-of-lines 2
:ellipsize-mode :tail
:weight :regular
:size :paragraph-1
@@ -1,8 +1,8 @@
(ns status-im2.contexts.contacts.drawers.nickname-drawer.view
(:require [clojure.string :as string]
[quo2.foundations.colors :as colors]
[quo2.components.icon :as icons]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
@@ -28,7 +28,8 @@
[{:keys [contact]}]
(let [{:keys [primary-name nickname public-key]} contact
entered-nickname (reagent/atom (or nickname ""))
photo-path (rf/sub [:chats/photo-path public-key])
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path public-key]))
insets (safe-area/get-insets)]
(fn [{:keys [title description accessibility-label
close-button-text]}]
@@ -40,10 +41,10 @@
:size :heading-1} title]
[rn/view {:style (style/context-container)}
[quo/user-avatar
{:full-name primary-name
:profile-picture photo-path
:size :xxs
:status-indicator? false}]
{:full-name primary-name
:profile-picture photo-path
:size :xxs
:status-indicator false}]
[quo/text
{:weight :medium
:size :paragraph-2
@@ -1,20 +1,20 @@
(ns status-im2.contexts.onboarding.create-profile.view
(:require [clojure.string :as string]
[oops.core :as oops]
[quo2.core :as quo]
(:require [quo2.core :as quo]
[clojure.string :as string]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[status-im2.contexts.onboarding.create-profile.style :as style]
[utils.i18n :as i18n]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.safe-area :as safe-area]
[react-native.hooks :as hooks]
[reagent.core :as reagent]
[status-im2.constants :as c]
[status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
[status-im2.contexts.onboarding.create-profile.style :as style]
[status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[oops.core :as oops]
[react-native.blur :as blur]
[status-im2.constants :as c]
[react-native.platform :as platform]))
;; NOTE - validation should match with Desktop
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
@@ -162,12 +162,9 @@
[:show-bottom-sheet
{:content
(fn []
[method-menu/view on-change-profile-pic])}]))
:image-picker-props {:profile-picture (or
@profile-pic
(rf/sub
[:profile/onboarding-placeholder-avatar
@profile-pic]))
[method-menu/view on-change-profile-pic])
:theme :dark}]))
:image-picker-props {:profile-picture (when @profile-pic {:uri @profile-pic})
:full-name (if (seq @full-name)
@full-name
(i18n/label :t/your-name))
@@ -1,7 +1,7 @@
(ns status-im2.contexts.onboarding.identifiers.profile-card.style
(:require [quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]
[react-native.reanimated :as reanimated]))
[react-native.reanimated :as reanimated]
[quo2.foundations.typography :as typography]))
(def card-view
{:margin-horizontal 20
@@ -36,7 +36,7 @@
:background-color :transparent
:height 48
:border-color :black
:border-width 3
:border-width 2
:border-radius 44}))
(def picture-avatar-mask
@@ -1,12 +1,12 @@
(ns status-im2.contexts.onboarding.identifiers.profile-card.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.masked-view :as masked-view]
(:require [react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.masked-view :as masked-view]
[reagent.core :as reagent]
[status-im2.contexts.onboarding.identifiers.profile-card.style :as style]
[utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting]))
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting]
[status-im2.contexts.onboarding.identifiers.profile-card.style :as style]))
(defn- f-profile-card-component
[{:keys [profile-picture name hash emoji-hash
@@ -20,24 +20,29 @@
ring-opacity (worklets.identifiers-highlighting/ring-opacity @progress)
user-hash-color (worklets.identifiers-highlighting/user-hash-color @progress)
user-hash-opacity (worklets.identifiers-highlighting/user-hash-opacity @progress)
emoji-hash-style (worklets.identifiers-highlighting/emoji-hash-style @progress)
avatar [quo/user-avatar
{:full-name name
:profile-picture profile-picture
:size :medium
:status-indicator? false
:customization-color customization-color}]]
emoji-hash-style (worklets.identifiers-highlighting/emoji-hash-style @progress)]
[rn/view
{:style style/card-view}
[reanimated/view
{:style (style/card-container container-background)}
[rn/view {:style style/card-header}
[reanimated/view {:style (style/avatar avatar-opacity)} avatar]
[reanimated/view
{:style (style/avatar avatar-opacity)}
[quo/user-avatar
{:full-name name
:profile-picture profile-picture
:size :medium
:status-indicator? false
:customization-color customization-color}]]
[masked-view/masked-view
{:style {:position :absolute}
:mask-element (reagent/as-element
[reanimated/view {:style (style/mask-view ring-opacity)}])}
(when profile-picture avatar)]]
(when profile-picture
[rn/image
{:accessibility-label :ring-background
:style style/picture-avatar-mask
:source profile-picture}])]]
[reanimated/view
{:style (style/user-name-container opacity)}
[quo/text
@@ -111,7 +111,7 @@
:customization-color (or customization-color :primary)
:keycard-account? keycard-pairing
:show-options-button? true
:profile-picture profile-picture
:profile-picture (when profile-picture {:uri profile-picture})
:card-style (style/profiles-profile-card last-item?)
:on-options-press #(show-profile-options
key-uid
@@ -257,7 +257,7 @@
[quo/profile-card
{:name name
:customization-color (or customization-color :primary)
:profile-picture profile-picture
:profile-picture (when profile-picture {:uri profile-picture})
:card-style style/login-profile-card}]
[quo/input
{:type :password
+1 -3
View File
@@ -1,11 +1,9 @@
(ns status-im2.contexts.profile.rpc
(:require [clojure.string :as string]
[status-im.ethereum.ens :as ens]))
(:require [clojure.string :as string]))
(defn rpc->profiles-overview
[{:keys [customizationColor keycard-pairing] :as profile}]
(-> profile
(dissoc :customizationColor)
(assoc :customization-color (keyword customizationColor))
(assoc :ens-name? (ens/is-valid-eth-name? (:name profile)))
(assoc :keycard-pairing (when-not (string/blank? keycard-pairing) keycard-pairing))))
@@ -10,28 +10,28 @@
[{:label "Size"
:key :size
:type :select
:options [{:key 20
:value 20}
{:key 28
:value 28}
{:key 32
:value 32}
{:key 48
:value 48}
{:key 80
:value 80}]}
:options [{:key :x-small
:value "x-small"}
{:key :small
:value "Small"}
{:key :medium
:value "Medium"}
{:key :large
:value "Large"}
{:key :x-large
:value "x-Large"}]}
{:label "Avatar"
:key :picture?
:type :boolean}
(preview/customization-color-option)])
(def avatar (resources/get-mock-image :photo1))
(def avatar (resources/get-mock-image :user-picture-male4))
(defn cool-preview
[]
(let [state (reagent/atom {:theme :light
:customization-color :blue
:size 20
:size :small
:picture? false})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
@@ -67,7 +67,12 @@
{:padding-vertical 60
:flex-direction :row
:justify-content :center}
[quo2/user-avatar @state]]]])))
(let [{:keys [profile-picture ring?]} @state
ring-bg (resources/get-mock-image :ring)
params (cond-> @state
(and (not profile-picture) ring?)
(assoc :ring-background ring-bg))]
[quo2/user-avatar params])]]])))
(defn preview-user-avatar
[]
@@ -1,26 +1,48 @@
(ns status-im2.contexts.quo-preview.colors.color-picker
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:key :selected
[{:label "Color:"
:key :color
:type :select
:options (map (fn [color]
(let [k (get color :name)]
{:key k :value k}))
(quo/picker-colors))}
{:key :blur?
:type :boolean}])
{:label "Blur?"
:key :blur
:type :boolean}])
(defn view
(defn cool-preview
[]
(let [state (reagent/atom {:selected :orange
:blur? false})]
(let [state (reagent/atom {:color "orange" :blur false})
blur (reagent/cursor state [:blur])
color (reagent/cursor state [:color])]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true}
[quo/color-picker (assoc @state :on-change #(swap! state assoc :selected %))]])))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[preview/customizer state descriptor]
[(if @blur blur/view :<>)
[rn/view {:padding-vertical 60 :align-items :center}
[quo/color-picker
{:blur? @blur
:selected @color
:on-change #(reset! color %)}]]]]])))
(defn preview-color-picker
[]
[rn/view
{:background-color (colors/theme-colors
colors/white
colors/neutral-95)
:flex 1}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -1,29 +1,54 @@
(ns status-im2.contexts.quo-preview.dividers.divider-label
(:require [quo2.core :as quo]
(:require [quo2.components.dividers.divider-label :as divider-label]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:type :text :key :label}
{:type :text :key :counter-value}
{:type :boolean :key :increase-padding-top?}
{:type :boolean :key :blur?}
{:key :chevron-position
[{:label "Label:"
:key :label
:type :text}
{:label "Chevron position:"
:key :chevron-position
:type :select
:options [{:key :left}
{:key :right}]}])
:options [{:key :left
:value "Left"}
{:key :right
:value "Right"}]}
{:label "Counter value:"
:key :counter-value
:type :text}
{:label "Increase padding top:"
:key :increase-padding-top?
:type :boolean}
{:label "Blur:"
:key :blur?
:type :boolean}])
(defn view
(defn cool-preview
[]
(let [state (reagent/atom {:blur? false
(let [state (reagent/atom {:label "Welcome"
:chevron-position :left
:counter-value "0"
:counter-value 0
:increase-padding-top? true
:label "Welcome"})]
:blur? false})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true}
[quo/divider-label @state]])))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[preview/customizer state descriptor]
[rn/view {:padding-vertical 60}
[divider-label/divider-label @state]]]])))
(defn preview-divider-label
[]
[rn/view
{:background-color (colors/theme-colors
colors/white
colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -25,15 +25,21 @@
(defn example-tags
[blur?]
[[quo/context-tag {:blur? [blur?]}
(resources/get-mock-image :user-picture-male5)
"alisher.eth"]
[quo/context-tag {:blur? [blur?]}
(resources/get-mock-image :user-picture-male4)
"Pedro"]
[quo/context-tag {:blur? [blur?]}
(resources/get-mock-image :user-picture-female2)
"Freya Odinson"]])
[[quo/context-tag
{:blur? blur?
:size 24
:profile-picture (resources/get-mock-image :user-picture-male5)
:full-name "alisher.eth"}]
[quo/context-tag
{:blur? blur?
:size 24
:profile-picture (resources/get-mock-image :user-picture-male4)
:full-name "Pedro"}]
[quo/context-tag
{:blur? blur?
:size 24
:profile-picture (resources/get-mock-image :user-picture-female2)
:full-name "Freya Odinson"}]])
(defn cool-preview
[]
@@ -1,56 +1,100 @@
(ns status-im2.contexts.quo-preview.links.link-preview
(:require [quo2.core :as quo]
(:require [clojure.string :as string]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
[status-im2.contexts.quo-preview.preview :as preview]
utils.number))
(def descriptor
[{:type :text :key :title}
{:type :text :key :description}
{:type :text :key :link}
{:type :number :key :width}
{:type :boolean :key :with-logo?}
{:type :boolean :key :with-description?}
{:type :boolean :key :with-thumbnail?}
{:type :text :key :disabled-text}
{:type :boolean :key :enabled?}
{:key :thumbnail
[{:label "Title"
:key :title
:type :text}
{:label "Description"
:key :description
:type :text}
{:label "Link"
:key :link
:type :text}
{:label "Container width"
:key :width
:type :text}
{:label "With logo?"
:key :with-logo?
:type :boolean}
{:label "With description?"
:key :with-description?
:type :boolean}
{:label "With thumbnail?"
:key :with-thumbnail?
:type :boolean}
{:label "Disabled text"
:key :disabled-text
:type :text}
{:label "Enabled?"
:key :enabled?
:type :boolean}
{:label "Thumbnail"
:key :thumbnail
:type :select
:options (mapv (fn [k] {:key k})
:options (mapv (fn [k]
{:key k
:value (string/capitalize (name k))})
(keys resources/mock-images))}
{:key :thumbnail-size
{:label "Thumbnail size"
:key :thumbnail-size
:type :select
:options [{:key :normal}
{:key :large}]}])
:options [{:key :normal
:value :normal}
{:key :large
:value :large}]}])
(defn view
(defn cool-preview
[]
(let [state (reagent/atom
{:description "Turn your products or services into publicly tradeable items"
:disabled-text "Enable Preview"
:enabled? true
{:title "Rarible - NFT Marketplace"
:description "Turn your products or services into publicly tradeable items"
:link "rarible.com"
:thumbnail :collectible
:thumbnail-size :normal
:title "Rarible - NFT Marketplace"
:width 295
:with-description? true
:width "295"
:with-logo? true
:with-thumbnail? true})]
:with-thumbnail? true
:with-description? true
:enabled? true
:thumbnail-size :normal
:disabled-text "Enable Preview"})]
(fn []
(let [thumbnail (get resources/mock-images (:thumbnail @state))]
[preview/preview-container {:state state :descriptor descriptor}
[quo/link-preview
{:logo (when (:with-logo? @state)
(resources/get-mock-image :status-logo))
:title (:title @state)
:description (when (:with-description? @state)
(:description @state))
:enabled? (:enabled? @state)
:on-enable #(js/alert "Button pressed")
:disabled-text (:disabled-text @state)
:link (:link @state)
:thumbnail (when (:with-thumbnail? @state)
thumbnail)
:thumbnail-size (:thumbnail-size @state)
:container-style {:width (:width @state)}}]]))))
(let [width (utils.number/parse-int (:width @state) 295)
thumbnail (get resources/mock-images (:thumbnail @state))]
[rn/view {:style {:margin-bottom 20}}
[preview/customizer state descriptor]
[rn/view
{:style {:align-items :center
:margin-top 20}}
[quo/link-preview
{:logo (when (:with-logo? @state)
(resources/get-mock-image :status-logo))
:title (:title @state)
:description (when (:with-description? @state)
(:description @state))
:enabled? (:enabled? @state)
:on-enable #(js/alert "Button pressed")
:disabled-text (:disabled-text @state)
:link (:link @state)
:thumbnail (when (:with-thumbnail? @state)
thumbnail)
:thumbnail-size (:thumbnail-size @state)
:container-style {:width width}}]]]))))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -1,18 +1,30 @@
(ns status-im2.contexts.quo-preview.links.url-preview
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:type :text :key :title}
{:type :text :key :body}
{:type :boolean :key :with-logo?}
{:type :boolean :key :loading?}
{:type :text :key :loading-message}])
[{:label "Title"
:key :title
:type :text}
{:label "Body"
:key :body
:type :text}
{:label "With logo?"
:key :with-logo?
:type :boolean}
{:label "Loading?"
:key :loading?
:type :boolean}
{:label "Loading message"
:key :loading-message
:type :text}])
(defn view
(defn cool-preview
[]
(let [state (reagent/atom
{:title "Status - Private, Secure Communication"
@@ -21,12 +33,29 @@
:loading? false
:loading-message "Generating preview"})]
(fn []
[preview/preview-container {:state state :descriptor descriptor}
[quo/url-preview
{:title (:title @state)
:body (:body @state)
:logo (when (:with-logo? @state)
(resources/get-mock-image :status-logo))
:loading? (:loading? @state)
:loading-message (:loading-message @state)
:on-clear #(js/alert "Clear button pressed")}]])))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:style {:padding-bottom 150}}
[preview/customizer state descriptor]
[rn/view
{:style {:align-items :center
:padding-horizontal 16
:margin-top 50}}
[quo/url-preview
{:title (:title @state)
:body (:body @state)
:logo (when (:with-logo? @state)
(resources/get-mock-image :status-logo))
:loading? (:loading? @state)
:loading-message (:loading-message @state)
:on-clear #(js/alert "Clear button pressed")}]]]])))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -1,34 +1,50 @@
(ns status-im2.contexts.quo-preview.links.url-preview-list
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
[status-im2.contexts.quo-preview.preview :as preview]
utils.number))
(def descriptor
[{:type :number :key :previews-length}])
[{:label "Number of previews"
:key :previews-length
:type :text}])
(defn view
(defn cool-preview
[]
(let [state (reagent/atom {:previews-length 3})
padding 20]
(let [state (reagent/atom {:previews-length "3"})]
(fn []
[preview/preview-container
{:state state
:descriptor descriptor
:component-container-style {:padding-horizontal 0}}
[quo/url-preview-list
{:horizontal-spacing padding
:preview-width (- (:width (rn/get-window))
(* 2 padding))
:on-clear #(js/alert "Clear button pressed")
:key-fn :url
:data (for [index (range (:previews-length @state))
:let [index (inc index)]]
{:title (str "Title " index)
:body (str "status.im." index)
:logo (resources/get-mock-image
:status-logo)
:loading? false
:url (str "status.im." index)})}]])))
(let [previews-length (min 6 (utils.number/parse-int (:previews-length @state)))
padding 20]
[rn/view {:style {:padding-bottom 150}}
[preview/customizer state descriptor]
[rn/view
{:style {:align-items :center
:margin-top 50}}
[quo/url-preview-list
{:horizontal-spacing padding
:preview-width (- (:width (rn/get-window))
(* 2 padding))
:on-clear #(js/alert "Clear button pressed")
:key-fn :url
:data (for [index (range previews-length)
:let [index (inc index)]]
{:title (str "Title " index)
:body (str "status.im." index)
:logo (resources/get-mock-image :status-logo)
:loading? false
:url (str "status.im." index)})}]]]))))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1}}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -2,33 +2,39 @@
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[quo2.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.community.data :as data]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor-type
{:type :select
{:label "Type:"
:key :type
:options [{:key :discover}
{:key :engage}
{:key :share}]})
:type :select
:options [{:key :discover :value "Discover"}
{:key :engage :value "Engage"}
{:key :share :value "Share"}]})
(def descriptor-locked
{:type :boolean :key :locked?})
{:label "Locked?" :key :locked? :type :boolean})
(def descriptor-unread-count
{:type :number :key :unread-count})
{:label "Unread count:" :key :unread-count :type :number})
(def descriptor-title
{:type :text :key :title})
{:label "Title:" :key :title :type :text})
(def descriptor-blur
{:type :boolean :key :blur?})
{:label "Blur?" :key :blur? :type :boolean})
(def descriptor-member-stats
[{:type :number :key :members-count}
{:type :number :key :active-count}])
[{:label "Total member count:"
:key :members-count
:type :number}
{:label "Active member count:"
:key :active-count
:type :number}])
(def descriptors-base
[descriptor-type
@@ -37,27 +43,29 @@
(def descriptors-type-discover
(conj descriptors-base
{:type :select
{:label "Info:"
:key :info
:options [{:key :token-gated}
{:key :default}]}
:type :select
:options [{:key :token-gated :value "Token gated"}
{:key :default :value "Default"}]}
{:label "Member stats?"
:type :boolean
:key :members?}))
:key :members?
:type :boolean}))
(def descriptors-type-engage
(conj descriptors-base
{:type :select
{:label "Info:"
:key :info
:options [{:key :notification}
{:key :mention}
{:key :muted}
{:key :token-gated}
{:key :navigation}
{:key :default}]}))
:type :select
:options [{:key :notification :value "Notification"}
{:key :mention :value "Mention"}
{:key :muted :value "Muted"}
{:key :token-gated :value "Token gated"}
{:key :navigation :value "Navigation"}
{:key :default :value "Default"}]}))
(def descriptors-type-share
(conj descriptors-base {:type :text :key :subtitle}))
(conj descriptors-base {:label "Subtitle:" :key :subtitle :type :text}))
(defn descriptors
[{:keys [members? info] :as state}]
@@ -80,7 +88,7 @@
(into [descriptor-blur] descs)
descs)))
(defn view
(defn cool-preview
[]
(let [state (reagent/atom {:blur? false
:customization-color :blue
@@ -95,16 +103,30 @@
:unread-count 5})]
(fn []
(let [customization-color (colors/custom-color-by-theme (:customization-color @state) 50 60)]
[preview/preview-container {:state state :descriptor (descriptors @state)}
[quo/community-list-item
(merge @state
{:container-style {:width 335}
:logo (resources/get-mock-image :status-logo)
:tokens (:tokens data/community)
:customization-color customization-color
:on-press #(js/alert "List item pressed")
:on-long-press #(js/alert "Long pressed item")
:on-press-info #(js/alert "Info pressed")
:members (when (:members? @state)
{:members-count (:members-count @state)
:active-count (:active-count @state)})})]]))))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:style {:margin-bottom 20}}
[preview/customizer state (descriptors @state)]
[rn/view {:style {:margin-vertical 30 :align-items :center}}
[quo/community-list-item
(merge @state
{:container-style {:width 335}
:logo (resources/get-mock-image :status-logo)
:tokens (:tokens data/community)
:customization-color customization-color
:on-press #(js/alert "List item pressed")
:on-long-press #(js/alert "Long pressed item")
:on-press-info #(js/alert "Info pressed")
:members (when (:members? @state)
{:members-count (:members-count @state)
:active-count (:active-count @state)})})]]]]))))
(defn preview
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)
:flex 1}}
[rn/flat-list
{:style {:flex 1}
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
+161 -49
View File
@@ -2,9 +2,9 @@
(:refer-clojure :exclude [filter])
(:require
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[reagent.core :as reagent]
[react-native.core :as rn]
[status-im2.contexts.quo-preview.style :as style]
[status-im2.common.theme.core :as theme]
[status-im2.contexts.quo-preview.animated-header-list.animated-header-list :as animated-header-list]
[status-im2.contexts.quo-preview.avatars.account-avatar :as account-avatar]
@@ -116,237 +116,352 @@
[status-im2.contexts.quo-preview.wallet.summary-info :as summary-info]
[status-im2.contexts.quo-preview.wallet.token-input :as token-input]
[status-im2.contexts.quo-preview.wallet.wallet-overview :as wallet-overview]
[status-im2.contexts.quo-preview.wallet.wallet-activity :as wallet-activity]
[utils.re-frame :as rf]))
(def screens-categories
{:foundations [{:name :shadows
:options {:topBar {:visible true}}
:component shadows/preview-shadows}]
:animated-list [{:name :animated-header-list
:options {:topBar {:visible false}}
:component animated-header-list/mock-screen}]
:avatar [{:name :group-avatar
:options {:topBar {:visible true}}
:component group-avatar/preview-group-avatar}
{:name :icon-avatar
:options {:topBar {:visible true}}
:component icon-avatar/preview-icon-avatar}
{:name :user-avatar
:options {:topBar {:visible true}}
:component user-avatar/preview-user-avatar}
{:name :wallet-user-avatar
:options {:topBar {:visible true}}
:component wallet-user-avatar/preview-wallet-user-avatar}
{:name :channel-avatar
:options {:topBar {:visible true}}
:component channel-avatar/preview-channel-avatar}
{:name :account-avatar
:options {:topBar {:visible true}}
:component account-avatar/preview-account-avatar}]
:banner [{:name :banner
:options {:topBar {:visible true}}
:component banner/preview-banner}]
:buttons [{:name :button
:options {:topBar {:visible true}}
:component button/preview-button}
{:name :composer-button
:options {:topBar {:visible true}}
:component composer-button/preview-composer-button}
{:name :dynamic-button
:options {:topBar {:visible true}}
:component dynamic-button/preview-dynamic-button}
{:name :slide-button
:options {:topBar {:visible true}}
:component slide-button/preview-slide-button}
{:name :predictive-keyboard
:options {:topBar {:visible true}}
:component predictive-keyboard/preview-predictive-keyboard}]
:browser [{:name :browser-input
:options {:topBar {:visible false}}
:component browser-input/preview-browser-input}]
:calendar [{:name :calendar
:options {:topBar {:visible true}}
:component calendar/preview-calendar}
{:name :calendar-day
:options {:topBar {:visible true}}
:component calendar-day/preview-calendar-day}
{:name :calendar-year
:options {:topBar {:visible true}}
:component calendar-year/preview-calendar-year}]
:code [{:name :snippet
:options {:topBar {:visible true}}
:component code-snippet/preview-code-snippet}]
:colors [{:name :color-picker
:component color-picker/view}]
:options {:topBar {:visible true}}
:component color-picker/preview-color-picker}]
:community [{:name :community-card-view
:options {:topBar {:visible true}}
:component community-card/preview-community-card}
{:name :community-membership-list-view
:options {:topBar {:visible true}}
:component community-membership-list-view/preview-community-list-view}
{:name :discover-card
:options {:topBar {:visible true}}
:component discover-card/preview-discoverd-card}
{:name :token-gating
:options {:insets {:bottom? true}}
:options {:insets {:bottom? true}
:topBar {:visible true}}
:component token-gating/preview-token-gating}
{:name :channel-actions
:options {:insets {:bottom? true}}
:options {:insets {:bottom? true}
:topBar {:visible true}}
:component channel-actions/preview-channel-actions}]
:counter [{:name :counter
:options {:topBar {:visible true}}
:component counter/preview-counter}
{:name :step
:options {:topBar {:visible true}}
:component step/preview-step}]
:dividers [{:name :divider-label
:component divider-label/view}
:options {:topBar {:visible true}}
:component divider-label/preview-divider-label}
{:name :new-messages
:options {:topBar {:visible true}}
:component new-messages/preview-new-messages}
{:name :divider-date
:options {:topBar {:visible true}}
:component divider-date/preview-divider-date}
{:name :strength-divider
:options {:topBar {:visible true}}
:component strength-divider/preview-strength-divider}]
:drawers [{:name :action-drawers
:options {:topBar {:visible true}}
:component action-drawers/preview-action-drawers}
{:name :documentation-drawer
:options {:topBar {:visible true}}
:component documenation-drawers/preview-documenation-drawers}
{:name :drawer-buttons
:options {:topBar {:visible true}}
:component drawer-buttons/preview-drawer-buttons}
{:name :permission-drawers
:options {:topBar {:visible true}}
:component permission-drawers/preview-permission-drawers}]
:dropdowns [{:name :dropdown
:options {:topBar {:visible true}}
:component dropdown/preview-dropdown}]
:empty-state [{:name :empty-state
:options {:topBar {:visible true}}
:component empty-state/preview-empty-state}]
:gradient [{:name :gradient-cover
:options {:topBar {:visible true}}
:component gradient-cover/preview-gradient-cover}]
:graph [{:name :wallet-graph
:options {:topBar {:visible true}}
:component wallet-graph/preview-wallet-graph}]
:info [{:name :info-message
:options {:topBar {:visible true}}
:component info-message/preview-info-message}
{:name :information-box
:options {:topBar {:visible true}}
:component information-box/preview-information-box}]
:inputs [{:name :input
:options {:topBar {:visible true}}
:component input/preview-input}
{:name :locked-input
:options {:topBar {:visible true}}
:component locked-input/preview-locked-input}
{:name :profile-input
:options {:topBar {:visible true}}
:component profile-input/preview-profile-input}
{:name :recovery-phrase-input
:options {:topBar {:visible true}}
:component recovery-phrase-input/preview-recovery-phrase-input}
{:name :search-input
:options {:topBar {:visible true}}
:component search-input/preview-search-input}
{:name :title-input
:options {:topBar {:visible true}}
:component title-input/preview-title-input}]
:numbered-keyboard [{:name :keyboard-key
:options {:insets {:top? true}}
:options {:insets {:top? true}
:topBar {:visible true}}
:component keyboard-key/preview-keyboard-key}
{:name :numbered-keyboard
:options {:insets {:top? true}}
:options {:insets {:top? true}
:topBar {:visible true}}
:component numbered-keyboard/preview-numbered-keyboard}]
:links [{:name :url-preview
:options {:insets {:top? true}}
:component url-preview/view}
:options {:insets {:top? true}
:topBar {:visible true}}
:component url-preview/preview}
{:name :url-preview-list
:options {:insets {:top? true}}
:component url-preview-list/view}
:options {:insets {:top? true}
:topBar {:visible true}}
:component url-preview-list/preview}
{:name :link-preview
:options {:insets {:top? true}}
:component link-preview/view}]
:options {:insets {:top? true}
:topBar {:visible true}}
:component link-preview/preview}]
:list-items [{:name :account-list-card
:options {:topBar {:visible true}}
:component account-list-card/preview}
{:name :channel
:options {:topBar {:visible true}}
:component channel/preview-channel}
{:name :community-list
:options {:insets {:top? true}}
:component community-list/view}
:options {:insets {:top? true}
:topBar {:visible true}}
:component community-list/preview}
{:name :preview-lists
:options {:topBar {:visible true}}
:component preview-lists/preview-preview-lists}
{:name :user-list
:options {:topBar {:visible true}}
:component user-list/preview-user-list}
{:name :token-value
:options {:topBar {:visible true}}
:component token-value/preview}]
:loaders [{:name :skeleton
:options {:topBar {:visible true}}
:component skeleton/preview-skeleton}]
:markdown [{:name :texts
:options {:topBar {:visible true}}
:component text/preview-text}
{:name :markdown-list
:options {:topBar {:visible true}}
:component markdown-list/preview-markdown-list}]
:messages [{:name :gap
:options {:topBar {:visible true}}
:component messages-gap/preview-messages-gap}
{:name :system-messages
:options {:topBar {:visible true}}
:component system-message/preview-system-message}
{:name :author
:options {:topBar {:visible true}}
:component messages-author/preview-author}]
:navigation [{:name :bottom-nav-tab
:options {:topBar {:visible true}}
:component bottom-nav-tab/preview-bottom-nav-tab}
{:name :top-nav
:options {:topBar {:visible true}}
:component top-nav/preview-top-nav}
{:name :page-nav
:options {:topBar {:visible true}}
:component page-nav/preview-page-nav}
{:name :floating-shell-button
:options {:topBar {:visible true}}
:component floating-shell-button/preview-floating-shell-button}]
:notifications [{:name :activity-logs
:options {:topBar {:visible true}}
:component activity-logs/preview-activity-logs}
{:name :activity-logs-photos
:options {:topBar {:visible true}}
:component activity-logs-photos/preview-activity-logs-photos}
{:name :toast
:options {:topBar {:visible true}}
:component toast/preview-toasts}
{:name :notification
:options {:topBar {:visible true}}
:component notification/preview-notification}]
:onboarding [{:name :small-option-card
:options {:topBar {:visible true}}
:component small-option-card/preview-small-option-card}]
:password [{:name :tips
:options {:topBar {:visible true}}
:component tips/preview-tips}]
:profile [{:name :profile-card
:options {:topBar {:visible true}}
:component profile-card/preview-profile-card}
{:name :collectible
:options {:topBar {:visible true}}
:component collectible/preview-collectible}
{:name :select-profile
:options {:topBar {:visible true}}
:component select-profile/preview-select-profile}]
:reactions [{:name :react
:options {:topBar {:visible true}}
:component react/preview-react}]
:record-audio [{:name :record-audio
:options {:topBar {:visible true}}
:component record-audio/preview-record-audio}]
:switcher [{:name :switcher-cards
:options {:topBar {:visible true}}
:component switcher-cards/preview-switcher-cards}]
:selectors [{:name :disclaimer
:options {:topBar {:visible true}}
:component disclaimer/preview-disclaimer}
{:name :filter
:options {:topBar {:visible true}}
:component filter/preview}
{:name :selectors
:options {:topBar {:visible true}}
:component selectors/preview-selectors}
{:name :select-reactions
:options {:topBar {:visible true}}
:component selector-reactions/preview}]
:settings [{:name :privacy-option
:options {:topBar {:visible true}}
:component privacy-option/preview-options}
{:name :accounts
:options {:topBar {:visible true}}
:component accounts/preview-accounts}
{:name :settings-list
:options {:topBar {:visible true}}
:component settings-list/preview-settings-list}
{:name :reorder-item
:options {:topBar {:visible true}}
:component reorder-item/preview-reorder-item}
{:name :category
:options {:topBar {:visible true}}
:component category/preview}]
:share [{:name :qr-code
:options {:topBar {:visible true}}
:component qr-code/preview-qr-code}
{:name :share-qr-code
:options {:topBar {:visible true}}
:component share-qr-code/preview-share-qr-code}]
:tabs [{:name :segmented
:options {:topBar {:visible true}}
:component segmented/preview-segmented}
{:name :tabs
:options {:topBar {:visible true}}
:component tabs/preview-tabs}
{:name :account-selector
:options {:topBar {:visible true}}
:component account-selector/preview-this}]
:tags [{:name :context-tags
:options {:topBar {:visible true}}
:component context-tags/preview-context-tags}
{:name :tags
:options {:topBar {:visible true}}
:component tags/preview-tags}
{:name :permission-tag
:options {:topBar {:visible true}}
:component permission-tag/preview-permission-tag}
{:name :status-tags
:options {:topBar {:visible true}}
:component status-tags/preview-status-tags}
{:name :token-tag
:options {:topBar {:visible true}}
:component token-tag/preview-token-tag}]
:text-combinations [{:name :title
:options {:topBar {:visible true}}
:component title/preview-title}]
:wallet [{:name :account-card
:options {:topBar {:visible true}}
:component account-card/preview-account-card}
{:name :account-overview
:options {:topBar {:visible true}}
:component account-overview/preview-account-overview}
{:name :network-amount
:options {:topBar {:visible true}}
:component network-amount/preview}
{:name :network-bridge
:options {:topBar {:visible true}}
:component network-bridge/preview}
{:name :progress-bar
:options {:topBar {:visible true}}
:component progress-bar/preview}
{:name :summary-info
:options {:topBar {:visible true}}
:component summary-info/preview}
{:name :token-input
:options {:topBar {:visible true}}
:component token-input/preview}
{:name :wallet-overview
:component wallet-overview/preview-wallet-overview}]
:options {:topBar {:visible true}}
:component wallet-overview/preview-wallet-overview}
{:name :wallet-activity
:options {:topBar {:visible true}}
:component wallet-activity/preview-wallet-activity}]
:keycard [{:name :keycard-component
:options {:topBar {:visible true}}
:component keycard/preview-keycard}]})
(defn- navigation-bar
(def screens (flatten (map val screens-categories)))
(defn navigation-bar
[]
(let [logged-in? (rf/sub [:multiaccount/logged-in?])
has-profiles? (boolean (rf/sub [:profile/profiles-overview]))
@@ -366,51 +481,48 @@
(theme/set-theme :dark)
(rf/dispatch [:init-root root]))))}}]))
(defn- theme-switcher
(defn theme-switcher
[]
[rn/view {:style style/theme-switcher}
[rn/view
{:style {:flex-direction :row
:justify-content :space-between
:padding-horizontal 24
:padding-vertical 12}}
[quo/button {:on-press #(theme/set-theme :light)} "Set light theme"]
[quo/button {:on-press #(theme/set-theme :dark)} "Set dark theme"]])
(defn- category-view
(defn category-view
[]
(let [open? (reagent/atom false)
on-change #(swap! open? not)]
(let [open? (reagent/atom false)]
(fn [category]
[rn/view {:style {:margin-vertical 8}}
[quo/dropdown
{:selected @open?
:on-change on-change
:type :grey}
(name (key category))]
[quo/dropdown {:selected @open? :on-change #(swap! open? not) :type :grey}
(clojure.core/name (key category))]
(when @open?
(for [{category-name :name} (val category)]
^{:key category-name}
(for [{:keys [name]} (val category)]
^{:key name}
[quo/button
{:type :outline
:container-style {:margin-vertical 8}
:on-press #(rf/dispatch [:navigate-to category-name])}
(name category-name)]))])))
:on-press #(rf/dispatch [:navigate-to name])}
(clojure.core/name name)]))])))
(defn- main-screen
(defn main-screen
[]
[:<>
[navigation-bar]
[theme-switcher]
[rn/scroll-view {:style (style/main)}
(for [category (sort screens-categories)]
^{:key (first category)}
[category-view category])]])
(def screens
(->> screens-categories
(map val)
flatten
(map (fn [subcategory]
(update-in subcategory
[:options :topBar]
merge
{:visible true})))))
(fn []
[:<>
[navigation-bar]
[theme-switcher]
[rn/scroll-view
{:flex 1
:padding-bottom 8
:padding-horizontal 16
:background-color (colors/theme-colors colors/white colors/neutral-90)}
[rn/view
(map (fn [category]
^{:key (get category 0)}
[category-view category])
(sort screens-categories))]]]))
(def main-screens
[{:name :quo2-preview
@@ -1,6 +1,7 @@
(ns status-im2.contexts.quo-preview.notifications.activity-logs
(:require [quo2.core :as quo2]
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[quo2.theme :as quo.theme]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]
@@ -67,27 +68,20 @@
status-tags/status-tags-options])
(def basic-user-action
[[quo2/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style {:background-color colors/white-opa-10}
:text-style {:color colors/white}}
"Name"]
[[quo/context-tag
{:size 24
:full-name "Name"
:blur? true}]
"did something here."])
(def complex-user-action
(let [tag-props {:color :purple
:size :small
:style {:background-color colors/white-opa-10}
:text-style {:color colors/white}}]
[[quo2/user-avatar-tag tag-props "Alice"]
"from"
[quo2/user-avatar-tag tag-props "Mainnet"]
"to"
[quo2/user-avatar-tag tag-props "Optimism"]
"on"
[quo2/user-avatar-tag tag-props "My savings"]]))
[[quo/context-tag {:size 24 :full-name "Alice" :blur? true}]
"from"
[quo/context-tag {:size 24 :full-name "Mainnet" :blur? true}]
"to"
[quo/context-tag {:size 24 :full-name "Optimism" :blur? true}]
"on"
[quo/context-tag {:size 24 :full-name "My savings" :blur? true}]])
(def message-with-mention
(let [common-text-style {:style {:color colors/white}
@@ -95,8 +89,8 @@
{:body [rn/view
{:flex 1
:flex-direction :row}
[quo2/text common-text-style "Hello"]
[quo2/text
[quo/text common-text-style "Hello"]
[quo/text
{:style {:background-color colors/primary-50-opa-10
:border-radius 6
:color colors/primary-50
@@ -104,7 +98,7 @@
:padding-horizontal 3
:size :paragraph-1}}
"@name"]
[quo2/text common-text-style "! How are you feeling?"]]}))
[quo/text common-text-style "! How are you feeling?"]]}))
(def message-with-title
{:body "Your favorite color is Turquoise."
@@ -176,12 +170,13 @@
{:flex 1
:padding 16}
[preview/customizer state descriptor]]
[rn/view
{:background-color colors/neutral-90
:flex-direction :row
:justify-content :center
:padding-vertical 60}
[quo2/activity-log props]]]))))
[quo.theme/provider {:theme :dark}
[rn/view
{:background-color colors/neutral-90
:flex-direction :row
:justify-content :center
:padding-vertical 60}
[quo/activity-log props]]]]))))
(defn preview-activity-logs
[]
@@ -1,6 +1,7 @@
(ns status-im2.contexts.quo-preview.notifications.notification
(:require [quo2.core :as quo]
[react-native.core :as rn]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.code.snippet :as snippet-preview]
[utils.re-frame :as rf]))
@@ -33,7 +34,8 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue}]
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:title "Alisher Yakupov accepted your contact request"
:duration 4000
:title-weight :medium
@@ -48,7 +50,8 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue}]
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:title "Default to semibold title"
:text "The quick brown fox jumped over the lazy dog and ate a potatoe."
:duration 4000
@@ -63,7 +66,8 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue}]
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:header [rn/view
[quo/info-message
{:type :success
+187 -163
View File
@@ -1,178 +1,216 @@
(ns status-im2.contexts.quo-preview.preview
(:require [camel-snake-kebab.core :as camel-snake-kebab]
[clojure.string :as string]
[quo2.core :as quo]
(:require [clojure.string :as string]
[quo2.foundations.colors :as colors]
[quo2.theme :as quo.theme]
[quo2.theme :as theme]
[react-native.blur :as blur]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.style :as style]
utils.number)
(:require-macros status-im2.contexts.quo-preview.preview))
(defn- label-view
(def container
{:flex-direction :row
:padding-vertical 8
:flex 1
:align-items :center})
(defn touchable-style
[]
{:flex 1
:align-items :center
:justify-content :center
:padding-horizontal 16
:height 44})
(defn select-style
[]
{:flex 1
:flex-direction :row
:align-items :center
:padding-horizontal 16
:height 44
:border-radius 4
:background-color colors/neutral-20
:border-width 1
:border-color colors/neutral-100})
(defn select-option-style
[selected]
(merge (select-style)
{:margin-vertical 8
:justify-content :center}
(if selected
{:background-color colors/primary-50-opa-30}
{:background-color (colors/theme-colors colors/neutral-20 colors/white)})))
(def label-style
{:flex 0.4
:padding-right 8})
(defn label-view
[_ label]
[rn/view {:style style/label-container}
[rn/text {:style (style/label)}
[rn/view {:style label-style}
[rn/text
(when-let [label-color (colors/theme-colors colors/neutral-100 colors/white)]
{:style {:color label-color}})
label]])
(defn- humanize
[k]
;; We explicitly convert `k` to string because sometimes it's a number and
;; Clojure would throw an exception.
(-> (if (keyword? k) k (str k))
camel-snake-kebab/->kebab-case-keyword
name
(string/replace "-" " ")
string/capitalize))
(defn modal-container
[]
{:flex 1
:justify-content :center
:padding-horizontal 24
:background-color "rgba(0,0,0,0.4)"})
(defn- key->boolean-label
[k]
(let [label (humanize k)]
(if (string/ends-with? label "?")
label
(str label "?"))))
(defn modal-view
[]
{:padding-horizontal 16
:padding-vertical 8
:border-radius 8
:flex-direction :column
:margin-vertical 100
:background-color (colors/theme-colors colors/neutral-20 colors/white)})
(defn- key->text-label
[k]
(str (humanize k) ":"))
(defn- customizer-boolean
(defn customizer-boolean
[{:keys [label state] :as args}]
(let [label (or label (key->boolean-label (:key args)))
field-value (reagent/cursor state [(:key args)])
active? @field-value]
[rn/view {:style style/field-row}
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
[label-view state label]
[rn/view {:style (style/boolean-container)}
[rn/pressable
{:style (style/boolean-button {:active? active? :left? true})
:on-press #(reset! field-value true)}
[rn/text {:style (style/field-text active?)}
[rn/view
{:style {:flex-direction :row
:flex 0.6
:border-radius 4
:background-color (colors/theme-colors colors/neutral-20 colors/white)
:border-width 1
:border-color (colors/theme-colors colors/neutral-100 colors/white)}}
[rn/touchable-opacity
{:style (merge (touchable-style) {:background-color (when @state* colors/primary-50-opa-30)})
:on-press #(reset! state* true)}
[rn/text
"True"]]
[rn/pressable
{:style (style/boolean-button {:active? (not active?) :left? false})
:on-press #(reset! field-value false)}
[rn/text {:style (style/field-text (not active?))}
[rn/view
{:width 1
:margin-vertical 4
:background-color (colors/theme-colors colors/neutral-20 colors/white)}]
[rn/touchable-opacity
{:style (merge (touchable-style)
{:background-color (when (not @state*) colors/primary-50-opa-30)})
:on-press #(reset! state* false)}
[rn/text {}
"False"]]]]))
(defn- customizer-text
(defn customizer-text
[{:keys [label state limit suffix] :as args}]
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[rn/view {:style style/field-row}
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
[label-view state label]
[rn/view {:style style/field-column}
[rn/view {:style {:flex 0.6}}
[rn/text-input
(merge
{:value @field-value
{:value @state*
:show-cancel false
:style (style/field-container false)
:keyboard-appearance (quo.theme/theme-value :light :dark)
:on-change-text (fn [text]
(reset! field-value (if (and suffix
(> (count text) (count @field-value)))
(str (string/replace text suffix "") suffix)
text))
(reagent/flush))}
:style {:border-radius 4
:border-width 1
:color (colors/theme-colors colors/neutral-100 colors/white)
:border-color (colors/theme-colors colors/neutral-100 colors/white)}
:keyboard-appearance (theme/theme-value :light :dark)
:on-change-text #(do
(reset! state* (if (and suffix (> (count %) (count @state*)))
(str (string/replace % suffix "") suffix)
%))
(reagent/flush))}
(when limit
{:max-length limit}))]]]))
(defn- customizer-number
(defn customizer-number
[{:keys [label state default] :as args}]
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[rn/view {:style style/field-row}
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
[label-view state label]
[rn/view {:style style/field-column}
[rn/view {:style {:flex 0.6}}
[rn/text-input
(merge
{:value (str @field-value)
{:value (str @state*)
:show-cancel false
:style (style/field-container false)
:keyboard-appearance (quo.theme/theme-value :light :dark)
:on-change-text (fn [text]
(reset! field-value (utils.number/parse-int text default))
:style {:border-radius 4
:border-width 1
:color (colors/theme-colors colors/neutral-100 colors/white)
:border-color (colors/theme-colors colors/neutral-100 colors/white)}
:keyboard-appearance (theme/theme-value :light :dark)
:on-change-text (fn [v]
(reset! state* (utils.number/parse-int v default))
(reagent/flush))})]]]))
(defn- find-selected-option
(defn value-for-key
[id v]
(first (filter #(= (:key %) id) v)))
(:value (first (filter #(= (:key %) id) v))))
(defn- customizer-select-modal
[{:keys [open options field-value]}]
[rn/modal
{:visible @open
:on-request-close #(reset! open false)
:status-bar-translucent true
:transparent true
:animation :slide}
[rn/view {:style (style/modal-overlay)}
[rn/view {:style (style/modal-container)}
[rn/scroll-view {:shows-vertical-scroll-indicator false}
(doall
(for [{k :key v :value} options
:let [v (or v (humanize k))]]
^{:key k}
[rn/pressable
{:style (style/select-option (= @field-value k))
:on-press (fn []
(reset! open false)
(reset! field-value k))}
[rn/text {:style (style/field-text (= @field-value k))}
v]]))]
[rn/view {:style (style/footer)}
[rn/pressable
{:style (style/select-button)
:on-press (fn []
(reset! field-value nil)
(reset! open false))}
[rn/text {:style (style/field-text false)}
"Clear"]]
[rn/view {:style {:width 16}}]
[rn/touchable-opacity
{:style (style/select-button)
:on-press #(reset! open false)}
[rn/text {:style (style/field-text false)}
"Close"]]]]]])
(defn- customizer-select-button
[{:keys [open selected-key]}]
[rn/pressable
{:style (style/select-container)
:on-press #(reset! open true)}
[rn/text
{:style (style/field-select)
:number-of-lines 1}
(if selected-key
(humanize selected-key)
"Select option")]
[rn/view
[quo/icon :i/chevron-right]]])
(defn- customizer-select
(defn customizer-select
[]
(let [open (reagent/atom nil)]
(fn [{:keys [label state options] :as args}]
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])
selected-key (:key (find-selected-option @field-value options))]
[rn/view {:style style/field-row}
(let [state* (reagent/cursor state [(:key args)])
selected (value-for-key @state* options)]
[rn/view {:style container}
[label-view state label]
[rn/view {:style style/field-column}
[customizer-select-modal
{:open open
:options options
:field-value field-value}]
[customizer-select-button {:open open :selected-key selected-key}]]]))))
[rn/view {:style {:flex 0.6}}
[rn/modal
{:visible @open
:on-request-close #(reset! open false)
:statusBarTranslucent true
:transparent true
:animation :slide}
[rn/view {:style (modal-container)}
[rn/view {:style (modal-view)}
[rn/scroll-view
(doall
(for [{k :key v :value} options]
^{:key k}
[rn/touchable-opacity
{:style (select-option-style (= @state* k))
:on-press #(do
(reset! open false)
(reset! state* k))}
[rn/text {:color (if (= @state* k) :link :secondary)}
v]]))]
[rn/view
{:flex-direction :row
:padding-top 20
:margin-top 10
:border-top-width 1
:border-top-color (colors/theme-colors colors/neutral-100 colors/white)}
[rn/touchable-opacity
{:style (select-option-style false)
:on-press #(do
(reset! state* nil)
(reset! open false))}
[rn/text "Clear"]]
[rn/view {:width 16}]
[rn/touchable-opacity
{:style (select-option-style false)
:on-press #(reset! open false)}
[rn/text "Close"]]]]]]
[rn/touchable-opacity
{:style (select-style)
:on-press #(reset! open true)}
(if selected
[rn/text {:color :link} selected]
[rn/text "Select option"])
[rn/view
{:position :absolute
:right 16
:top 0
:bottom 0
:justify-content :center}
[rn/text "↓"]]]]]))))
(defn customizer
[state descriptors]
[rn/view
{:style {:flex-shrink 1
:padding-horizontal 20}}
{:style {:flex 1}
:padding-horizontal 16}
(doall
(for [desc descriptors
:let [descriptor (merge desc {:state state})]]
@@ -199,6 +237,19 @@
{:key k :value (string/capitalize (name k))})))}
opts)))
(comment
[{:label "Show error:"
:key :error
:type :boolean}
{:label "Label:"
:key :label
:type :text}
{:label "Type:"
:key :type
:type :select
:options [{:key :primary :value "Primary"}
{:key :secondary :value "Secondary"}]}])
(defn blur-view
[{:keys [show-blur-background? image height blur-view-props style]} children]
[rn/view
@@ -211,7 +262,8 @@
:overflow :hidden}}
[rn/image
{:source (or image (resources/get-mock-image :community-cover))
:style {:height "100%" :width "100%"}}]
:style {:height "100%"
:width "100%"}}]
[blur/view
(merge {:style {:position :absolute
:top 0
@@ -219,7 +271,9 @@
:left 0
:right 0}
:blur-amount 10
:overlay-color (colors/theme-colors colors/white-opa-70 colors/neutral-80-opa-80)}
:overlay-color (colors/theme-colors
colors/white-opa-70
colors/neutral-80-opa-80)}
blur-view-props)]])
[rn/view
{:style (merge {:position :absolute
@@ -227,33 +281,3 @@
:padding-horizontal 16}
style)}
children]])
(defn preview-container
[{:keys [state descriptor blur?
component-container-style
blur-container-style blur-view-props blur-height show-blur-background?]
:or {blur-height 200}}
component]
[rn/scroll-view
{:style (style/panel-basic)
:shows-vertical-scroll-indicator false}
[rn/pressable {:on-press rn/dismiss-keyboard!}
[rn/view {:style style/customizer-container}
[customizer state descriptor]]
[rn/view
(merge {:style style/component-container}
component-container-style)
(if blur?
[blur-view
{:show-blur-background? show-blur-background?
:height blur-height
:style (merge {:width "100%"
:flex-grow 1}
(when-not show-blur-background?
{:padding-horizontal 0
:top 0})
blur-container-style)
:blur-view-props (merge {:blur-type (quo.theme/get-theme)}
blur-view-props)}
component]
component)]]])
@@ -1,179 +0,0 @@
(ns status-im2.contexts.quo-preview.style
(:require [quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]))
;;;; Form fields
(def field-border-radius 12)
(def field-flex-percentage 0.6)
(def text-default typography/paragraph-1)
(defn field-active-bg-color
[]
(colors/theme-colors colors/primary-50 colors/primary-60))
(defn field-default-color
[]
(colors/theme-colors colors/neutral-100 colors/white))
(defn field-default-bg-color
[]
(colors/theme-colors colors/neutral-20 colors/neutral-80))
(defn field-default-border-color
[]
(colors/theme-colors colors/neutral-30 colors/neutral-70))
(def field-row
{:flex-direction :row
:padding-vertical 6
:align-items :center})
(def field-column
{:flex field-flex-percentage})
(defn field-container
[active?]
(merge text-default
{:color (if active?
(colors/theme-colors colors/white colors/white-opa-95)
(colors/theme-colors colors/neutral-100 colors/white))
:border-width 1
:border-color (field-default-border-color)
:border-radius field-border-radius
:padding-vertical 9
:padding-horizontal 12}))
(defn field-text
[active?]
(merge text-default
{:color (if active?
(colors/theme-colors colors/white colors/white-opa-95)
(field-default-color))}))
(def customizer-container
{:flex-shrink 1
:padding-top 12})
(defn select-container
[]
(merge (field-container false)
{:flex-direction :row
:align-items :center
:border-radius field-border-radius
:background-color (field-default-bg-color)
:border-width 1
:border-color (field-default-border-color)}))
(defn field-select
[]
(merge text-default
{:flex-grow 1
:color (field-default-color)}))
(defn select-option
[selected?]
(merge (field-container selected?)
{:justify-content :center
:flex 1
:margin-vertical 4}
(if selected?
{:border-color (field-active-bg-color)
:background-color (field-active-bg-color)}
{:background-color (field-default-bg-color)})))
(defn select-button
[]
(merge (select-option false) {:align-items :center}))
(def label-container
{:flex (- 1 field-flex-percentage)
:padding-right 8})
(defn label
[]
(merge text-default
typography/font-medium
{:color (field-default-color)}))
(defn boolean-container
[]
{:flex-direction :row
:flex field-flex-percentage
:border-radius field-border-radius})
(defn boolean-button
[{:keys [active? left?]}]
(cond-> {:flex 1
:align-items :center
:justify-content :center
:padding-vertical 9
:padding-horizontal 12
:border-color (if active?
(field-active-bg-color)
(field-default-border-color))
:border-top-width 1
:border-bottom-width 1
:background-color (if active?
(field-active-bg-color)
(field-default-bg-color))}
left?
(assoc :border-top-left-radius field-border-radius
:border-bottom-left-radius field-border-radius
:border-left-width 1)
(not left?)
(assoc :border-top-right-radius field-border-radius
:border-bottom-right-radius field-border-radius
:border-right-width 1)))
;;;; Modal
(defn modal-overlay
[]
{:flex 1
:justify-content :center
:padding-horizontal 24
:background-color (colors/theme-colors colors/neutral-80-opa-60 colors/neutral-80-opa-80)})
(defn modal-container
[]
{:padding-horizontal 16
:padding-vertical 8
:border-radius 12
:margin-vertical 100
:background-color (colors/theme-colors colors/white colors/neutral-95)})
(defn footer
[]
{:flex-direction :row
:padding-top 10
:margin-top 10
:border-top-width 1
:border-top-color (colors/theme-colors colors/neutral-10 colors/neutral-80)})
;;;; Misc
(defn panel-basic
[]
{:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1})
(def component-container
{:flex-grow 1
:min-height 200
:padding-vertical 20
:padding-horizontal 20})
(defn main
[]
{:flex 1
:padding-bottom 8
:padding-horizontal 16
:background-color (colors/theme-colors colors/white colors/neutral-90)})
(def theme-switcher
{:flex-direction :row
:justify-content :space-between
:padding-horizontal 24
:padding-vertical 12})
@@ -1,173 +1,267 @@
(ns status-im2.contexts.quo-preview.tags.context-tags
(:require [quo2.components.tags.context-tag.view :as quo2]
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def group-avatar-default-params
{:size :small
:color :purple})
(def example-pk
"0x04fcf40c526b09ff9fb22f4a5dbd08490ef9b64af700870f8a0ba2133f4251d5607ed83cd9047b8c2796576bc83fa0de23a13a4dced07654b8ff137fe744047917")
(def example-pk2
"0x04c178513eb741e8c4e50326b22baefa7d60a2f4eb81e328c4bbe0b441f87b2a014a5907a419f5897fc3c0493a0ff9db689a1999d6ca7fdc63119dd1981d0c7ccf")
(def example-photo
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII")
(def example-photo2
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII=")
(def coinbase-community-image (resources/get-mock-image :coinbase))
(def avatar-options
[{:key nil
:value "Default avatar"}
{:key (resources/mock-images :user-picture-male5)
:value "User pic male 5"}
{:key (resources/mock-images :user-picture-male4)
:value "User pic male 4"}
{:key (resources/mock-images :user-picture-female2)
:value "User pic female 2"}])
(def size-descriptor
{:label "Size"
:key :size
:type :select
:options [{:key 24
:value "24"}
{:key 32
:value "32"}]})
(def main-descriptor
[{:label "Type"
:key :type
:type :select
:options [{:key :public-key
:value "Public key"}
{:key :avatar
:value "Avatar"}
{:key :group-avatar
:value "Group avatar"}
{:key :context-tag
:value "Context tag"}
{:key :audio
:value "Audio"}
:options [{:key :default
:value "Default"}
{:key :multiuser
:value "Multiuser"}
{:key :group
:value "Group"}
{:key :channel
:value "Channel"}
{:key :community
:value "Community"}]}
{:label "Blur"
:value "Community"}
{:key :token
:value "Token"}
{:key :network
:value "Network"}
{:key :multinetwork
:value "Multinetwork"}
{:key :account
:value "Account"}
{:key :collectible
:value "Collectible"}
{:key :address
:value "Address"}
{:key :icon
:value "Icon"}
{:key :audio
:value "Audio"}]}
{:label "Blur?"
:key :blur?
:type :boolean}])
(def context-tag-descriptor
[{:label "Show avatar"
:key :show-avatar?
:type :boolean}
{:label "Label"
:key :label
{:label "State"
:key :state
:type :select
:options [{:key :default
:value "Default"}
{:key :selected
:value "selected"}]}
{:label "Customization color:"
:key :customization-color
:type :select
:options (map (fn [[color-kw _]]
{:key color-kw
:value (name color-kw)})
colors/customization)}])
(def default-descriptor
[size-descriptor
{:label "Profile picture"
:key :profile-picture
:type :select
:options avatar-options}
{:label "Full name"
:key :full-name
:type :text}])
(def multiuser-descriptor
(let [users [(resources/mock-images :user-picture-male5)
(resources/mock-images :user-picture-male4)
nil
(resources/mock-images :user-picture-female2)
nil]]
[{:label "users"
:key :users
:type :select
:options (map (fn [idx]
{:key (mapv (fn [picture idx-name]
{:profile-picture picture
:full-name (str (inc idx-name))})
(take idx (cycle users))
(range))
:value (str idx)})
(range 1 10))}]))
(def group-descriptor
[size-descriptor
{:label "Group"
:key :group-name
:type :text}])
(def channel-descriptor
[size-descriptor
{:label "Community name"
:key :community-name
:type :text}
{:label "Channel name"
:key :channel-name
:type :text}])
(def community-descriptor
[size-descriptor
{:label "Community name"
:key :community-name
:type :text}])
(def token-descriptor
[size-descriptor
{:label "Amount"
:key :amount
:type :text}
{:label "Avatar placeholder"
:key :no-avatar-placeholder?
:type :boolean}])
{:label "Token name"
:key :token-name
:type :text}])
(def network-descriptor
[size-descriptor
{:label "Network name"
:key :network-name
:type :text}])
(def multinetwork-descriptor
(let [networks (cycle [(resources/mock-images :monkey) (resources/mock-images :diamond)])]
[{:label "Networks"
:key :networks
:type :select
:options (map (fn [size]
{:key (take size networks)
:value (str size)})
(range 1 10))}]))
(def account-descriptor
[size-descriptor
{:label "Account name"
:key :account-name
:type :text}
{:label "Emoji"
:key :emoji
:type :select
:options [{:key "🐷" :value "🐷"}
{:key "🍇" :value "🍇"}
{:key "🐱" :value "🐱"}]}])
(def collectible-descriptor
[size-descriptor
{:label "Collectible name"
:key :collectible-name
:type :text}
{:label "Collectible number"
:key :collectible-number
:type :text}])
(def address-descriptor
[size-descriptor])
(def icon-descriptor
[size-descriptor
{:label "Context"
:key :context
:type :text}
{:label "Icon"
:key :icon
:type :select
:options [{:key :i/placeholder :value "Placeholder"}
{:key :i/add :value "Add"}
{:key :i/alert :value "Alert"}]}])
(def audio-descriptor
[{:label "Duration"
:key :duration
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom {:label "Name"
:channel-name "Channel"
:type :group-avatar
:duration "00:32"
:show-avatar? true
:no-avatar-placeholder? false})]
(let [state
(reagent/atom
{:label "Name"
:size 32
:type :group
:blur? false
:state :selected
:customization-color :army
:profile-picture nil
:full-name "Full Name"
:users [{:profile-picture (resources/mock-images :user-picture-male5)
:full-name "1"}
{:profile-picture nil
:full-name "3"}
{:profile-picture (resources/mock-images :user-picture-male5)
:full-name "2"}]
:group-name "Group"
:community-logo (resources/mock-images :coinbase)
:community-name "Community"
:channel-name "my channel"
:token-logo (resources/mock-images :diamond)
:token-name "ETH"
:amount "10"
:network-logo (resources/mock-images :monkey)
:network-name "Network"
:networks [(resources/mock-images :monkey)
(resources/mock-images :diamond)]
:account-name "Account name"
:emoji "😝"
:collectible (resources/mock-images :collectible)
:collectible-name "Collectible"
:collectible-number "123"
:address example-pk
:icon :i/placeholder
:context "Context"
:duration "00:32"})]
(fn []
(let [contacts {example-pk {:public-key example-pk
:primary-name "Automatic incompatible Coati"
:photo example-photo}
example-pk2 {:public-key example-pk2
:primary-name "Clearcut Flickering Rattlesnake"
:photo example-photo2}}
contacts-public-keys (map (fn [{:keys [public-key]}]
{:key public-key
:value (get-in contacts [public-key :primary-name])})
(vals contacts))
current-username (if (seq (:contact @state))
(->> @state
:contact
contacts
multiaccounts/displayed-name)
"Please select a user")
descriptor (cond
(= (:type @state) :context-tag)
(into main-descriptor context-tag-descriptor)
(= (:type @state) :group-avatar)
(conj main-descriptor
{:label "Label"
:key :label
:type :text})
(= (:type @state) :avatar)
(let [photo (-> @state :contact contacts :photo)]
(when-not (contains? @state :contacts)
(swap! state assoc :contacts contacts-public-keys))
(when-not (= (:photo @state)
photo)
(swap! state assoc :photo photo))
(conj main-descriptor
{:label "Contacts"
:key :contact
:type :select
:options contacts-public-keys}))
(= (:type @state) :community)
(conj main-descriptor
{:label "Community name"
:key :label
:type :text})
(= (:type @state) :audio)
(conj main-descriptor
{:label "Duration"
:key :duration
:type :text})
:else
main-descriptor)]
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:style {:padding-bottom 150}}
[rn/view {:style {:flex 1}}
[preview/customizer state descriptor]]
[rn/view {:style {:padding-vertical 60}}
[preview/blur-view
{:style {:flex 1
:margin-vertical 20
:margin-horizontal 40}
:show-blur-background? (:blur? @state)}
(case (:type @state)
:context-tag [quo2/context-tag
{:blur? (:blur? @state)
:size :small
:color :purple
:no-avatar-placeholder? (:no-avatar-placeholder? @state)}
(when (:show-avatar? @state)
example-photo2)
(:label @state)
(:channel-name @state)]
:group-avatar [quo2/group-avatar-tag (:label @state)
{:blur? (:blur? @state)
:size 20
:customization-color :purple}]
:public-key [quo2/public-key-tag
{:blur? (:blur? @state)
:size :small
:color :purple}
example-pk]
:avatar [quo2/user-avatar-tag
{:blur? (:blur? @state)
:size :small
:color :purple}
current-username (:photo @state)]
:audio [quo2/audio-tag (:duration @state) {:blur? (:blur? @state)}]
:community [quo2/community-tag
coinbase-community-image
(:label @state)
{:blur? (:blur? @state)}])]]]]))))
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:style {:padding-bottom 150}}
[rn/view {:style {:flex 1}}
[preview/customizer state
(concat main-descriptor
(case (:type @state)
:default default-descriptor
:multiuser multiuser-descriptor
:group group-descriptor
:channel channel-descriptor
:community community-descriptor
:token token-descriptor
:network network-descriptor
:multinetwork multinetwork-descriptor
:account account-descriptor
:collectible collectible-descriptor
:address address-descriptor
:icon icon-descriptor
:audio audio-descriptor
default-descriptor))]]
[rn/view {:style {:padding-vertical 60}}
[preview/blur-view
{:style {:flex 1
:margin-vertical 20
:margin-horizontal 40}
:show-blur-background? (:blur? @state)}
[quo/context-tag @state]]]]])))
(defn preview-context-tags
[]
[rn/view
{:style {:background-color (colors/theme-colors colors/white
colors/neutral-95)
{:style {:background-color (colors/theme-colors colors/white colors/neutral-95)
:flex 1}}
[rn/flat-list
{:style {:flex 1}
@@ -0,0 +1,241 @@
(ns status-im2.contexts.quo-preview.wallet.wallet-activity
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]
[quo2.foundations.resources :as quo.resources]))
(def asset-snt
{:size 24
:type :token
:token-name "SNT"
:amount 1500
:token-logo (quo.resources/get-token :snt)})
(def asset-dai
{:size 24
:type :token
:token-name "DAI"
:amount 2400
:token-logo (quo.resources/get-token :dai)})
(def asset-collectible
{:size 24
:type :collectible
:collectible (resources/mock-images :collectible)
:collectible-name "Collectible"
:collectible-number "123"})
(def trip-to-vegas
{:size 24
:type :account
:account-name "Trip to Vegas"
:emoji "🤑"})
(def piggy-bank
{:size 24
:type :account
:account-name "Piggy bank"
:emoji "🐷"})
(def aretha-gosling
{:size 24
:type :default
:full-name "Aretha Gosling"
:profile-picture (resources/mock-images :user-picture-female2)})
(def james-bond
{:size 24
:type :default
:full-name "James Bond"
:profile-picture (resources/mock-images :user-picture-male4)})
(def mainnet
{:size 24
:type :network
:network-logo (quo.resources/get-network :ethereum)
:network-name "Mainnet"})
(def optimism
{:size 24
:type :network
:network-logo (quo.resources/get-network :optimism)
:network-name "Optimism"})
(def arbitrum
{:size 24
:type :network
:network-logo (quo.resources/get-network :arbitrum)
:network-name "Arbitrum"})
(def multinetwork
{:size 24
:type :multinetwork
:networks [(quo.resources/get-network :ethereum)
(quo.resources/get-network :arbitrum)
(quo.resources/get-network :optimism)]})
(def moonpay
{:size 24
:type :network
:network-logo (quo.resources/get-network :ethereum)
:network-name "Moonpay"})
(def binance
{:size 24
:type :network
:network-logo (quo.resources/get-network :ethereum)
:network-name "Binance"})
(def context-tags
[{:key asset-snt
:value "SNT"}
{:key asset-dai
:value "UNK"}
{:key asset-collectible
:value "Collectible"}
{:key trip-to-vegas
:value "Account: Trip to Vegas"}
{:key piggy-bank
:value "Account: Piggy bank"}
{:key aretha-gosling
:value "Person: Aretha Gosling"}
{:key james-bond
:value "Person: James Bond"}
{:key mainnet
:value "Network: Mainnet"}
{:key optimism
:value "Network: Optimism"}
{:key arbitrum
:value "Network: Arbitrum"}
{:key multinetwork
:value "Network: Multinetwork"}
{:key moonpay
:value "Market: Moonpay"}
{:key binance
:value "Market: Binance"}])
(def prefixes
[{:key :t/to
:value "To"}
{:key :t/in
:value "In"}
{:key :t/via
:value "Via"}
{:key :t/from
:value "From"}
{:key :t/on
:value "On"}
{:key :t/at
:value "At"}])
(def descriptor
(concat
[{:label "Transaction"
:key :transaction
:type :select
:options [{:key :receive
:value "Receive"}
{:key :send
:value "Send"}
{:key :swap
:value "Swap"}
{:key :bridge
:value "Bridge"}
{:key :buy
:value "Buy"}
{:key :destroy
:value "Destroy"}
{:key :mint
:value "Mint"}]}
{:label "Status"
:key :status
:type :select
:options [{:key :pending
:value "Pending"}
{:key :confirmed
:value "Confirmed"}
{:key :finalised
:value "Finalised"}
{:key :failed
:value "Failed"}]}
{:label "Timestamp"
:key :timestamp
:type :text}
{:label "Counter"
:key :counter
:type :select
:options [{:key 1
:value 1}
{:key 2
:value 2}
{:key 3
:value 3}]}
{:label "Slot 1"
:key :first
:type :select
:options context-tags}
{:label "Slot 2 prefix"
:key :second-prefix
:type :select
:options prefixes}
{:label "Slot 2"
:key :second
:type :select
:options context-tags}
{:label "Slot 3 prefix"
:key :third-prefix
:type :select
:options prefixes}
{:label "Slot 3"
:key :third
:type :select
:options context-tags}
{:label "Slot 4 prefix"
:key :fourth-prefix
:type :select
:options prefixes}
{:label "Slot 4"
:key :fourth
:type :select
:options context-tags}]))
(defn cool-preview
[]
(let [state (reagent/atom {:transaction :send
:timestamp "Today 22:20"
:status :pending
:counter 1
:first asset-snt
:second-prefix :t/from
:second piggy-bank
:third-prefix :t/to
:third aretha-gosling
:fourth-prefix :t/via
:fourth mainnet})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[rn/view {:flex 1}
[preview/customizer state descriptor]]
[rn/view
{:padding-vertical 60
:flex-direction :row
:justify-content :center}
[quo/wallet-activity @state]]]])))
(defn preview-wallet-activity
[]
[rn/view
{:background-color (colors/theme-colors colors/white
colors/neutral-95)
:flex 1}
[rn/flat-list
{:flex 1
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])
@@ -4,8 +4,8 @@
[status-im.data-store.chats :as data-store.chats]
[status-im2.common.toasts.events :as toasts]
[status-im2.constants :as constants]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.contexts.shell.activity-center.notification-types :as types]
[status-im2.contexts.chat.events :as chat.events]
[taoensso.timbre :as log]
[utils.collection :as collection]
[utils.i18n :as i18n]
@@ -502,35 +502,33 @@
{:events [:activity-center.notifications/show-toasts]}
[{:keys [db]} new-notifications]
(let [my-public-key (get-in db [:profile/profile :public-key])]
(reduce (fn [cofx {:keys [author chat-id type accepted dismissed message name] :as x}]
(reduce (fn [cofx {:keys [author type accepted dismissed message name] :as x}]
(let [user-avatar {:full-name name
:status-indicator? true
:online? nil
:size :small
:ring? true}]
:ring? false}]
(cond
(and (not= author my-public-key)
(= type types/contact-request)
(not accepted)
(not dismissed))
(toasts/upsert cofx
{:user user-avatar
:user-public-key author
:icon-color colors/primary-50-opa-40
:title (i18n/label :t/contact-request-sent-toast
{:name name})
:text (get-in message [:content :text])})
{:user user-avatar
:icon-color colors/primary-50-opa-40
:title (i18n/label :t/contact-request-sent-toast
{:name name})
:text (get-in message [:content :text])})
(and (= author my-public-key) ;; we show it for user who sent the request
(= type types/contact-request)
accepted
(not dismissed))
(toasts/upsert cofx
{:user user-avatar
:user-public-key chat-id ;; user public key who accepted the request
:icon-color colors/success-50-opa-40
:title (i18n/label :t/contact-request-accepted-toast
{:name (or name (:alias message))})})
{:user user-avatar
:icon-color colors/success-50-opa-40
:title (i18n/label :t/contact-request-accepted-toast
{:name (or name (:alias message))})})
:else
cofx)))
{:db db}
@@ -69,8 +69,11 @@
:context [[common/user-avatar-tag author]
(i18n/label :t/wants-to-join)
[quo/context-tag
common/tag-params
community-image community-name]]
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]
:items (case membership-status
constants/activity-center-membership-status-accepted
[{:type :status
@@ -8,24 +8,14 @@
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def tag-params
{:size 20
:customization-color :blue
:style style/user-avatar-tag
:text-style style/user-avatar-tag-text
:no-avatar-placeholder? true})
(defn user-avatar-tag
[user-id]
(let [{:keys [primary-name] :as contact} (rf/sub [:contacts/contact-by-identity user-id])]
[quo/user-avatar-tag
{:color :purple
:size :small
:style style/user-avatar-tag
:text-style style/user-avatar-tag-text
:ring? false}
primary-name
(multiaccounts/displayed-photo contact)]))
[quo/context-tag
{:blur? true
:size 24
:full-name primary-name
:profile-picture (multiaccounts/displayed-photo contact)}]))
(defn- render-swipe-action
[{:keys [active-swipeable
@@ -34,5 +34,9 @@
:unread? (not read)
:context [[quo/text {:style common-style/user-avatar-tag-text}
(i18n/label :t/community-kicked-body)]
[quo/context-tag common/tag-params community-image
community-name]]}]]))
[quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]}]]))
@@ -22,8 +22,12 @@
[community membership-status]
(let [community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])
community-context-tag [quo/context-tag common/tag-params community-image
community-name]]
community-context-tag [quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]
(cond
(= membership-status constants/activity-center-membership-status-idle)
{:header-text (i18n/label :t/community-request-not-accepted)
@@ -66,9 +66,11 @@
:unread? (not read)
:context [[common/user-avatar-tag author]
(i18n/label :t/added-you-to)
[quo/group-avatar-tag chat-name
{:size 20
:customization-color :purple}]]
[quo/context-tag
{:type :group
:blur? true
:size 24
:group-name chat-name}]]
:items (when-not (or accepted dismissed)
[{:type :button
:subtype :positive
@@ -59,9 +59,19 @@
:timestamp (datetime/timestamp->relative timestamp)
:unread? (not read)
:context [[common/user-avatar-tag author]
[quo/text {:style style/tag-text} (string/lower-case (i18n/label :t/on))]
[quo/text {:style style/tag-text}
(string/lower-case (i18n/label :t/on))]
(if community-chat?
[quo/context-tag common/tag-params community-image community-name
chat-name]
[quo/group-avatar-tag chat-name common/tag-params])]
[quo/context-tag
{:type :channel
:blur? true
:size 24
:community-logo community-image
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
{:type :group
:group-name chat-name
:blur? true
:size 24}])]
:message {:body (message-body message)}}]]]))
@@ -74,9 +74,18 @@
:context [[common/user-avatar-tag author]
[quo/text {:style style/lowercase-text} (i18n/label :t/on)]
(if community-chat?
[quo/context-tag common/tag-params community-image community-name
chat-name]
[quo/group-avatar-tag chat-name common/tag-params])]
[quo/context-tag
{:type :channel
:blur? true
:size 24
:community-logo community-image
:community-name community-name
:channel-name chat-name}]
[quo/context-tag
{:type :group
:group-name chat-name
:blur? true
:size 24}])]
:message {:body-number-of-lines 1
:attachment (cond
(= (:content-type message)
@@ -1,17 +1,17 @@
(ns status-im2.contexts.shell.jump-to.components.switcher-cards.view
(:require [clojure.string :as string]
[utils.i18n :as i18n]
[quo2.core :as quo]
[utils.re-frame :as rf]
[status-im2.config :as config]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.fast-image :as fast-image]
[status-im2.config :as config]
[status-im2.constants :as constants]
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]
[status-im2.contexts.shell.jump-to.animation :as animation]
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
[status-im2.contexts.shell.jump-to.components.switcher-cards.style :as style]
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]))
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- channel-card
[{:keys [emoji channel-name customization-color]}]
@@ -82,13 +82,14 @@
:style style/gif}]
constants/content-type-audio
[quo/audio-tag data {:override-theme :dark}]
[quo/context-tag {:type :audio :duration data}]
constants/content-type-community
[quo/community-tag
(:avatar data)
(:community-name data)
{:override-theme :dark}]
[quo/context-tag
{:type :community
:size 24
:community-logo (:avatar data)
:community-name (:community-name data)}]
(constants/content-type-link) ;; Components not available
;; Code snippet content type is not supported yet
@@ -1,6 +1,5 @@
(ns status-im2.contexts.syncing.syncing-instructions.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.gesture :as gesture]
[reagent.core :as reagent]
@@ -15,7 +14,8 @@
[quo/text
{:size :paragraph-2
:weight :regular
:container-style style/list-text} (i18n/label value)]
:container-style style/list-text}
(i18n/label value)]
:button-primary
[quo/button
@@ -42,10 +42,10 @@
:context-tag
[quo/context-tag
{:override-theme :dark
:text-style {:color colors/white}}
(resources/get-mock-image (:source value))
(i18n/label (:label value))]))
{:blur? true
:size 24
:profile-picture (resources/get-mock-image (:source value))
:full-name (i18n/label (:label value))}]))
(defn- render-item
[i list-item]
+12 -15
View File
@@ -1,21 +1,20 @@
(ns status-im2.events
(:require [status-im.bottom-sheet.events]
[status-im.keycard.core :as keycard]
status-im2.common.font
[status-im2.common.json-rpc.events]
status-im2.common.password-authentication.events
status-im2.common.theme.events
(:require [status-im2.common.json-rpc.events]
[status-im2.common.toasts.events]
[status-im2.contexts.add-new-contact.events]
status-im2.contexts.chat.events
status-im2.contexts.chat.photo-selector.events
status-im2.contexts.communities.overview.events
status-im2.contexts.onboarding.events
status-im2.contexts.profile.events
[status-im.bottom-sheet.events]
[status-im2.db :as db]
[utils.re-frame :as rf]
status-im2.contexts.shell.share.events
status-im2.contexts.syncing.events
[status-im2.db :as db]
[utils.re-frame :as rf]))
status-im2.contexts.chat.events
status-im2.common.password-authentication.events
status-im2.contexts.communities.overview.events
status-im2.contexts.chat.photo-selector.events
status-im2.common.theme.events
status-im2.contexts.profile.events
[status-im.keycard.core :as keycard]))
(rf/defn start-app
{:events [:app-started]}
@@ -27,7 +26,5 @@
:biometric/get-supported-biometric-type nil
;;app starting flow continues in get-profiles-overview
:profile/get-profiles-overview #(rf/dispatch
[:profile/get-profiles-overview-success %])
:font/get-font-file-for-initials-avatar #(rf/dispatch
[:font/init-font-file-for-initials-avatar %])}
[:profile/get-profiles-overview-success %])}
(keycard/init)))
+4 -3
View File
@@ -2,9 +2,9 @@
(:require [clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.communities.core :as communities]
[status-im.contact.core :as contact]
[status-im.group-chats.core :as group-chat]
[status-im.group-chats.db :as group-chats.db]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.constants :as constants]
[status-im2.contexts.chat.composer.constants :as composer.constants]
[status-im2.contexts.chat.events :as chat.events]))
@@ -298,9 +298,10 @@
:chats/photo-path
:<- [:contacts/contacts]
:<- [:profile/multiaccount]
:<- [:mediaserver/port]
(fn [[contacts {:keys [public-key] :as multiaccount}] [_ id]]
(let [contact (or (when (= id public-key) multiaccount) (get contacts id))]
(contact/displayed-photo contact))))
(multiaccounts/displayed-photo (or (when (= id public-key) multiaccount)
(get contacts id)))))
(re-frame/reg-sub
:chats/unread-messages-number
+29 -45
View File
@@ -1,16 +1,16 @@
(ns status-im2.subs.contact
(:require [clojure.string :as string]
[quo2.theme :as theme]
[utils.i18n :as i18n]
[re-frame.core :as re-frame]
[status-im.contact.db :as contact.db]
[status-im.ethereum.core :as ethereum]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[status-im.utils.gfycat.core :as gfycat]
[status-im2.constants :as constants]
[utils.image-server :as image-server]
[utils.collection]
[utils.i18n :as i18n]
[utils.image-server :as image-server]))
[status-im2.constants :as constants]
[quo2.theme :as theme]))
(re-frame/reg-sub
::query-current-chat-contacts
@@ -32,42 +32,28 @@
(get multiaccount :profile-pictures-visibility)))
(defn- replace-contact-image-uri
[contact port public-key font-file]
(let [theme (theme/get-theme)
{:keys [images ens-name]} contact
images
(reduce (fn [acc image]
(let [image-name (:type image)
clock (:clock image)
uri (image-server/get-contact-image-uri-fn
{:port port
:public-key public-key
:image-name image-name
; We pass the clock so that we reload the
; image if the image is updated
:clock clock
:theme theme
:override-ring? (when ens-name false)})]
(assoc-in acc [(keyword image-name) :fn] uri)))
images
(vals images))
images (if (seq images)
images
{:thumbnail
{:fn (image-server/get-initials-avatar-uri-fn
{:port port
:public-key public-key
:override-ring? (when ens-name false)
:theme theme
:font-file font-file})}})]
(assoc contact :images images)))
[contact port contact-identity]
(let [theme (theme/get-theme)
contact-images (:images contact)
contact-images (reduce (fn [acc image]
(let [image-name (:type image)
; We pass the clock so that we reload the image if the image
; is updated
clock (:clock image)
uri (image-server/get-contact-image-uri port
contact-identity
image-name
clock
theme)]
(assoc-in acc [(keyword image-name) :uri] uri)))
contact-images
(vals contact-images))]
(assoc contact :images contact-images)))
(defn- reduce-contacts-image-uri
[contacts port font-file]
[contacts port]
(reduce-kv (fn [acc public-key contact]
(let [contact (replace-contact-image-uri contact port public-key font-file)]
(let [contact (replace-contact-image-uri contact port public-key)]
(assoc acc public-key contact)))
{}
contacts))
@@ -78,10 +64,9 @@
:<- [::profile-pictures-visibility]
:<- [:multiaccount/public-key]
:<- [:mediaserver/port]
:<- [:initials-avatar-font-file]
(fn [[contacts profile-pictures-visibility public-key port font-file]]
(fn [[contacts profile-pictures-visibility public-key port]]
(let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)]
(reduce-contacts-image-uri contacts port font-file))))
(reduce-contacts-image-uri contacts port))))
(re-frame/reg-sub
:contacts/active
@@ -190,10 +175,10 @@
contacts)))))
(defn- enrich-contact
[_ contact-identity ens-name port font-file]
[_ contact-identity ens-name port]
(let [contact (contact.db/enrich-contact
(contact.db/public-key-and-ens-name->new-contact contact-identity ens-name))]
(replace-contact-image-uri contact port contact-identity font-file)))
(replace-contact-image-uri contact port contact-identity)))
(re-frame/reg-sub
:contacts/current-contact
@@ -201,12 +186,11 @@
:<- [:contacts/current-contact-identity]
:<- [:contacts/current-contact-ens-name]
:<- [:mediaserver/port]
:<- [:initials-avatar-font-file]
(fn [[contacts contact-identity ens-name port font-file]]
(fn [[contacts contact-identity ens-name port]]
(let [contact (get contacts contact-identity)]
(cond-> contact
(nil? contact)
(enrich-contact contact-identity ens-name port font-file)))))
(enrich-contact contact-identity ens-name port)))))
(re-frame/reg-sub
:contacts/contact-by-identity
+6 -8
View File
@@ -1,8 +1,8 @@
(ns status-im2.subs.contact-test
(:require [cljs.test :refer [is testing]]
[re-frame.db :as rf-db]
status-im2.subs.contact
[test-helpers.unit :as h]
status-im2.subs.contact
[utils.re-frame :as rf]))
(def contacts-sample-data
@@ -74,13 +74,14 @@
:has-added-us? true
:contact-request-state 1}}})
(def expected-sorted-contacts-without-images
(def expected-sorted-contacts
[{:title "F"
:data [{:active? true
:last-updated 1672582629695
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "fslim.shady"
@@ -104,6 +105,7 @@
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "islim.shady"
@@ -127,6 +129,7 @@
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "rslim.shady"
@@ -145,10 +148,6 @@
:has-added-us? true
:contact-request-state 1}]}])
(defn remove-contact-images
[{:keys [data] :as contact}]
(assoc contact :data (mapv #(dissoc % :images) data)))
(h/deftest-sub :contacts/sorted-and-grouped-by-first-letter
[sub-name]
(testing "Returning empty sequence when no contacts"
@@ -171,5 +170,4 @@
(dissoc contact :identicon))
%)))
(rf/sub [sub-name]))]
(is (= expected-sorted-contacts-without-images
(mapv remove-contact-images contact-list-without-identicons))))))
(is (= expected-sorted-contacts contact-list-without-identicons)))))
+32 -61
View File
@@ -6,9 +6,9 @@
[status-im.ethereum.core :as ethereum]
[status-im.fleet.core :as fleet]
[status-im.multiaccounts.db :as multiaccounts.db]
[status-im2.constants :as constants]
[utils.image-server :as image-server]
[utils.security.core :as security]))
[utils.security.core :as security]
[status-im2.constants :as constants]))
(re-frame/reg-sub
:profile/customization-color
@@ -16,44 +16,21 @@
(fn [{:keys [customization-color]}]
(or customization-color constants/profile-default-color)))
(re-frame/reg-sub
:profile/onboarding-placeholder-avatar
:<- [:mediaserver/port]
:<- [:initials-avatar-font-file]
(fn [[port font-file] [_ profile-pic]]
{:fn
(if profile-pic
(image-server/get-account-image-uri-fn {:port port
:image-name profile-pic
:override-ring? false
:theme (theme/get-theme)})
(image-server/get-initials-avatar-uri-fn {:port port
:theme (theme/get-theme)
:override-ring? false
:font-file font-file}))}))
(re-frame/reg-sub
:profile/login-profiles-picture
:<- [:profile/profiles-overview]
:<- [:mediaserver/port]
:<- [:initials-avatar-font-file]
(fn [[multiaccounts port font-file] [_ target-key-uid]]
(let [{:keys [images ens-name?] :as multiaccount} (get multiaccounts target-key-uid)
image-name (-> images first :type)
override-ring? (not ens-name?)]
(when multiaccount
{:fn
(if image-name
(image-server/get-account-image-uri-fn {:port port
:image-name image-name
:key-uid target-key-uid
:theme (theme/get-theme)
:override-ring? override-ring?})
(image-server/get-initials-avatar-uri-fn {:port port
:key-uid target-key-uid
:theme (theme/get-theme)
:override-ring? override-ring?
:font-file font-file}))}))))
(fn [[multiaccounts port] [_ target-key-uid]]
(let [image-name (-> multiaccounts
(get-in [target-key-uid :images])
first
:type)]
(when image-name
(image-server/get-account-image-uri {:port port
:image-name image-name
:key-uid target-key-uid
:theme (theme/get-theme)
:ring? true})))))
(re-frame/reg-sub
:multiaccount/public-key
@@ -247,36 +224,30 @@
(pos? (count (get multiaccount :images)))))
(defn- replace-multiaccount-image-uri
[multiaccount port font-file avatar-opts]
(let [{:keys [key-uid ens-name? images]} multiaccount
theme (theme/get-theme)
avatar-opts (assoc avatar-opts :override-ring? (when ens-name? false))
images-with-uri (mapv (fn [{key-uid :keyUid image-name :type :as image}]
(let [uri-fn (image-server/get-account-image-uri-fn
(merge {:port port
:image-name image-name
:key-uid key-uid
:theme theme}
avatar-opts))]
(assoc image :fn uri-fn)))
images)
new-images (if (seq images-with-uri)
images-with-uri
[{:fn (image-server/get-initials-avatar-uri-fn
(merge {:port port
:key-uid key-uid
:theme theme
:font-file font-file}
avatar-opts))}])]
(assoc multiaccount :images new-images)))
[multiaccount port]
(let [public-key (:public-key multiaccount)
theme (theme/get-theme)
images (:images multiaccount)
images (reduce (fn [acc current]
(let [key-uid (:keyUid current)
image-name (:type current)
uri (image-server/get-account-image-uri {:port port
:public-key public-key
:image-name image-name
:key-uid key-uid
:theme theme
:ring? true})]
(conj acc (assoc current :uri uri))))
[]
images)]
(assoc multiaccount :images images)))
(re-frame/reg-sub
:profile/multiaccount
:<- [:profile/profile]
:<- [:mediaserver/port]
:<- [:initials-avatar-font-file]
(fn [[multiaccount port font-file] [_ avatar-opts]]
(replace-multiaccount-image-uri multiaccount port font-file avatar-opts)))
(fn [[multiaccount port]]
(replace-multiaccount-image-uri multiaccount port)))
(re-frame/reg-sub
:profile/login-profile
-1
View File
@@ -75,7 +75,6 @@
(reg-root-key-sub :password-authentication :password-authentication)
(reg-root-key-sub :shell/floating-screens :shell/floating-screens)
(reg-root-key-sub :shell/loaded-screens :shell/loaded-screens)
(reg-root-key-sub :initials-avatar-font-file :initials-avatar-font-file)
;;NOTE this one is not related to ethereum network
;; it is about cellular network/ wifi network
+15 -19
View File
@@ -1,12 +1,12 @@
(ns status-im2.subs.shell
(:require [re-frame.core :as re-frame]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.common.resources :as resources]
(:require [utils.i18n :as i18n]
[re-frame.core :as re-frame]
[utils.datetime :as datetime]
[status-im2.config :as config]
[status-im2.constants :as constants]
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
[utils.datetime :as datetime]
[utils.i18n :as i18n]))
[status-im2.common.resources :as resources]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.contexts.shell.jump-to.constants :as shell.constants]))
;; Helper Functions
(defn community-avatar
@@ -79,11 +79,13 @@
:counter-label (:unviewed-mentions-count chat)})))
(defn one-to-one-chat-card
[contact names profile-picture chat id communities]
(let [display-name (first names)]
{:title display-name
:avatar-params {:full-name display-name
:profile-picture profile-picture}
[contact names chat id communities]
(let [images (:images contact)
profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))]
{:title (first names)
:avatar-params {:full-name (first names)
:profile-picture (when profile-picture
(str profile-picture "&addRing=0"))}
:customization-color (or (:customization-color contact) :primary)
:content (get-card-content
{:chat chat
@@ -149,16 +151,10 @@
(fn [[_ id] _]
[(re-frame/subscribe [:contacts/contact-by-identity id])
(re-frame/subscribe [:contacts/contact-two-names-by-identity id])
(re-frame/subscribe [:chats/photo-path id])
(re-frame/subscribe [:chats/chat id])
(re-frame/subscribe [:communities])])
(fn [[contact names profile-picture chat communities] [_ id]]
(one-to-one-chat-card contact
names
profile-picture
chat
id
communities)))
(fn [[contact names chat communities] [_ id]]
(one-to-one-chat-card contact names chat id communities)))
(re-frame/reg-sub
:shell/private-group-chat-card
+7 -7
View File
@@ -70,11 +70,11 @@
(assoc acc
hash
(enrich-transaction transaction contacts native-currency))) ;;TODO this doesn't
;;look good for
;;performance, we
;;need to calculate
;;this only once for
;;each transaction
;;look good for
;;performance, we
;;need to calculate
;;this only once for
;;each transaction
{}
transactions)))
@@ -125,13 +125,13 @@
(case type
:inbound
(assoc transaction
:label (i18n/label :t/from)
:label (i18n/label :t/From)
:contact-accessibility-label :sender-text
:address-accessibility-label :sender-address-text
:contact from-contact
:address from)
(assoc transaction
:label (i18n/label :t/to)
:label (i18n/label :t/To)
:contact-accessibility-label :recipient-name-text
:address-accessibility-label :recipient-address-text
:contact to-contact
+4 -187
View File
@@ -1,43 +1,13 @@
(ns utils.image-server
(:require
[react-native.fs :as utils.fs]
[react-native.platform :as platform]
status-im.utils.pixel-ratio
[status-im2.constants :as constants]
[utils.datetime :as datetime]))
(:require [utils.datetime :as datetime]))
(def ^:const image-server-uri-prefix "https://localhost:")
(def ^:const account-images-action "/accountImages")
(def ^:const account-initials-action "/accountInitials")
(def ^:const contact-images-action "/contactImages")
(def ^:const generate-qr-action "/GenerateQRCode")
(def ^:const status-profile-base-url "https://join.status.im/u/")
(def ^:const status-profile-base-url-without-https "join.status.im/u/")
(defn get-font-file-ready
"setup font file and get the absolute path to it
this font file is passed to status-go later to render the initials avatar
for ios, it's located at main-bundle-path
for android, it's located in the assets dir which can not be accessed by status-go
so we copy one to the cache directory"
[callback]
(if platform/android?
(let [cache-dir (utils.fs/cache-dir)
font-file-name (:android constants/initials-avatar-font-conf)
src (str "fonts/" font-file-name)
dest (str cache-dir "/" font-file-name)
copy #(utils.fs/copy-assets src dest)
cb #(callback dest)]
(.then (utils.fs/file-exists? dest)
(fn [exists?]
(if exists?
(cb)
(.then (copy) cb)))))
(callback (str (utils.fs/main-bundle-path)
"/"
(:ios constants/initials-avatar-font-conf)))))
(defn timestamp [] (datetime/timestamp))
(defn current-theme-index
@@ -56,22 +26,7 @@
4))
(defn get-account-image-uri
"fn to get the avatar uri when multiaccount has custom image set
not directly called, check `get-account-image-uri-fn`
color formats (for all color options):
#RRGGBB
#RRGGBBAA
rgb(255,255,255)
rgba(255,255,255,0.1) note alpha is 0-1
non-placeholder-avatar: requires at least one of `public-key` or `key-uid`
placeholder-avatar: pass image file path as `image-name`
`indicator-size` is outer indicator radius
`indicator-size` - `indicator-border` is inner indicator radius"
[{:keys [port public-key image-name key-uid size theme indicator-size
indicator-border indicator-color ring?]}]
[{:keys [port public-key image-name key-uid theme ring?]}]
(str image-server-uri-prefix
port
account-images-action
@@ -81,130 +36,15 @@
key-uid
"&imageName="
image-name
"&size="
(Math/round (* size status-im.utils.pixel-ratio/ratio))
"&theme="
(current-theme-index theme)
"&clock="
(timestamp)
"&indicatorColor="
(js/encodeURIComponent indicator-color)
"&indicatorSize="
(* indicator-size status-im.utils.pixel-ratio/ratio)
"&indicatorBorder="
(* indicator-border status-im.utils.pixel-ratio/ratio)
"&addRing="
(if ring? 1 0)))
(defn get-account-image-uri-fn
"pass the result fn to user-avatar component as `:profile-picture`
use this fn in subs to set multiaccount `:images` as [{:fn ...}]
pass the image to user-avatar
user-avatar can fill the rest style related options
set `override-ring?` to a non-nil value to override `ring?`, mainly used to
hide ring for account with ens name
check `get-account-image-uri` for color formats"
[{:keys [port public-key key-uid image-name theme override-ring?]}]
(fn [{:keys [size indicator-size indicator-border indicator-color ring?
override-theme]}]
(get-account-image-uri
{:port port
:image-name image-name
:size size
:public-key public-key
:key-uid key-uid
:theme (if (nil? override-theme) theme override-theme)
:indicator-size indicator-size
:indicator-border indicator-border
:indicator-color indicator-color
:ring? (if (nil? override-ring?) ring? override-ring?)})))
(defn get-initials-avatar-uri
"fn to get the avatar uri when account/contact/placeholder has no custom pic set
not directly called, check `get-account-initials-uri-fn`
multiaccount: at least one of `key-uid`, `public-key` is required to render the ring
contact: `public-key` is required to render the ring
check `get-account-image-uri` for color formats
check `get-font-file-ready` for `font-file`
`uppercase-ratio` is the uppercase-height/line-height for `font-file`"
[{:keys [port public-key key-uid theme ring? length size background-color color
font-size font-file uppercase-ratio indicator-size indicator-border
indicator-color full-name]}]
(str
image-server-uri-prefix
port
account-initials-action
"?publicKey="
public-key
"&keyUid="
key-uid
"&length="
length
"&size="
(Math/round (* size status-im.utils.pixel-ratio/ratio))
"&bgColor="
(js/encodeURIComponent background-color)
"&color="
(js/encodeURIComponent color)
"&fontSize="
(* font-size status-im.utils.pixel-ratio/ratio)
"&fontFile="
(js/encodeURIComponent font-file)
"&uppercaseRatio="
uppercase-ratio
"&theme="
(current-theme-index theme)
"&clock="
"&name="
(js/encodeURIComponent full-name)
(timestamp)
"&indicatorColor="
(js/encodeURIComponent indicator-color)
"&indicatorSize="
(* indicator-size status-im.utils.pixel-ratio/ratio)
"&indicatorBorder="
(* indicator-border status-im.utils.pixel-ratio/ratio)
"&addRing="
(if ring? 1 0)))
(defn get-initials-avatar-uri-fn
"return a fn that calls `get-account-initials-uri`
pass the fn to user-avatar component to fill the style related options
check `get-account-image-uri` for color formats
check `get-font-file-ready` for `font-file`
check `get-account-image-uri-fn` for `override-ring?`"
[{:keys [port public-key key-uid theme override-ring? font-file]}]
(fn [{:keys [full-name length size background-color font-size color
indicator-size indicator-border indicator-color ring?
override-theme]}]
(get-initials-avatar-uri {:port port
:public-key public-key
:key-uid key-uid
:full-name full-name
:length length
:size size
:background-color background-color
:theme (if (nil? override-theme) theme override-theme)
:ring? (if (nil? override-ring?) ring? override-ring?)
:font-size font-size
:color color
:font-file font-file
:uppercase-ratio (:uppercase-ratio constants/initials-avatar-font-conf)
:indicator-size indicator-size
:indicator-border indicator-border
:indicator-color indicator-color})))
(defn get-contact-image-uri
[{:keys [port public-key image-name clock theme indicator-size indicator-border
indicator-color size ring?]}]
[port public-key image-name clock theme]
(str image-server-uri-prefix
port
contact-images-action
@@ -212,34 +52,11 @@
public-key
"&imageName="
image-name
"&size="
(Math/round (* size status-im.utils.pixel-ratio/ratio))
"&theme="
(current-theme-index theme)
"&clock="
clock
"&indicatorColor="
(js/encodeURIComponent indicator-color)
"&indicatorSize="
(* indicator-size status-im.utils.pixel-ratio/ratio)
"&indicatorBorder="
(* indicator-border status-im.utils.pixel-ratio/ratio)
"&addRing="
(if ring? 1 0)))
(defn get-contact-image-uri-fn
[{:keys [port public-key image-name theme override-ring? clock]}]
(fn [{:keys [size indicator-size indicator-border indicator-color ring? override-theme]}]
(get-contact-image-uri {:port port
:image-name image-name
:public-key public-key
:size size
:theme (if (nil? override-theme) theme override-theme)
:clock clock
:indicator-size indicator-size
:indicator-border indicator-border
:indicator-color indicator-color
:ring? (if (nil? override-ring?) ring? override-ring?)})))
"&addRing=1"))
(defn get-account-qr-image-uri
[{:keys [key-uid public-key port qr-size]}]
+9 -38
View File
@@ -1,46 +1,17 @@
(ns utils.image-server-test
(:require [cljs.test :as t]
status-im.utils.pixel-ratio
[utils.image-server :as sut]))
(t/deftest get-account-image-uri
(with-redefs
[sut/current-theme-index identity
status-im.utils.pixel-ratio/ratio 2
sut/timestamp (constantly "timestamp")]
[sut/current-theme-index identity
sut/timestamp (constantly "timestamp")]
(t/is
(=
(sut/get-account-image-uri {:port "port"
:public-key "public-key"
:image-name "image-name"
:key-uid "key-uid"
:theme :dark
:indicator-size 2
:indicator-color "rgba(9,16,28,0.08)"
:ring? true})
"https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&size=0&theme=:dark&clock=timestamp&indicatorColor=rgba(9%2C16%2C28%2C0.08)&indicatorSize=4&indicatorBorder=0&addRing=1"))))
(t/deftest get-account-initials-uri
(with-redefs
[sut/current-theme-index identity
status-im.utils.pixel-ratio/ratio 2
sut/timestamp (constantly "timestamp")]
(t/is
(=
(sut/get-initials-avatar-uri
{:port "port"
:public-key "public-key"
:key-uid "key-uid"
:full-name "full-name"
:length "length"
:size 48
:theme :light
:ring? "ring?"
:background-color "background-color"
:color "#0E162000"
:font-size 12
:font-file "/font/Inter Medium.otf"
:uppercase-ratio "uppercase-ratio"
:indicator-size 2
:indicator-color "#0E1620"})
"https://localhost:port/accountInitials?publicKey=public-key&keyUid=key-uid&length=length&size=96&bgColor=background-color&color=%230E162000&fontSize=24&fontFile=%2Ffont%2FInter%20Medium.otf&uppercaseRatio=uppercase-ratio&theme=:light&clock=&name=full-nametimestamp&indicatorColor=%230E1620&indicatorSize=4&indicatorBorder=0&addRing=1"))))
(sut/get-account-image-uri {:port "port"
:public-key "public-key"
:image-name "image-name"
:key-uid "key-uid"
:theme "theme"
:ring? true})
"https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&theme=theme&clock=timestamp&addRing=1"))))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "7603b10fb902244899836a19d906cd573fb26093",
"commit-sha1": "7603b10fb902244899836a19d906cd573fb26093",
"src-sha256": "0asnapan03skhxr1r9cmj3q2rfa36sky1qzczficw34kb2icgj15"
"version": "v0.163.8",
"commit-sha1": "d61f983d9555e98cf84a3b1273687914887c2e67",
"src-sha256": "1y0s5ivrkywj9simvv2i31ggfzg38li12if2lvfqn8nx10a5y9ai"
}

Some files were not shown because too many files have changed in this diff Show More