Compare commits

..
Author SHA1 Message Date
alwx 349c707066 Updated Go version 2023-08-17 11:46:49 +02:00
Churikova Tetiana aecad2136e e2e: starting to-dos 2023-08-17 05:09:19 +03:00
codemaster 673b1afc3a chore: update group-avatar component (#17014)
We merge it without QA because it only changes the API and doesn't need design review because nothing has been changed 👍
2023-08-17 06:44:30 +10:00
Icaro Motta b0f748cb73 Refactor Quo preview (#16996)
Improvements to quo previews:

- Change quo-preview.preview code to be more aligned with our guidelines.
- Remove duplication when setting up preview screens in quo-preview.main. Now we
  only need to specify the :name and :component keys and fallback to a good
  default for "{:options {:topBar {:visible true}}".
- Auto-generate descriptor labels based on the key.
- Fix form field colors for dark & light, especially for Android.
- Redesigned form fields to look nicer 💄
- Create component that abstracts away the code for rendering the form fields
  and the preview area. This will aid us in creating more consistent looking
  preview screens and keep things DRY.

How do we use the new code?

Just as before, define a state binding and use it to build up the arguments of
the component. Then, use the preview/preview-container to wrap the component.
You can use certain props to control how the preview is styled, etc, but that's
about it.

    (def descriptor
      [{:type :text :key :label}
       {:key     :chevron-position
        :type    :select
        :options [{:key :left}
                  {:key :right}]}])
    
    (defn view
      []
      (let [state (reagent/atom {:chevron-position :left
                                 :label            "Welcome"})]
        (fn []
          [preview/preview-container {:state state :descriptor descriptor}
           [quo/divider-label @state]])))
2023-08-16 11:30:21 +00:00
Andrea Maria Piana d988296ecf Add next in line for communities 2023-08-16 12:16:32 +01:00
Andrea Maria Piana dc8a09ce75 Update wallet team members 2023-08-16 12:16:08 +01:00
Andrea Maria Piana 0dea703ca0 3 lines community description 2023-08-16 12:15:12 +01:00
Ibrahem Khalil 50134ebeff Fix jump to button showing inside composer (#16999) 2023-08-15 11:31:50 +03:00
yqrashawn a6710f902f feat: render all avatars using media server (#16193) 2023-08-15 09:59:40 +08:00
108 changed files with 1951 additions and 2612 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
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?
react-native.fs/move-file
react-native.fs/read-dir
react-native.fs/mkdir
react-native.fs/unlink
react-native.fs/file-exists?
quo.animated/code
quo.animated/eq
quo.animated/neq
+3 -5
View File
@@ -16,7 +16,7 @@ The responsibilities of the team are to implement the new wallet UI, with the su
## Decision
Some team members have already expressed interest and some have been asked and accepted to join the wallet team, these team members are:
The team members for the initial wallet team are:
- @rasom
- @OmarBasem
@@ -25,7 +25,5 @@ Some team members have already expressed interest and some have been asked and a
- @briansztamfater
- @smohamedjavid
- @ulisesmac
# Follow-up Actions
- We still need 3/4 team members to join the wallet team
- @erikseppanen
- @mmilad75
+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
- Communities @ilmotta, followed by @ajayesivan
- Activity Center & Shell @J-Son89, followed by @Parveshdhull
- Wallet (once the vertical team is created) @J-Son89, followed by @briansztamfater
Binary file not shown.

Before

Width:  |  Height:  |  Size: 731 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

+2 -1
View File
@@ -90,7 +90,8 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
:configureNext (fn [])}
:requireNativeComponent (fn [] {:propTypes ""})
:Appearance {:getColorScheme (fn [])
:addChangeListener (fn [])}}))
:addChangeListener (fn [])}
:PixelRatio {:get (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)
: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)
:overflow :hidden
:background-color (colors/theme-colors (colors/custom-color customization-color 50)
(colors/custom-color customization-color 60)
theme)})
@@ -1,43 +1,35 @@
(ns quo2.components.avatars.group-avatar.view
(:require [quo2.components.icon :as icon]
[quo2.theme :as quo.theme]
[quo2.theme :as 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
{: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}})
{20 {:icon 12}
28 {:icon 16}
32 {:icon 16}
48 {:icon 20}
80 {:icon 32}})
(defn- view-internal
[_]
(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])]
(fn [{:keys [size theme customization-color picture]
:or {size 20
customization-color :blue}}]
(let [icon-size (get-in sizes [size :icon])]
[rn/view
{:style (style/container {:container-size container-size
{:style (style/container {:container-size size
:customization-color customization-color
:theme theme})}
(if picture
[fast-image/fast-image
{:source picture
:style {:width container-size
:height container-size}}]
[icon/icon icon-name
:style {:width size
:height size}}]
[icon/icon :i/members
{:size icon-size
:color colors/white-opa-70}])])))
(def view (quo.theme/with-theme view-internal))
(def view (theme/with-theme view-internal))
@@ -2,14 +2,9 @@
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
[test-helpers.component :as h]))
(defonce mock-picture (js/require "../resources/images/mock2/user_picture_male4.png"))
(defonce mock-picture {:uri (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
@@ -18,124 +13,5 @@
(h/test "Renders even if `:full-name` is passed"
(h/render
[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))))))
[user-avatar/user-avatar {:profile-picture mock-picture}])
(h/is-truthy (h/get-by-label-text :profile-picture)))))
@@ -2,97 +2,61 @@
(:require [quo2.foundations.colors :as colors]))
(def sizes
{:big {:outer 80
:inner 72
{:big {:dimensions 80
:status-indicator 20
:status-indicator-border 4
:font-size :heading-1}
:medium {:outer 48
:inner 44
:medium {:dimensions 48
:status-indicator 12
:status-indicator-border 2
:font-size :heading-2}
:small {:outer 32
:inner 28
:small {:dimensions 32
:status-indicator 12
:status-indicator-border 2
:font-size :paragraph-2}
28 {:outer 28
:inner 28
:xs {:dimensions 24
:status-indicator 0
:status-indicator-border 0
:font-size :paragraph-2}
:xs {:outer 24
:inner 24
:status-indicator 0
:status-indicator-border 0
:font-size :paragraph-2}
:xxs {:outer 20
:inner 20
:xxs {:dimensions 20
:status-indicator 0
:status-indicator-border 0
:font-size :label}
:xxxs {:outer 16
:inner 16
:xxxs {:dimensions 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 draw-ring? customization-color theme]
(let [outer-dimensions (get-in sizes [size :outer])
inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])]
[size customization-color theme]
(let [dimensions (get-in sizes [size :dimensions])]
{:position :absolute
:top (/ (- outer-dimensions inner-dimensions) 2)
:left (/ (- outer-dimensions inner-dimensions) 2)
:width inner-dimensions
:height inner-dimensions
:border-radius inner-dimensions
:top 0
:left 0
:width dimensions
:height dimensions
:border-radius 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,64 +1,104 @@
(ns quo2.components.avatars.user-avatar.view
(: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))
(: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))
(defn initials-avatar
[{:keys [full-name size draw-ring? customization-color theme]}]
[{:keys [full-name size 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 draw-ring? customization-color theme)}
:style (style/initials-avatar size customization-color theme)}
[text/text
{:style style/initials-avatar-text
:size font-size
:weight :semi-bold}
(utils.string/get-initials full-name amount-initials)]]))
(def valid-ring-sizes #{:big :medium :small})
(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}
(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
`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
online? true
ring? true
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,
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,
;; 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? rn/image fast-image/fast-image)]
[rn/view {:style outer-styles :accessibility-label :user-avatar}
;; The `profile-picture` already has the ring in it
(when-let [image (or profile-picture ring-background)]
[image-view
{: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?)}]])]))
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)]
(def user-avatar (quo.theme/with-theme user-avatar-internal))
[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]
[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})}])]))
(def user-avatar (quo2.theme/with-theme user-avatar-internal))
@@ -0,0 +1,49 @@
(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,23 +3,6 @@
[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.buttons.button.view :as buttons]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.buttons.button.view :as buttons]
[quo2.components.inputs.profile-input.style :as style]
[quo2.components.inputs.title-input.view :as title-input]
[react-native.core :as rn]
@@ -13,38 +13,40 @@
on-press
title-input-props
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
: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})]]])
(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})]]]))
@@ -21,12 +21,6 @@
: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
@@ -44,7 +38,6 @@
:size (case size
32 :small
24 :xs
20 :xxs
16 :xxxs)}
item)]
(:photo :collectible) [fast-image/fast-image
@@ -54,10 +47,11 @@
: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 (dec list-size))]
[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))]
[hole-view/hole-view
{:style {:margin-left (if (zero? index) 0 margin-left)}
{:style {:margin-left (if (= index 0) 0 margin-left)}
:holes (if last-item?
[]
[{:x hole-x
@@ -128,7 +122,8 @@
items preview list items (only 4 items is required for preview)
"
[{:keys [type size list-size transparent? theme more-than-99-label]} items]
(let [list-size (or list-size (count items))
(let [items-arr (into [] items)
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)])
@@ -138,7 +133,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 (vec items) index) list-size
[list-item index type size (get items-arr index) list-size
margin-left hole-size hole-radius hole-x hole-y border-radius])
(when (> list-size 4)
[overflow-label
+9 -10
View File
@@ -1,11 +1,11 @@
(ns quo2.components.list-items.user-list
(:require [react-native.core :as rn]
[quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.markdown.text :as text]
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
[quo2.components.icon :as icons]
[quo2.foundations.colors :as colors]
[quo2.components.markdown.text :as text]
[quo2.components.messages.author.view :as author]
[quo2.components.selectors.selectors.view :as selectors]))
[quo2.components.selectors.selectors.view :as selectors]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]))
(def container-style
{:margin-horizontal 8
@@ -45,11 +45,10 @@
: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
:status-indicator? true
:online? online?
:size :small}]
{:full-name primary-name
:profile-picture photo-path
:online? online?
:size :small}]
[rn/view {:style {:margin-left 8}}
[author/author
{:primary-name primary-name
+6 -10
View File
@@ -1,12 +1,12 @@
(ns quo2.components.markdown.list.view
(:require [quo2.components.counter.step.view :as step]
[quo2.components.icon :as icon]
[quo2.components.markdown.list.style :as style]
(:require [react-native.core :as rn]
[quo2.components.markdown.text :as text]
[quo2.components.tags.context-tag.view :as context-tag]
[quo2.components.counter.step.view :as step]
[quo2.components.markdown.list.style :as style]
[quo2.components.icon :as icon]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[react-native.core :as rn]))
[quo2.components.tags.context-tag.view :as context-tag]))
(defn get-colors
[theme blur?]
@@ -27,11 +27,7 @@
:size :paragraph-2}
description]
[rn/view {:style {:margin-left 4}}
[context-tag/view
{:blur? blur?
:size 24
:profile-picture tag-picture
:full-name tag-name}]]
[context-tag/context-tag {:blur? blur?} tag-picture 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,31 +24,27 @@
(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}}]
(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]]))))
(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]])))
+37 -87
View File
@@ -1,11 +1,31 @@
(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
[theme blur?]
[blur?]
(if blur?
(colors/theme-colors colors/neutral-80-opa-40 colors/white-opa-40 theme)
(colors/theme-colors colors/neutral-50 colors/neutral-40 theme)))
(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})
(def audio-tag-icon-container
{:width 20
@@ -17,91 +37,21 @@
(def audio-tag-icon-color colors/white)
(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))))
(defn audio-tag-text-color
[override-theme]
(colors/theme-colors colors/neutral-100 colors/white override-theme))
(defn tag-container
[size]
{:margin-right (if (= size 24) 6 10)
(def community-tag
{:padding-vertical 2
:padding-left 2})
(def community-tag-text-container
{:margin-left 4
:flex 1
:flex-direction :row
:align-items :center})
(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})
(defn community-tag-text
[override-theme]
{:margin-left 2
:color (colors/theme-colors colors/neutral-100 colors/white override-theme)})
+91 -197
View File
@@ -1,212 +1,106 @@
(ns quo2.components.tags.context-tag.view
(:require [quo2.components.avatars.account-avatar.view :as account-avatar]
[quo2.components.avatars.group-avatar.view :as group-avatar]
(:require [quo2.components.avatars.group-avatar.view :as group-avatar]
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
[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- 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
(defn trim-public-key
[pk]
(str (subs pk 0 5) "..." (subs pk (- (count pk) 3))))
(str (subs pk 0 6) "..." (subs pk (- (count pk) 3))))
(defn- address-tag
[{:keys [theme size address]}]
[rn/view {:style (style/address size)}
(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]
[text/text
{:style (style/text theme)
:weight :monospace ;; TODO: fix this style (issue #17009)
:size (if (= size 24) :paragraph-2 :paragraph-1)}
(trim-public-key address)]])
{:weight :medium
:size :paragraph-2
:style (:text-style opts)}
(str " " label)]])
(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 public-key-tag
[params public-key]
[base-tag params
[text/text
{:weight :monospace
:size :paragraph-2}
(trim-public-key public-key)]])
(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 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)]])]]))
:multiuser
[preview-list/preview-list {:type :user :size 20}
users]
(defn user-avatar-tag
[params username photo]
[context-tag params photo username])
: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 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]])
: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))
(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])
@@ -1,19 +0,0 @@
(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))))
@@ -1,83 +0,0 @@
(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})
@@ -1,169 +0,0 @@
(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))
+6 -5
View File
@@ -114,8 +114,7 @@
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-activity.view))
quo2.components.wallet.wallet-overview.view))
(def separator quo2.components.common.separator.view/separator)
@@ -302,8 +301,11 @@
(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 context-tag quo2.components.tags.context-tag.view/view)
(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)
;;;; Title
(def title quo2.components.text-combinations.title.view/title)
@@ -317,4 +319,3 @@
(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)
+1 -2
View File
@@ -59,5 +59,4 @@
[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-activity.component-spec]))
[quo2.components.wallet.wallet-overview.component-spec]))
-4
View File
@@ -28,7 +28,3 @@
{: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,3 +42,11 @@
(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))
+8 -2
View File
@@ -1,6 +1,6 @@
(ns status-im.contact.core
(:require [utils.re-frame :as rf]
[status-im2.navigation.events :as navigation]))
(:require [status-im2.navigation.events :as navigation]
[utils.re-frame :as rf]))
(rf/defn open-contact-toggle-list
{:events [:contact.ui/start-group-chat-pressed]}
@@ -10,3 +10,9 @@
: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)))
+10 -9
View File
@@ -1,13 +1,13 @@
(ns status-im.multiaccounts.logout.core
(:require [re-frame.core :as re-frame]
[utils.i18n :as i18n]
(:require [native-module.core :as native-module]
[re-frame.core :as re-frame]
[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]))
[status-im2.db :as db]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(re-frame/reg-fx
::logout
@@ -15,14 +15,15 @@
(native-module/logout)))
(rf/defn initialize-app-db
[{{:keys [keycard]
[{{:keys [keycard initials-avatar-font-file]
:biometric/keys [supported-type]
:network/keys [type]}
:db}]
{:db (assoc db/app-db
:network/type type
:keycard (dissoc keycard :secrets :pin :application-info)
:biometric/supported-type supported-type)})
:network/type type
:initials-avatar-font-file initials-avatar-font-file
:keycard (dissoc keycard :secrets :pin :application-info)
:biometric/supported-type supported-type)})
(rf/defn logout-method
{:events [::logout-method]}
+8 -5
View File
@@ -1,5 +1,6 @@
(ns status-im.multiaccounts.update.core
(:require [status-im.utils.types :as types]
(:require [status-im.ethereum.ens :as ens]
[status-im.utils.types :as types]
[status-im2.constants :as constants]
[taoensso.timbre :as log]
[utils.re-frame :as rf]))
@@ -19,10 +20,12 @@
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
{:json-rpc/call [{:method "multiaccounts_updateAccount"
:params [(assoc account :name new-name)]
:on-success #(log/debug "sent multiaccount update")}]}))))
(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/defn multiaccount-update
"Takes effects (containing :db) + new multiaccount fields, adds all effects necessary for multiaccount update.
@@ -2,8 +2,11 @@
(: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]
@@ -47,7 +50,7 @@
[rn/text {:style (:default-chat-icon-text styles)} emoji]]))
(defn profile-photo-plus-dot-view
[{:keys [public-key photo-container photo-path community?]}]
[{:keys [public-key full-name customization-color photo-container photo-path community?]}]
(let [photo-container (if (nil? photo-container)
styles/container-chat-list
photo-container)
@@ -55,11 +58,28 @@
dot-styles (visibility-status-utils/icon-visibility-status-dot
public-key
size)
dot-accessibility-label (:accessibility-label dot-styles)]
dot-accessibility-label (:accessibility-label dot-styles)
text-style (styles/default-chat-icon-text size)]
[rn/view
{:style photo-container
:accessibility-label :profile-photo}
[photos/photo photo-path {:size size}]
(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}])
(when-not community?
[rn/view
{:style dot-styles
@@ -179,14 +199,28 @@
(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)]
(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)]
[rn/view (:container styles)
(if (and photo-path (seq photo-path))
[profile-photo-plus-dot-view
@@ -2,23 +2,25 @@
(: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])
[status-im.ui.components.react :as react]
[utils.i18n :as i18n])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
(defn contacts-list-item
[{:keys [public-key] :as contact}]
(let [{:keys [primary-name secondary-name]} contact]
(let [{:keys [primary-name secondary-name customization-color]} contact]
[quo/list-item
{:title primary-name
:subtitle secondary-name
:icon [chat-icon.screen/profile-photo-plus-dot-view
{:public-key public-key
:photo-path (multiaccounts/displayed-photo contact)}]
{:public-key public-key
:full-name primary-name
:customization-color (or customization-color :primary)
:photo-path (multiaccounts/displayed-photo contact)}]
:chevron true
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
@@ -3,9 +3,10 @@
[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]
@@ -13,8 +14,9 @@
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.profile.components.sheets :as sheets]
[utils.re-frame :as rf]
[status-im2.constants :as constants]))
[status-im2.constants :as constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn actions
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
@@ -179,9 +181,11 @@
:as contact}
@(re-frame/subscribe
[:contacts/current-contact])
muted? @(re-frame/subscribe [:chats/muted
public-key])
{:keys [primary-name secondary-name]} contact
{:keys [primary-name secondary-name customization-color]} contact
customization-color (or customization-color :primary)
on-share #(re-frame/dispatch
[:show-popover
(merge
@@ -201,14 +205,17 @@
: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
:photo (multiaccounts/displayed-photo contact)
:monospace (not ens-verified)
:subtitle secondary-name
:compressed-key compressed-key
:public-key public-key})]
: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})]
[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,7 +19,9 @@
[status-im.utils.gfycat.core :as gfy]
[status-im.utils.universal-links.utils :as universal-links]
[status-im.utils.utils :as utils]
[status-im2.config :as config])
[status-im2.common.qr-code-viewer.view :as qr-code-viewer]
[status-im2.config :as config]
[utils.i18n :as i18n])
(:require-macros [status-im.utils.views :as views]))
(views/defview share-chat-key
@@ -190,9 +192,12 @@
(let [{:keys [public-key
compressed-key
ens-verified
preferred-name]
preferred-name
key-uid]
: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
@@ -213,6 +218,8 @@
: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
@@ -0,0 +1,4 @@
(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 [utils.i18n :as i18n]
[quo2.core :as quo]
(:require [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,12 +41,7 @@
(= contact-name-by-identity
nil) name
:else contact-name-by-identity)
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])))]
photo-path (or profile-picture (rf/sub [:chats/photo-path id]))]
[rn/view
{:style {:margin-horizontal 20}
:accessibility-label accessibility-label}
+17
View File
@@ -0,0 +1,17 @@
(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)}))
+1 -4
View File
@@ -60,10 +60,7 @@
{:accessibility-label :open-profile
:style style/left-section}
[quo/user-avatar
(merge {:status-indicator? true
:size :small
:online? online?}
avatar)]]]))
(merge {: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)]
[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/user-avatar-tag
{:size :small
:style {:margin-top 8 :margin-bottom 20}}
(multiaccounts/displayed-name account)
(multiaccounts/displayed-photo account)]
[quo/input
{:type :password
:label (i18n/label :t/profile-password)
+10 -3
View File
@@ -11,10 +11,17 @@
(defn toast
[toast-id]
(let [{:keys [type] :as toast-opts} (rf/sub [:toasts/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)]
(if (= type :notification)
[quo/notification toast-opts]
[quo/toast toast-opts])))
[quo/notification toast-opts-with-profile-picture]
[quo/toast toast-opts-with-profile-picture])))
(defn f-container
[toast-id]
+8
View File
@@ -345,3 +345,11 @@
(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,10 +2,9 @@
(:require
[clojure.string :as string]
[quo2.core :as quo]
[react-native.core :as rn]
[react-native.clipboard :as clipboard]
[react-native.core :as rn]
[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]
@@ -15,8 +14,8 @@
(defn found-contact
[public-key]
(let [{:keys [primary-name compressed-key]
:as contact} (rf/sub [:contacts/contact-by-identity 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])]
(when primary-name
[rn/view style/found-user
[quo/text (style/text-description)
@@ -24,7 +23,7 @@
[rn/view (style/found-user-container)
[quo/user-avatar
{:full-name primary-name
:profile-picture (multiaccounts/displayed-photo contact)
:profile-picture photo-path
: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]
[status-im2.constants :as constant]
[react-native.core :as rn]
[react-native.linear-gradient :as linear-gradient]
[react-native.reanimated :as reanimated]
[status-im.ethereum.stateofus :as stateofus]
[utils.re-frame :as rf]
[status-im2.constants :as constant]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.reply.style :as style]
[react-native.linear-gradient :as linear-gradient]))
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn get-quoted-text-with-mentions
[parsed-text]
@@ -63,8 +63,7 @@
(defn reply-from
[{:keys [from contact-name current-public-key]}]
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
contact (rf/sub [:contacts/contact-by-address from])
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))]
photo-path (rf/sub [:chats/photo-path from])]
[rn/view {:style style/reply-from}
[quo/user-avatar
{:full-name display-name
@@ -41,7 +41,6 @@
(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 [quo2.core :as quo]
(:require [clojure.string :as string]
[quo2.components.icon :as icons]
[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]
[quo2.components.icon :as icons]))
[utils.re-frame :as rf]))
(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])
image-key (if (seq (:images contact)) :profile-picture :ring-background)]
photo-path (rf/sub [:chats/photo-path chat-id])]
[quo/user-avatar
{:full-name full-name
:size :small
:online? online?
image-key photo-path
:muted? muted?}])
(cond-> {:full-name full-name
:size :small
:online? online?
:profile-picture photo-path}
muted?
(assoc :ring? false))])
[quo/group-avatar
{:customization-color color
:size :small}]))
@@ -1,21 +1,19 @@
(ns status-im2.contexts.chat.messages.avatar.view
(:require [utils.re-frame :as rf]
(:require [quo2.core :as quo]
[react-native.core :as rn]
[quo2.core :as quo]))
[utils.re-frame :as rf]))
(defn avatar
[public-key size]
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
contact (rf/sub [:contacts/contact-by-address public-key])
photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path public-key]))
photo-path (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
:status-indicator? true
:online? online?
:size size}]]]))
{:full-name display-name
:profile-picture photo-path
:online? online?
:size size}]]]))
@@ -28,9 +28,7 @@
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)]))
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)]))]
photo-path (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]
[status-im2.contexts.chat.composer.constants :as composer.constants]
[utils.re-frame :as rf]
[utils.i18n :as i18n]))
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
(defonce ^:const loading-indicator-extra-spacing 250)
@@ -203,8 +203,7 @@
online? (rf/sub [:visibility-status-updates/online? 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]))
photo-path (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]
[status-im2.config :as config]
[react-native.reanimated :as reanimated]
[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]
[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]
[status-im2.common.home.actions.view :as actions]))
[utils.re-frame :as rf]))
(defn f-view
[{:keys [scroll-y]}]
@@ -27,10 +27,7 @@
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
(str emoji " " chat-name))
online? (rf/sub [:visibility-status-updates/online? 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]))
photo-path (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 community-tag
(def context-tag
{:margin-right :auto
:margin-top 8})
@@ -14,10 +14,7 @@
:weight :semi-bold
:size :heading-1}
title]]
[rn/view {:style style/community-tag}
[quo/context-tag
{:type :community
:size 24
:community-logo (:thumbnail images)
:community-name name}]]
[quo/context-tag
{:style style/context-tag}
(:thumbnail images) name]
children]))
@@ -37,12 +37,11 @@
:weight :semi-bold
:size :heading-1}
(request-to-join-text open?)]]
[rn/view {:style {:margin-right :auto :margin-top 8}}
[quo/context-tag
{:type :community
:size 24
:community-logo (:thumbnail images)
:community-name name}]]
[quo/context-tag
{:style
{:margin-right :auto
:margin-top 8}}
(:thumbnail images) 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 2
:number-of-lines 4
: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,8 +28,7 @@
[{:keys [contact]}]
(let [{:keys [primary-name nickname public-key]} contact
entered-nickname (reagent/atom (or nickname ""))
photo-path (when-not (empty? (:images contact))
(rf/sub [:chats/photo-path public-key]))
photo-path (rf/sub [:chats/photo-path public-key])
insets (safe-area/get-insets)]
(fn [{:keys [title description accessibility-label
close-button-text]}]
@@ -41,10 +40,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 [quo2.core :as quo]
[clojure.string :as string]
(:require [clojure.string :as string]
[oops.core :as oops]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[status-im2.contexts.onboarding.create-profile.style :as style]
[utils.i18n :as i18n]
[react-native.blur :as blur]
[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.contexts.onboarding.common.navigation-bar.view :as navigation-bar]
[status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu]
[utils.re-frame :as rf]
[oops.core :as oops]
[react-native.blur :as blur]
[status-im2.constants :as c]
[react-native.platform :as platform]))
[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]))
;; NOTE - validation should match with Desktop
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
@@ -162,9 +162,12 @@
[:show-bottom-sheet
{:content
(fn []
[method-menu/view on-change-profile-pic])
:theme :dark}]))
:image-picker-props {:profile-picture (when @profile-pic {:uri @profile-pic})
[method-menu/view on-change-profile-pic])}]))
:image-picker-props {:profile-picture (or
@profile-pic
(rf/sub
[:profile/onboarding-placeholder-avatar
@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]
[react-native.reanimated :as reanimated]
[quo2.foundations.typography :as typography]))
[quo2.foundations.typography :as typography]
[react-native.reanimated :as reanimated]))
(def card-view
{:margin-horizontal 20
@@ -36,7 +36,7 @@
:background-color :transparent
:height 48
:border-color :black
:border-width 2
:border-width 3
:border-radius 44}))
(def picture-avatar-mask
@@ -1,12 +1,12 @@
(ns status-im2.contexts.onboarding.identifiers.profile-card.view
(:require [react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.masked-view :as masked-view]
[reagent.core :as reagent]
[quo2.core :as quo]
(:require [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]))
[react-native.core :as rn]
[react-native.masked-view :as masked-view]
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im2.contexts.onboarding.identifiers.profile-card.style :as style]
[utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting]))
(defn- f-profile-card-component
[{:keys [profile-picture name hash emoji-hash
@@ -20,29 +20,24 @@
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)]
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}]]
[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)}
[quo/user-avatar
{:full-name name
:profile-picture profile-picture
:size :medium
:status-indicator? false
:customization-color customization-color}]]
[reanimated/view {:style (style/avatar avatar-opacity)} avatar]
[masked-view/masked-view
{:style {:position :absolute}
:mask-element (reagent/as-element
[reanimated/view {:style (style/mask-view ring-opacity)}])}
(when profile-picture
[rn/image
{:accessibility-label :ring-background
:style style/picture-avatar-mask
:source profile-picture}])]]
(when profile-picture avatar)]]
[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 (when profile-picture {:uri profile-picture})
:profile-picture 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 (when profile-picture {:uri profile-picture})
:profile-picture profile-picture
:card-style style/login-profile-card}]
[quo/input
{:type :password
+3 -1
View File
@@ -1,9 +1,11 @@
(ns status-im2.contexts.profile.rpc
(:require [clojure.string :as string]))
(:require [clojure.string :as string]
[status-im.ethereum.ens :as ens]))
(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 :x-small
:value "x-small"}
{:key :small
:value "Small"}
{:key :medium
:value "Medium"}
{:key :large
:value "Large"}
{:key :x-large
:value "x-Large"}]}
:options [{:key 20
:value 20}
{:key 28
:value 28}
{:key 32
:value 32}
{:key 48
:value 48}
{:key 80
:value 80}]}
{:label "Avatar"
:key :picture?
:type :boolean}
(preview/customization-color-option)])
(def avatar (resources/get-mock-image :user-picture-male4))
(def avatar (resources/get-mock-image :photo1))
(defn cool-preview
[]
(let [state (reagent/atom {:theme :light
:customization-color :blue
:size :small
:size 20
:picture? false})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
@@ -67,12 +67,7 @@
{:padding-vertical 60
:flex-direction :row
:justify-content :center}
(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])]]])))
[quo2/user-avatar @state]]]])))
(defn preview-user-avatar
[]
@@ -1,48 +1,26 @@
(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
[{:label "Color:"
:key :color
[{:key :selected
:type :select
:options (map (fn [color]
(let [k (get color :name)]
{:key k :value k}))
(quo/picker-colors))}
{:label "Blur?"
:key :blur
:type :boolean}])
{:key :blur?
:type :boolean}])
(defn cool-preview
(defn view
[]
(let [state (reagent/atom {:color "orange" :blur false})
blur (reagent/cursor state [:blur])
color (reagent/cursor state [:color])]
(let [state (reagent/atom {:selected :orange
:blur? false})]
(fn []
[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}]])
[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 %))]])))
@@ -1,54 +1,29 @@
(ns status-im2.contexts.quo-preview.dividers.divider-label
(:require [quo2.components.dividers.divider-label :as divider-label]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
(:require [quo2.core :as quo]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Label:"
:key :label
:type :text}
{:label "Chevron position:"
:key :chevron-position
[{:type :text :key :label}
{:type :text :key :counter-value}
{:type :boolean :key :increase-padding-top?}
{:type :boolean :key :blur?}
{:key :chevron-position
:type :select
: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}])
:options [{:key :left}
{:key :right}]}])
(defn cool-preview
(defn view
[]
(let [state (reagent/atom {:label "Welcome"
(let [state (reagent/atom {:blur? false
:chevron-position :left
:counter-value 0
:counter-value "0"
:increase-padding-top? true
:blur? false})]
:label "Welcome"})]
(fn []
[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}]])
[preview/preview-container
{:state state
:descriptor descriptor
:blur? (:blur? @state)
:show-blur-background? true}
[quo/divider-label @state]])))
@@ -25,21 +25,15 @@
(defn example-tags
[blur?]
[[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"}]])
[[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"]])
(defn cool-preview
[]
@@ -1,100 +1,56 @@
(ns status-im2.contexts.quo-preview.links.link-preview
(:require [clojure.string :as string]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
(:require [quo2.core :as quo]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]
utils.number))
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{: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 :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
:type :select
:options (mapv (fn [k]
{:key k
:value (string/capitalize (name k))})
:options (mapv (fn [k] {:key k})
(keys resources/mock-images))}
{:label "Thumbnail size"
:key :thumbnail-size
{:key :thumbnail-size
:type :select
:options [{:key :normal
:value :normal}
{:key :large
:value :large}]}])
:options [{:key :normal}
{:key :large}]}])
(defn cool-preview
(defn view
[]
(let [state (reagent/atom
{:title "Rarible - NFT Marketplace"
:description "Turn your products or services into publicly tradeable items"
{:description "Turn your products or services into publicly tradeable items"
:disabled-text "Enable Preview"
:enabled? true
:link "rarible.com"
:thumbnail :collectible
:width "295"
:with-logo? true
:with-thumbnail? true
:with-description? true
:enabled? true
:thumbnail-size :normal
:disabled-text "Enable Preview"})]
:title "Rarible - NFT Marketplace"
:width 295
:with-description? true
:with-logo? true
:with-thumbnail? true})]
(fn []
(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}]])
(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)}}]]))))
@@ -1,30 +1,18 @@
(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
[{: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}])
[{:type :text :key :title}
{:type :text :key :body}
{:type :boolean :key :with-logo?}
{:type :boolean :key :loading?}
{:type :text :key :loading-message}])
(defn cool-preview
(defn view
[]
(let [state (reagent/atom
{:title "Status - Private, Secure Communication"
@@ -33,29 +21,12 @@
:loading? false
:loading-message "Generating preview"})]
(fn []
[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}]])
[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")}]])))
@@ -1,50 +1,34 @@
(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]
utils.number))
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Number of previews"
:key :previews-length
:type :text}])
[{:type :number :key :previews-length}])
(defn cool-preview
(defn view
[]
(let [state (reagent/atom {:previews-length "3"})]
(let [state (reagent/atom {:previews-length 3})
padding 20]
(fn []
(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}]])
[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)})}]])))
@@ -2,39 +2,33 @@
(: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
{:label "Type:"
{:type :select
:key :type
:type :select
:options [{:key :discover :value "Discover"}
{:key :engage :value "Engage"}
{:key :share :value "Share"}]})
:options [{:key :discover}
{:key :engage}
{:key :share}]})
(def descriptor-locked
{:label "Locked?" :key :locked? :type :boolean})
{:type :boolean :key :locked?})
(def descriptor-unread-count
{:label "Unread count:" :key :unread-count :type :number})
{:type :number :key :unread-count})
(def descriptor-title
{:label "Title:" :key :title :type :text})
{:type :text :key :title})
(def descriptor-blur
{:label "Blur?" :key :blur? :type :boolean})
{:type :boolean :key :blur?})
(def descriptor-member-stats
[{:label "Total member count:"
:key :members-count
:type :number}
{:label "Active member count:"
:key :active-count
:type :number}])
[{:type :number :key :members-count}
{:type :number :key :active-count}])
(def descriptors-base
[descriptor-type
@@ -43,29 +37,27 @@
(def descriptors-type-discover
(conj descriptors-base
{:label "Info:"
{:type :select
:key :info
:type :select
:options [{:key :token-gated :value "Token gated"}
{:key :default :value "Default"}]}
:options [{:key :token-gated}
{:key :default}]}
{:label "Member stats?"
:key :members?
:type :boolean}))
:type :boolean
:key :members?}))
(def descriptors-type-engage
(conj descriptors-base
{:label "Info:"
{:type :select
:key :info
: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"}]}))
:options [{:key :notification}
{:key :mention}
{:key :muted}
{:key :token-gated}
{:key :navigation}
{:key :default}]}))
(def descriptors-type-share
(conj descriptors-base {:label "Subtitle:" :key :subtitle :type :text}))
(conj descriptors-base {:type :text :key :subtitle}))
(defn descriptors
[{:keys [members? info] :as state}]
@@ -88,7 +80,7 @@
(into [descriptor-blur] descs)
descs)))
(defn cool-preview
(defn view
[]
(let [state (reagent/atom {:blur? false
:customization-color :blue
@@ -103,30 +95,16 @@
:unread-count 5})]
(fn []
(let [customization-color (colors/custom-color-by-theme (:customization-color @state) 50 60)]
[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}]])
[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)})})]]))))
+49 -161
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,352 +116,237 @@
[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
:options {:topBar {:visible true}}
:component color-picker/preview-color-picker}]
:component color-picker/view}]
: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}
:topBar {:visible true}}
:options {:insets {:bottom? true}}
:component token-gating/preview-token-gating}
{:name :channel-actions
:options {:insets {:bottom? true}
:topBar {:visible true}}
:options {:insets {:bottom? 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
:options {:topBar {:visible true}}
:component divider-label/preview-divider-label}
:component divider-label/view}
{: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}
:topBar {:visible true}}
:options {:insets {:top? true}}
:component keyboard-key/preview-keyboard-key}
{:name :numbered-keyboard
:options {:insets {:top? true}
:topBar {:visible true}}
:options {:insets {:top? true}}
:component numbered-keyboard/preview-numbered-keyboard}]
:links [{:name :url-preview
:options {:insets {:top? true}
:topBar {:visible true}}
:component url-preview/preview}
:options {:insets {:top? true}}
:component url-preview/view}
{:name :url-preview-list
:options {:insets {:top? true}
:topBar {:visible true}}
:component url-preview-list/preview}
:options {:insets {:top? true}}
:component url-preview-list/view}
{:name :link-preview
:options {:insets {:top? true}
:topBar {:visible true}}
:component link-preview/preview}]
:options {:insets {:top? true}}
:component link-preview/view}]
: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}
:topBar {:visible true}}
:component community-list/preview}
:options {:insets {:top? true}}
:component community-list/view}
{: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
:options {:topBar {:visible true}}
:component wallet-overview/preview-wallet-overview}
{:name :wallet-activity
:options {:topBar {:visible true}}
:component wallet-activity/preview-wallet-activity}]
:component wallet-overview/preview-wallet-overview}]
:keycard [{:name :keycard-component
:options {:topBar {:visible true}}
:component keycard/preview-keycard}]})
(def screens (flatten (map val screens-categories)))
(defn navigation-bar
(defn- navigation-bar
[]
(let [logged-in? (rf/sub [:multiaccount/logged-in?])
has-profiles? (boolean (rf/sub [:profile/profiles-overview]))
@@ -481,48 +366,51 @@
(theme/set-theme :dark)
(rf/dispatch [:init-root root]))))}}]))
(defn theme-switcher
(defn- theme-switcher
[]
[rn/view
{:style {:flex-direction :row
:justify-content :space-between
:padding-horizontal 24
:padding-vertical 12}}
[rn/view {:style style/theme-switcher}
[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)]
(let [open? (reagent/atom false)
on-change #(swap! open? not)]
(fn [category]
[rn/view {:style {:margin-vertical 8}}
[quo/dropdown {:selected @open? :on-change #(swap! open? not) :type :grey}
(clojure.core/name (key category))]
[quo/dropdown
{:selected @open?
:on-change on-change
:type :grey}
(name (key category))]
(when @open?
(for [{:keys [name]} (val category)]
^{:key name}
(for [{category-name :name} (val category)]
^{:key category-name}
[quo/button
{:type :outline
:container-style {:margin-vertical 8}
:on-press #(rf/dispatch [:navigate-to name])}
(clojure.core/name name)]))])))
:on-press #(rf/dispatch [:navigate-to category-name])}
(name category-name)]))])))
(defn main-screen
(defn- main-screen
[]
(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))]]]))
[:<>
[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})))))
(def main-screens
[{:name :quo2-preview
@@ -1,7 +1,6 @@
(ns status-im2.contexts.quo-preview.notifications.activity-logs
(:require [quo2.core :as quo]
(:require [quo2.core :as quo2]
[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]
@@ -68,20 +67,27 @@
status-tags/status-tags-options])
(def basic-user-action
[[quo/context-tag
{:size 24
:full-name "Name"
:blur? true}]
[[quo2/user-avatar-tag
{:color :purple
:override-theme :dark
:size :small
:style {:background-color colors/white-opa-10}
:text-style {:color colors/white}}
"Name"]
"did something here."])
(def complex-user-action
[[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}]])
(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"]]))
(def message-with-mention
(let [common-text-style {:style {:color colors/white}
@@ -89,8 +95,8 @@
{:body [rn/view
{:flex 1
:flex-direction :row}
[quo/text common-text-style "Hello"]
[quo/text
[quo2/text common-text-style "Hello"]
[quo2/text
{:style {:background-color colors/primary-50-opa-10
:border-radius 6
:color colors/primary-50
@@ -98,7 +104,7 @@
:padding-horizontal 3
:size :paragraph-1}}
"@name"]
[quo/text common-text-style "! How are you feeling?"]]}))
[quo2/text common-text-style "! How are you feeling?"]]}))
(def message-with-title
{:body "Your favorite color is Turquoise."
@@ -170,13 +176,12 @@
{:flex 1
:padding 16}
[preview/customizer state descriptor]]
[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]]]]))))
[rn/view
{:background-color colors/neutral-90
:flex-direction :row
:justify-content :center
:padding-vertical 60}
[quo2/activity-log props]]]))))
(defn preview-activity-logs
[]
@@ -1,7 +1,6 @@
(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]))
@@ -34,8 +33,7 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:customization-color :blue}]
:title "Alisher Yakupov accepted your contact request"
:duration 4000
:title-weight :medium
@@ -50,8 +48,7 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:customization-color :blue}]
:title "Default to semibold title"
:text "The quick brown fox jumped over the lazy dog and ate a potatoe."
:duration 4000
@@ -66,8 +63,7 @@
:status-indicator? true
:online? true
:size :small
:customization-color :blue
:ring-background (resources/get-mock-image :ring)}]
:customization-color :blue}]
:header [rn/view
[quo/info-message
{:type :success
+163 -187
View File
@@ -1,216 +1,178 @@
(ns status-im2.contexts.quo-preview.preview
(:require [clojure.string :as string]
(:require [camel-snake-kebab.core :as camel-snake-kebab]
[clojure.string :as string]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[quo2.theme :as theme]
[quo2.theme :as quo.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))
(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
(defn- label-view
[_ label]
[rn/view {:style label-style}
[rn/text
(when-let [label-color (colors/theme-colors colors/neutral-100 colors/white)]
{:style {:color label-color}})
[rn/view {:style style/label-container}
[rn/text {:style (style/label)}
label]])
(defn modal-container
[]
{:flex 1
:justify-content :center
:padding-horizontal 24
:background-color "rgba(0,0,0,0.4)"})
(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-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->boolean-label
[k]
(let [label (humanize k)]
(if (string/ends-with? label "?")
label
(str label "?"))))
(defn customizer-boolean
(defn- key->text-label
[k]
(str (humanize k) ":"))
(defn- customizer-boolean
[{:keys [label state] :as args}]
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
(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}
[label-view state label]
[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
[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?)}
"True"]]
[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 {}
[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?))}
"False"]]]]))
(defn customizer-text
(defn- customizer-text
[{:keys [label state limit suffix] :as args}]
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[rn/view {:style style/field-row}
[label-view state label]
[rn/view {:style {:flex 0.6}}
[rn/view {:style style/field-column}
[rn/text-input
(merge
{:value @state*
{:value @field-value
:show-cancel false
: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))}
: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))}
(when limit
{:max-length limit}))]]]))
(defn customizer-number
(defn- customizer-number
[{:keys [label state default] :as args}]
(let [state* (reagent/cursor state [(:key args)])]
[rn/view {:style container}
(let [label (or label (key->text-label (:key args)))
field-value (reagent/cursor state [(:key args)])]
[rn/view {:style style/field-row}
[label-view state label]
[rn/view {:style {:flex 0.6}}
[rn/view {:style style/field-column}
[rn/text-input
(merge
{:value (str @state*)
{:value (str @field-value)
:show-cancel false
: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))
: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))
(reagent/flush))})]]]))
(defn value-for-key
(defn- find-selected-option
[id v]
(:value (first (filter #(= (:key %) id) v))))
(first (filter #(= (:key %) id) v)))
(defn customizer-select
(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
[]
(let [open (reagent/atom nil)]
(fn [{:keys [label state options] :as args}]
(let [state* (reagent/cursor state [(:key args)])
selected (value-for-key @state* options)]
[rn/view {:style container}
(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}
[label-view state label]
[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 "↓"]]]]]))))
[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}]]]))))
(defn customizer
[state descriptors]
[rn/view
{:style {:flex 1}
:padding-horizontal 16}
{:style {:flex-shrink 1
:padding-horizontal 20}}
(doall
(for [desc descriptors
:let [descriptor (merge desc {:state state})]]
@@ -237,19 +199,6 @@
{: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
@@ -262,8 +211,7 @@
: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
@@ -271,9 +219,7 @@
: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
@@ -281,3 +227,33 @@
: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)]]])
@@ -0,0 +1,179 @@
(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,267 +1,173 @@
(ns status-im2.contexts.quo-preview.tags.context-tags
(:require [quo2.core :as quo]
(:require [quo2.components.tags.context-tag.view :as quo2]
[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 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 coinbase-community-image (resources/get-mock-image :coinbase))
(def main-descriptor
[{:label "Type"
:key :type
:type :select
:options [{:key :default
:value "Default"}
{:key :multiuser
:value "Multiuser"}
{:key :group
:value "Group"}
{:key :channel
:value "Channel"}
{:key :community
: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"}
: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"}]}
{:label "Blur?"
:value "Audio"}
{:key :community
:value "Community"}]}
{:label "Blur"
:key :blur?
:type :boolean}])
(def context-tag-descriptor
[{:label "Show avatar"
:key :show-avatar?
:type :boolean}
{: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
{:label "Label"
:key :label
: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 "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}])
{:label "Avatar placeholder"
:key :no-avatar-placeholder?
:type :boolean}])
(defn cool-preview
[]
(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"})]
(let [state (reagent/atom {:label "Name"
:channel-name "Channel"
:type :group-avatar
:duration "00:32"
:show-avatar? true
:no-avatar-placeholder? false})]
(fn []
[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]]]]])))
(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)}])]]]]))))
(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}
@@ -1,241 +0,0 @@
(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.shell.activity-center.notification-types :as types]
[status-im2.contexts.chat.events :as chat.events]
[status-im2.contexts.shell.activity-center.notification-types :as types]
[taoensso.timbre :as log]
[utils.collection :as collection]
[utils.i18n :as i18n]
@@ -502,33 +502,35 @@
{: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 type accepted dismissed message name] :as x}]
(reduce (fn [cofx {:keys [author chat-id type accepted dismissed message name] :as x}]
(let [user-avatar {:full-name name
:status-indicator? true
:online? nil
:size :small
:ring? false}]
:ring? true}]
(cond
(and (not= author my-public-key)
(= type types/contact-request)
(not accepted)
(not dismissed))
(toasts/upsert cofx
{: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])})
{: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])})
(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
:icon-color colors/success-50-opa-40
:title (i18n/label :t/contact-request-accepted-toast
{:name (or name (:alias message))})})
{: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))})})
:else
cofx)))
{:db db}
@@ -69,11 +69,8 @@
:context [[common/user-avatar-tag author]
(i18n/label :t/wants-to-join)
[quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]
common/tag-params
community-image community-name]]
:items (case membership-status
constants/activity-center-membership-status-accepted
[{:type :status
@@ -8,14 +8,24 @@
[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/context-tag
{:blur? true
:size 24
:full-name primary-name
:profile-picture (multiaccounts/displayed-photo contact)}]))
[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)]))
(defn- render-swipe-action
[{:keys [active-swipeable
@@ -34,9 +34,5 @@
:unread? (not read)
:context [[quo/text {:style common-style/user-avatar-tag-text}
(i18n/label :t/community-kicked-body)]
[quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]}]]))
[quo/context-tag common/tag-params community-image
community-name]]}]]))
@@ -22,12 +22,8 @@
[community membership-status]
(let [community-name (:name community)
community-image (get-in community [:images :thumbnail :uri])
community-context-tag [quo/context-tag
{:type :community
:size 24
:blur? true
:community-logo community-image
:community-name community-name}]]
community-context-tag [quo/context-tag common/tag-params community-image
community-name]]
(cond
(= membership-status constants/activity-center-membership-status-idle)
{:header-text (i18n/label :t/community-request-not-accepted)
@@ -66,11 +66,9 @@
:unread? (not read)
:context [[common/user-avatar-tag author]
(i18n/label :t/added-you-to)
[quo/context-tag
{:type :group
:blur? true
:size 24
:group-name chat-name}]]
[quo/group-avatar-tag chat-name
{:size 20
:customization-color :purple}]]
:items (when-not (or accepted dismissed)
[{:type :button
:subtype :positive
@@ -59,19 +59,9 @@
: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
{: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}])]
[quo/context-tag common/tag-params community-image community-name
chat-name]
[quo/group-avatar-tag chat-name common/tag-params])]
:message {:body (message-body message)}}]]]))
@@ -74,18 +74,9 @@
:context [[common/user-avatar-tag author]
[quo/text {:style style/lowercase-text} (i18n/label :t/on)]
(if community-chat?
[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}])]
[quo/context-tag common/tag-params community-image community-name
chat-name]
[quo/group-avatar-tag chat-name common/tag-params])]
: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.components.switcher-cards.style :as style]
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
[status-im2.contexts.shell.jump-to.components.switcher-cards.style :as style]
[status-im2.contexts.chat.messages.resolver.message-resolver :as resolver]))
(defn- channel-card
[{:keys [emoji channel-name customization-color]}]
@@ -82,14 +82,13 @@
:style style/gif}]
constants/content-type-audio
[quo/context-tag {:type :audio :duration data}]
[quo/audio-tag data {:override-theme :dark}]
constants/content-type-community
[quo/context-tag
{:type :community
:size 24
:community-logo (:avatar data)
:community-name (:community-name data)}]
[quo/community-tag
(:avatar data)
(:community-name data)
{:override-theme :dark}]
(constants/content-type-link) ;; Components not available
;; Code snippet content type is not supported yet
@@ -1,5 +1,6 @@
(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]
@@ -14,8 +15,7 @@
[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
{:blur? true
:size 24
:profile-picture (resources/get-mock-image (:source value))
:full-name (i18n/label (:label value))}]))
{:override-theme :dark
:text-style {:color colors/white}}
(resources/get-mock-image (:source value))
(i18n/label (:label value))]))
(defn- render-item
[i list-item]
+15 -12
View File
@@ -1,20 +1,21 @@
(ns status-im2.events
(:require [status-im2.common.json-rpc.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
[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-im.bottom-sheet.events]
[status-im2.db :as db]
[utils.re-frame :as rf]
status-im2.contexts.profile.events
status-im2.contexts.shell.share.events
status-im2.contexts.syncing.events
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]))
[status-im2.db :as db]
[utils.re-frame :as rf]))
(rf/defn start-app
{:events [:app-started]}
@@ -26,5 +27,7 @@
: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 %])}
[:profile/get-profiles-overview-success %])
:font/get-font-file-for-initials-avatar #(rf/dispatch
[:font/init-font-file-for-initials-avatar %])}
(keycard/init)))
+3 -4
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,10 +298,9 @@
:chats/photo-path
:<- [:contacts/contacts]
:<- [:profile/multiaccount]
:<- [:mediaserver/port]
(fn [[contacts {:keys [public-key] :as multiaccount}] [_ id]]
(multiaccounts/displayed-photo (or (when (= id public-key) multiaccount)
(get contacts id)))))
(let [contact (or (when (= id public-key) multiaccount) (get contacts id))]
(contact/displayed-photo contact))))
(re-frame/reg-sub
:chats/unread-messages-number
+45 -29
View File
@@ -1,16 +1,16 @@
(ns status-im2.subs.contact
(:require [clojure.string :as string]
[utils.i18n :as i18n]
[quo2.theme :as theme]
[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]
[utils.image-server :as image-server]
[utils.collection]
[status-im2.constants :as constants]
[quo2.theme :as theme]))
[utils.collection]
[utils.i18n :as i18n]
[utils.image-server :as image-server]))
(re-frame/reg-sub
::query-current-chat-contacts
@@ -32,28 +32,42 @@
(get multiaccount :profile-pictures-visibility)))
(defn- replace-contact-image-uri
[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)))
[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)))
(defn- reduce-contacts-image-uri
[contacts port]
[contacts port font-file]
(reduce-kv (fn [acc public-key contact]
(let [contact (replace-contact-image-uri contact port public-key)]
(let [contact (replace-contact-image-uri contact port public-key font-file)]
(assoc acc public-key contact)))
{}
contacts))
@@ -64,9 +78,10 @@
:<- [::profile-pictures-visibility]
:<- [:multiaccount/public-key]
:<- [:mediaserver/port]
(fn [[contacts profile-pictures-visibility public-key port]]
:<- [:initials-avatar-font-file]
(fn [[contacts profile-pictures-visibility public-key port font-file]]
(let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)]
(reduce-contacts-image-uri contacts port))))
(reduce-contacts-image-uri contacts port font-file))))
(re-frame/reg-sub
:contacts/active
@@ -175,10 +190,10 @@
contacts)))))
(defn- enrich-contact
[_ contact-identity ens-name port]
[_ contact-identity ens-name port font-file]
(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)))
(replace-contact-image-uri contact port contact-identity font-file)))
(re-frame/reg-sub
:contacts/current-contact
@@ -186,11 +201,12 @@
:<- [:contacts/current-contact-identity]
:<- [:contacts/current-contact-ens-name]
:<- [:mediaserver/port]
(fn [[contacts contact-identity ens-name port]]
:<- [:initials-avatar-font-file]
(fn [[contacts contact-identity ens-name port font-file]]
(let [contact (get contacts contact-identity)]
(cond-> contact
(nil? contact)
(enrich-contact contact-identity ens-name port)))))
(enrich-contact contact-identity ens-name port font-file)))))
(re-frame/reg-sub
:contacts/contact-by-identity
+8 -6
View File
@@ -1,8 +1,8 @@
(ns status-im2.subs.contact-test
(:require [cljs.test :refer [is testing]]
[re-frame.db :as rf-db]
[test-helpers.unit :as h]
status-im2.subs.contact
[test-helpers.unit :as h]
[utils.re-frame :as rf]))
(def contacts-sample-data
@@ -74,14 +74,13 @@
:has-added-us? true
:contact-request-state 1}}})
(def expected-sorted-contacts
(def expected-sorted-contacts-without-images
[{:title "F"
:data [{:active? true
:last-updated 1672582629695
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "fslim.shady"
@@ -105,7 +104,6 @@
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "islim.shady"
@@ -129,7 +127,6 @@
:mutual? true
:blocked? false
:contactRequestClock 0
:images {}
:added? true
:name "slim.shady"
:primary-name "rslim.shady"
@@ -148,6 +145,10 @@
: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"
@@ -170,4 +171,5 @@
(dissoc contact :identicon))
%)))
(rf/sub [sub-name]))]
(is (= expected-sorted-contacts contact-list-without-identicons)))))
(is (= expected-sorted-contacts-without-images
(mapv remove-contact-images contact-list-without-identicons))))))
+61 -32
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]
[status-im2.constants :as constants]))
[utils.security.core :as security]))
(re-frame/reg-sub
:profile/customization-color
@@ -16,21 +16,44 @@
(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]
(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})))))
:<- [: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}))}))))
(re-frame/reg-sub
:multiaccount/public-key
@@ -224,30 +247,36 @@
(pos? (count (get multiaccount :images)))))
(defn- replace-multiaccount-image-uri
[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)))
[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)))
(re-frame/reg-sub
:profile/multiaccount
:<- [:profile/profile]
:<- [:mediaserver/port]
(fn [[multiaccount port]]
(replace-multiaccount-image-uri multiaccount port)))
:<- [:initials-avatar-font-file]
(fn [[multiaccount port font-file] [_ avatar-opts]]
(replace-multiaccount-image-uri multiaccount port font-file avatar-opts)))
(re-frame/reg-sub
:profile/login-profile
+1
View File
@@ -75,6 +75,7 @@
(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
+19 -15
View File
@@ -1,12 +1,12 @@
(ns status-im2.subs.shell
(:require [utils.i18n :as i18n]
[re-frame.core :as re-frame]
[utils.datetime :as datetime]
(:require [re-frame.core :as re-frame]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.common.resources :as resources]
[status-im2.config :as config]
[status-im2.constants :as constants]
[status-im2.common.resources :as resources]
[status-im.multiaccounts.core :as multiaccounts]
[status-im2.contexts.shell.jump-to.constants :as shell.constants]))
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
[utils.datetime :as datetime]
[utils.i18n :as i18n]))
;; Helper Functions
(defn community-avatar
@@ -79,13 +79,11 @@
:counter-label (:unviewed-mentions-count chat)})))
(defn one-to-one-chat-card
[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"))}
[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}
:customization-color (or (:customization-color contact) :primary)
:content (get-card-content
{:chat chat
@@ -151,10 +149,16 @@
(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 chat communities] [_ id]]
(one-to-one-chat-card contact names chat id communities)))
(fn [[contact names profile-picture chat communities] [_ id]]
(one-to-one-chat-card contact
names
profile-picture
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
+187 -4
View File
@@ -1,13 +1,43 @@
(ns utils.image-server
(:require [utils.datetime :as datetime]))
(: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]))
(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
@@ -26,7 +56,22 @@
4))
(defn get-account-image-uri
[{:keys [port public-key image-name key-uid theme ring?]}]
"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?]}]
(str image-server-uri-prefix
port
account-images-action
@@ -36,15 +81,130 @@
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
[port public-key image-name clock theme]
[{:keys [port public-key image-name clock theme indicator-size indicator-border
indicator-color size ring?]}]
(str image-server-uri-prefix
port
contact-images-action
@@ -52,11 +212,34 @@
public-key
"&imageName="
image-name
"&size="
(Math/round (* size status-im.utils.pixel-ratio/ratio))
"&theme="
(current-theme-index theme)
"&clock="
clock
"&addRing=1"))
"&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?)})))
(defn get-account-qr-image-uri
[{:keys [key-uid public-key port qr-size]}]
+38 -9
View File
@@ -1,17 +1,46 @@
(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
sut/timestamp (constantly "timestamp")]
[sut/current-theme-index identity
status-im.utils.pixel-ratio/ratio 2
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 "theme"
:ring? true})
"https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&theme=theme&clock=timestamp&addRing=1"))))
(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"))))
+3 -3
View File
@@ -3,7 +3,7 @@
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
"owner": "status-im",
"repo": "status-go",
"version": "v0.163.8",
"commit-sha1": "d61f983d9555e98cf84a3b1273687914887c2e67",
"src-sha256": "1y0s5ivrkywj9simvv2i31ggfzg38li12if2lvfqn8nx10a5y9ai"
"version": "7603b10fb902244899836a19d906cd573fb26093",
"commit-sha1": "7603b10fb902244899836a19d906cd573fb26093",
"src-sha256": "0asnapan03skhxr1r9cmj3q2rfa36sky1qzczficw34kb2icgj15"
}

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