feat: render all avatars using media server (#16193)
This commit is contained in:
parent
87a150cec1
commit
a6710f902f
|
@ -95,11 +95,11 @@ status-im.hardwallet.simulated-keycard/sign-typed-data
|
||||||
status-im.utils.core/safe-read-message-content
|
status-im.utils.core/safe-read-message-content
|
||||||
status-im.ui.components.react/native-modules
|
status-im.ui.components.react/native-modules
|
||||||
status-im.ui.components.react/progress-bar
|
status-im.ui.components.react/progress-bar
|
||||||
status-im.utils.fs/move-file
|
react-native.fs/move-file
|
||||||
status-im.utils.fs/read-dir
|
react-native.fs/read-dir
|
||||||
status-im.utils.fs/mkdir
|
react-native.fs/mkdir
|
||||||
status-im.utils.fs/unlink
|
react-native.fs/unlink
|
||||||
status-im.utils.fs/file-exists?
|
react-native.fs/file-exists?
|
||||||
quo.animated/code
|
quo.animated/code
|
||||||
quo.animated/eq
|
quo.animated/eq
|
||||||
quo.animated/neq
|
quo.animated/neq
|
||||||
|
|
|
@ -90,7 +90,8 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
|
||||||
:configureNext (fn [])}
|
:configureNext (fn [])}
|
||||||
:requireNativeComponent (fn [] {:propTypes ""})
|
:requireNativeComponent (fn [] {:propTypes ""})
|
||||||
:Appearance {:getColorScheme (fn [])
|
:Appearance {:getColorScheme (fn [])
|
||||||
:addChangeListener (fn [])}}))
|
:addChangeListener (fn [])}
|
||||||
|
:PixelRatio {:get (fn [])}}))
|
||||||
|
|
||||||
(set! js/ReactNative react-native)
|
(set! js/ReactNative react-native)
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,9 @@
|
||||||
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||||
[test-helpers.component :as h]))
|
[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/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/describe "Profile picture"
|
||||||
(h/test "Renders"
|
(h/test "Renders"
|
||||||
(h/render
|
(h/render
|
||||||
|
@ -18,124 +13,5 @@
|
||||||
|
|
||||||
(h/test "Renders even if `:full-name` is passed"
|
(h/test "Renders even if `:full-name` is passed"
|
||||||
(h/render
|
(h/render
|
||||||
[user-avatar/user-avatar
|
[user-avatar/user-avatar {:profile-picture mock-picture}])
|
||||||
{:profile-picture mock-picture
|
(h/is-truthy (h/get-by-label-text :profile-picture)))))
|
||||||
:full-name "New User1"}])
|
|
||||||
(h/is-truthy (h/get-by-label-text :profile-picture))
|
|
||||||
(h/is-null (h/query-by-label-text :initials-avatar)))
|
|
||||||
|
|
||||||
(h/describe "Status indicator"
|
|
||||||
(h/test "Render"
|
|
||||||
(h/render
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:profile-picture mock-picture
|
|
||||||
:status-indicator? true}])
|
|
||||||
(h/is-truthy (h/get-by-label-text :profile-picture))
|
|
||||||
(h/is-truthy (h/get-by-label-text :status-indicator)))
|
|
||||||
|
|
||||||
(h/test "Do not render"
|
|
||||||
(h/render
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:profile-picture mock-picture
|
|
||||||
:status-indicator? false}])
|
|
||||||
(h/is-truthy (h/get-by-label-text :profile-picture))
|
|
||||||
(h/is-null (h/query-by-label-text :status-indicator)))))
|
|
||||||
|
|
||||||
(h/describe "Initials Avatar"
|
|
||||||
(h/describe "Render initials"
|
|
||||||
(letfn [(user-avatar-component [size]
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:full-name "New User"
|
|
||||||
:size size}])]
|
|
||||||
(h/describe "Two letters"
|
|
||||||
(h/test "Size :big"
|
|
||||||
(h/render (user-avatar-component :big))
|
|
||||||
(h/is-truthy (h/get-by-text "NU")))
|
|
||||||
|
|
||||||
(h/test "Size :medium"
|
|
||||||
(h/render (user-avatar-component :medium))
|
|
||||||
(h/is-truthy (h/get-by-text "NU")))
|
|
||||||
|
|
||||||
(h/test "Size :small"
|
|
||||||
(h/render (user-avatar-component :small))
|
|
||||||
(h/is-truthy (h/get-by-text "NU")))
|
|
||||||
|
|
||||||
(h/test "Two letters with excess whitespace"
|
|
||||||
(h/render [user-avatar/user-avatar
|
|
||||||
{:full-name "New User"
|
|
||||||
:size :big}])
|
|
||||||
(h/is-truthy (h/get-by-text "NU")))
|
|
||||||
|
|
||||||
(h/test "Two letters with leading whitespace"
|
|
||||||
(h/render [user-avatar/user-avatar
|
|
||||||
{:full-name " New User"
|
|
||||||
:size :big}])
|
|
||||||
(h/is-truthy (h/get-by-text "NU"))))
|
|
||||||
|
|
||||||
(h/describe "One letter"
|
|
||||||
(h/test "Size :xs"
|
|
||||||
(h/render (user-avatar-component :xs))
|
|
||||||
(h/is-truthy (h/get-by-text "N")))
|
|
||||||
|
|
||||||
(h/test "Size :xxs"
|
|
||||||
(h/render (user-avatar-component :xxs))
|
|
||||||
(h/is-truthy (h/get-by-text "N")))
|
|
||||||
|
|
||||||
(h/test "Size :xxxs"
|
|
||||||
(h/render (user-avatar-component :xxxs))
|
|
||||||
(h/is-truthy (h/get-by-text "N"))))))
|
|
||||||
|
|
||||||
(h/describe "Render ring"
|
|
||||||
(letfn [(user-avatar-component [size]
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:full-name "New User"
|
|
||||||
:ring-background mock-picture
|
|
||||||
:size size}])]
|
|
||||||
(h/describe "Passed and drawn"
|
|
||||||
(h/test "Size :big"
|
|
||||||
(h/render (user-avatar-component :big))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-truthy (h/get-by-label-text :ring-background)))
|
|
||||||
|
|
||||||
(h/test "Size :medium"
|
|
||||||
(h/render (user-avatar-component :medium))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-truthy (h/get-by-label-text :ring-background)))
|
|
||||||
|
|
||||||
(h/test "Size :small"
|
|
||||||
(h/render (user-avatar-component :small))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-truthy (h/get-by-label-text :ring-background))))
|
|
||||||
|
|
||||||
(h/describe "Passed and not drawn (because of invalid size for ring)"
|
|
||||||
(h/test "Size :xs"
|
|
||||||
(h/render (user-avatar-component :xs))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-null (h/query-by-label-text :ring-background)))
|
|
||||||
|
|
||||||
(h/test "Size :xxs"
|
|
||||||
(h/render (user-avatar-component :xxs))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-null (h/query-by-label-text :ring-background)))
|
|
||||||
|
|
||||||
(h/test "Size :xxxs"
|
|
||||||
(h/render (user-avatar-component :xxxs))
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-null (h/query-by-label-text :ring-background))))))
|
|
||||||
|
|
||||||
(h/describe "Status indicator"
|
|
||||||
(h/test "Render"
|
|
||||||
(h/render
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:full-name "Test User"
|
|
||||||
:status-indicator? true}])
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-truthy (h/get-by-label-text :status-indicator)))
|
|
||||||
|
|
||||||
(h/test "Do not render"
|
|
||||||
(h/render
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
{:full-name "Test User"
|
|
||||||
:status-indicator? false}])
|
|
||||||
(h/is-truthy (h/get-by-label-text :initials-avatar))
|
|
||||||
(h/is-null (h/query-by-label-text :status-indicator))))))
|
|
||||||
|
|
|
@ -2,92 +2,61 @@
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def sizes
|
(def sizes
|
||||||
{:big {:outer 80
|
{:big {:dimensions 80
|
||||||
:inner 72
|
|
||||||
:status-indicator 20
|
:status-indicator 20
|
||||||
:status-indicator-border 4
|
:status-indicator-border 4
|
||||||
:font-size :heading-1}
|
:font-size :heading-1}
|
||||||
:medium {:outer 48
|
:medium {:dimensions 48
|
||||||
:inner 44
|
|
||||||
:status-indicator 12
|
:status-indicator 12
|
||||||
:status-indicator-border 2
|
:status-indicator-border 2
|
||||||
:font-size :heading-2}
|
:font-size :heading-2}
|
||||||
:small {:outer 32
|
:small {:dimensions 32
|
||||||
:inner 28
|
|
||||||
:status-indicator 12
|
:status-indicator 12
|
||||||
:status-indicator-border 2
|
:status-indicator-border 2
|
||||||
:font-size :paragraph-2}
|
:font-size :paragraph-2}
|
||||||
:xs {:outer 24
|
:xs {:dimensions 24
|
||||||
:inner 24
|
|
||||||
:status-indicator 0
|
:status-indicator 0
|
||||||
:status-indicator-border 0
|
:status-indicator-border 0
|
||||||
:font-size :paragraph-2}
|
:font-size :paragraph-2}
|
||||||
:xxs {:outer 20
|
:xxs {:dimensions 20
|
||||||
:inner 20
|
|
||||||
:status-indicator 0
|
:status-indicator 0
|
||||||
:status-indicator-border 0
|
:status-indicator-border 0
|
||||||
:font-size :label}
|
:font-size :label}
|
||||||
:xxxs {:outer 16
|
:xxxs {:dimensions 16
|
||||||
:inner 16
|
|
||||||
:status-indicator 0
|
:status-indicator 0
|
||||||
:status-indicator-border 0
|
:status-indicator-border 0
|
||||||
:font-size :label}})
|
:font-size :label}})
|
||||||
|
|
||||||
(defn outer
|
|
||||||
[size]
|
|
||||||
(let [dimensions (get-in sizes [size :outer])]
|
|
||||||
{:width dimensions
|
|
||||||
:height dimensions
|
|
||||||
:border-radius dimensions}))
|
|
||||||
|
|
||||||
(defn initials-avatar
|
(defn initials-avatar
|
||||||
[size draw-ring? customization-color theme]
|
[size customization-color theme]
|
||||||
(let [outer-dimensions (get-in sizes [size :outer])
|
(let [dimensions (get-in sizes [size :dimensions])]
|
||||||
inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])]
|
|
||||||
{:position :absolute
|
{:position :absolute
|
||||||
:top (/ (- outer-dimensions inner-dimensions) 2)
|
:top 0
|
||||||
:left (/ (- outer-dimensions inner-dimensions) 2)
|
:left 0
|
||||||
:width inner-dimensions
|
:width dimensions
|
||||||
:height inner-dimensions
|
:height dimensions
|
||||||
:border-radius inner-dimensions
|
:border-radius dimensions
|
||||||
:justify-content :center
|
:justify-content :center
|
||||||
:align-items :center
|
:align-items :center
|
||||||
:background-color (colors/custom-color-by-theme customization-color 50 60 nil nil theme)}))
|
: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
|
(def initials-avatar-text
|
||||||
{:color colors/white-opa-70})
|
{: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
|
(ns quo2.components.avatars.user-avatar.view
|
||||||
(:require [quo2.components.avatars.user-avatar.style :as style]
|
(: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.components.markdown.text :as text]
|
||||||
[quo2.theme :as quo.theme]
|
[quo2.theme]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.fast-image :as fast-image]
|
[react-native.fast-image :as fast-image]
|
||||||
utils.string))
|
utils.string))
|
||||||
|
|
||||||
(defn initials-avatar
|
(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])
|
(let [font-size (get-in style/sizes [size :font-size])
|
||||||
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)]
|
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:accessibility-label :initials-avatar
|
{:accessibility-label :initials-avatar
|
||||||
:style (style/initials-avatar size draw-ring? customization-color theme)}
|
:style (style/initials-avatar size customization-color theme)}
|
||||||
[text/text
|
[text/text
|
||||||
{:style style/initials-avatar-text
|
{:style style/initials-avatar-text
|
||||||
:size font-size
|
:size font-size
|
||||||
:weight :semi-bold}
|
:weight :semi-bold}
|
||||||
(utils.string/get-initials full-name amount-initials)]]))
|
(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
|
`profile-picture-fn` should return an image URI, there's helper fn to generate
|
||||||
"If no `profile-picture` is given, draws the initials based on the `full-name` and
|
it in `utils.image-server`
|
||||||
uses `ring-background` to display the ring behind the initials when given. Otherwise,
|
|
||||||
shows the `profile-picture` which already comes with the ring drawn."
|
params for `profile-picture-fn`
|
||||||
[{:keys [full-name status-indicator? online? size profile-picture ring-background
|
{:length initials' length
|
||||||
customization-color static? muted? theme ring?]
|
:full-name used to generate initials
|
||||||
:or {status-indicator? true
|
: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
|
online? true
|
||||||
ring? true
|
ring? true
|
||||||
size :big
|
customization-color :turquoise}
|
||||||
customization-color :turquoise}}]
|
:as props}]
|
||||||
(let [full-name (or full-name "empty name")
|
(let [full-name (or full-name "Your Name")
|
||||||
draw-ring? (and ring? (when-not muted? (and ring-background (valid-ring-sizes size))))
|
;; image generated with profile-picture-fn is round cropped
|
||||||
outer-styles (style/outer size)
|
;; no need to add border-radius for them
|
||||||
;; Once image is loaded, fast image rerenders view with the help of reagent atom,
|
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
|
;; But dynamic updates don't work when user-avatar is used inside hole-view
|
||||||
;; https://github.com/status-im/status-mobile/issues/15553
|
;; https://github.com/status-im/status-mobile/issues/15553
|
||||||
image-view (if static? rn/image fast-image/fast-image)]
|
image-view (if static? no-flicker-image/image fast-image/fast-image)
|
||||||
[rn/view {:style outer-styles :accessibility-label :user-avatar}
|
font-size (get-in style/sizes [size :font-size])
|
||||||
;; The `profile-picture` already has the ring in it
|
amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)
|
||||||
(when-let [image (or profile-picture ring-background)]
|
sizes (get style/sizes size)
|
||||||
[image-view
|
indicator-color (get style/indicator-color (if online? :online :offline))
|
||||||
{:accessibility-label (if draw-ring? :ring-background :profile-picture)
|
profile-picture-fn (:fn profile-picture)]
|
||||||
:style outer-styles
|
|
||||||
:source image}])
|
|
||||||
(when-not profile-picture
|
|
||||||
[initials-avatar
|
|
||||||
{:full-name full-name
|
|
||||||
:size size
|
|
||||||
:draw-ring? draw-ring?
|
|
||||||
:customization-color customization-color
|
|
||||||
:theme theme}])
|
|
||||||
(when status-indicator?
|
|
||||||
[rn/view
|
|
||||||
{:accessibility-label :status-indicator
|
|
||||||
:style (style/dot size draw-ring? theme)}
|
|
||||||
[rn/view
|
|
||||||
{:accessibility-label :inner-status-indicator-dot
|
|
||||||
:style (style/inner-dot size online?)}]])]))
|
|
||||||
|
|
||||||
(def user-avatar (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]))
|
[test-helpers.component :as h]))
|
||||||
|
|
||||||
(h/describe "Profile Input"
|
(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"
|
(h/test "on press event fires"
|
||||||
(let [event (h/mock-fn)]
|
(let [event (h/mock-fn)]
|
||||||
(h/render [profile-input/profile-input
|
(h/render [profile-input/profile-input
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
(ns quo2.components.inputs.profile-input.view
|
(ns quo2.components.inputs.profile-input.view
|
||||||
(:require
|
(:require
|
||||||
[quo2.components.buttons.button.view :as buttons]
|
|
||||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
[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.profile-input.style :as style]
|
||||||
[quo2.components.inputs.title-input.view :as title-input]
|
[quo2.components.inputs.title-input.view :as title-input]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
@ -13,6 +13,7 @@
|
||||||
on-press
|
on-press
|
||||||
title-input-props
|
title-input-props
|
||||||
image-picker-props]}]
|
image-picker-props]}]
|
||||||
|
(let [full-name (:full-name image-picker-props)]
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style (style/container customization-color)}
|
{:style (style/container customization-color)}
|
||||||
[rn/view
|
[rn/view
|
||||||
|
@ -32,6 +33,7 @@
|
||||||
(assoc image-picker-props
|
(assoc image-picker-props
|
||||||
:static? true
|
:static? true
|
||||||
:status-indicator? false
|
:status-indicator? false
|
||||||
|
:full-name (if (seq full-name) full-name placeholder)
|
||||||
:size :medium)]]
|
:size :medium)]]
|
||||||
[buttons/button
|
[buttons/button
|
||||||
{:accessibility-label :select-profile-picture-button
|
{:accessibility-label :select-profile-picture-button
|
||||||
|
@ -47,4 +49,4 @@
|
||||||
(merge title-input-props
|
(merge title-input-props
|
||||||
{:blur? true
|
{:blur? true
|
||||||
:placeholder placeholder
|
:placeholder placeholder
|
||||||
:customization-color customization-color})]]])
|
:customization-color customization-color})]]]))
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
(ns quo2.components.list-items.user-list
|
(ns quo2.components.list-items.user-list
|
||||||
(:require [react-native.core :as rn]
|
(:require [quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
|
||||||
[quo2.components.markdown.text :as text]
|
|
||||||
[quo2.components.icon :as icons]
|
[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.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
|
(def container-style
|
||||||
{:margin-horizontal 8
|
{:margin-horizontal 8
|
||||||
|
@ -47,7 +47,6 @@
|
||||||
[user-avatar/user-avatar
|
[user-avatar/user-avatar
|
||||||
{:full-name primary-name
|
{:full-name primary-name
|
||||||
:profile-picture photo-path
|
:profile-picture photo-path
|
||||||
:status-indicator? true
|
|
||||||
:online? online?
|
:online? online?
|
||||||
:size :small}]
|
:size :small}]
|
||||||
[rn/view {:style {:margin-left 8}}
|
[rn/view {:style {:margin-left 8}}
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
(ns quo2.components.profile.select-profile.view
|
(ns quo2.components.profile.select-profile.view
|
||||||
(:require
|
(:require
|
||||||
|
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||||
|
[quo2.components.markdown.text :as text]
|
||||||
[quo2.components.profile.select-profile.style :as style]
|
[quo2.components.profile.select-profile.style :as style]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[quo2.components.markdown.text :as text]
|
|
||||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
|
||||||
[reagent.core :as reagent]))
|
[reagent.core :as reagent]))
|
||||||
|
|
||||||
(defn- on-change-handler
|
(defn- on-change-handler
|
||||||
|
@ -24,13 +24,10 @@
|
||||||
(let [internal-selected? (reagent/atom (or default-selected? false))]
|
(let [internal-selected? (reagent/atom (or default-selected? false))]
|
||||||
(fn [{:keys [selected?
|
(fn [{:keys [selected?
|
||||||
profile-picture
|
profile-picture
|
||||||
ring-background
|
|
||||||
name
|
name
|
||||||
customization-color
|
customization-color
|
||||||
on-change]
|
on-change]
|
||||||
:or {customization-color :turquoise}}]
|
: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?))
|
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
|
||||||
(reset! internal-selected? selected?))
|
(reset! internal-selected? selected?))
|
||||||
[rn/touchable-opacity
|
[rn/touchable-opacity
|
||||||
|
@ -43,12 +40,11 @@
|
||||||
{:full-name name
|
{:full-name name
|
||||||
:status-indicator? false
|
:status-indicator? false
|
||||||
:size :medium
|
:size :medium
|
||||||
avatar-image-key picture}]
|
:profile-picture profile-picture}]
|
||||||
[rn/view {:style (style/select-radio @internal-selected?)}
|
[rn/view {:style (style/select-radio @internal-selected?)}
|
||||||
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
|
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
|
||||||
[text/text
|
[text/text
|
||||||
{:size :heading-2
|
{:size :heading-2
|
||||||
:weight :semi-bold
|
:weight :semi-bold
|
||||||
:style style/profile-name}
|
:style style/profile-name}
|
||||||
name]]))))
|
name]])))
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns quo2.components.tags.context-tag.view
|
(ns quo2.components.tags.context-tag.view
|
||||||
(:require [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.style :as user-avatar.style]
|
||||||
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
[quo2.components.avatars.user-avatar.view :as user-avatar]
|
||||||
[quo2.components.icon :as icons]
|
[quo2.components.icon :as icons]
|
||||||
[quo2.components.markdown.text :as text]
|
[quo2.components.markdown.text :as text]
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
(trim-public-key public-key)]])
|
(trim-public-key public-key)]])
|
||||||
|
|
||||||
(defn context-tag
|
(defn context-tag
|
||||||
[{:keys [text-style blur? no-avatar-placeholder? text-container-style ellipsize-text?]
|
[{:keys [text-style blur? no-avatar-placeholder? text-container-style ellipsize-text? ring?]
|
||||||
:as props}
|
:as props}
|
||||||
photo
|
photo
|
||||||
name
|
name
|
||||||
|
@ -52,7 +52,7 @@
|
||||||
:ellipsize-mode :tail}
|
:ellipsize-mode :tail}
|
||||||
empty-photo? (nil? photo)
|
empty-photo? (nil? photo)
|
||||||
avatar-size :xxs
|
avatar-size :xxs
|
||||||
avatar-outer-size (get-in user-avatar-style/sizes [avatar-size :outer])]
|
avatar-outer-size (get-in user-avatar.style/sizes [avatar-size :outer])]
|
||||||
[base-tag (update-in props [:style :padding-left] #(or % 3))
|
[base-tag (update-in props [:style :padding-left] #(or % 3))
|
||||||
(if (and empty-photo? no-avatar-placeholder?)
|
(if (and empty-photo? no-avatar-placeholder?)
|
||||||
[rn/view {:style {:width avatar-outer-size}}]
|
[rn/view {:style {:width avatar-outer-size}}]
|
||||||
|
@ -60,6 +60,7 @@
|
||||||
{:full-name name
|
{:full-name name
|
||||||
:profile-picture photo
|
:profile-picture photo
|
||||||
:size avatar-size
|
:size avatar-size
|
||||||
|
:ring? ring?
|
||||||
:status-indicator? false}])
|
:status-indicator? false}])
|
||||||
[rn/view {:style (or text-container-style style/context-tag-text-container)}
|
[rn/view {:style (or text-container-style style/context-tag-text-container)}
|
||||||
(if ellipsize-text?
|
(if ellipsize-text?
|
||||||
|
|
|
@ -42,3 +42,11 @@
|
||||||
(defn cache-dir
|
(defn cache-dir
|
||||||
[]
|
[]
|
||||||
(.-CachesDirectoryPath ^js react-native-fs))
|
(.-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))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
(ns status-im.contact.core
|
(ns status-im.contact.core
|
||||||
(:require [utils.re-frame :as rf]
|
(:require [status-im2.navigation.events :as navigation]
|
||||||
[status-im2.navigation.events :as navigation]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(rf/defn open-contact-toggle-list
|
(rf/defn open-contact-toggle-list
|
||||||
{:events [:contact.ui/start-group-chat-pressed]}
|
{:events [:contact.ui/start-group-chat-pressed]}
|
||||||
|
@ -10,3 +10,9 @@
|
||||||
:group/selected-contacts #{}
|
:group/selected-contacts #{}
|
||||||
:new-chat-name "")}
|
:new-chat-name "")}
|
||||||
(navigation/navigate-to :contact-toggle-list nil)))
|
(navigation/navigate-to :contact-toggle-list nil)))
|
||||||
|
|
||||||
|
(defn displayed-photo
|
||||||
|
[{:keys [images]}]
|
||||||
|
(or (:large images)
|
||||||
|
(:thumbnail images)
|
||||||
|
(first images)))
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
(ns status-im.multiaccounts.logout.core
|
(ns status-im.multiaccounts.logout.core
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [native-module.core :as native-module]
|
||||||
[utils.i18n :as i18n]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[native-module.core :as native-module]
|
|
||||||
[status-im.notifications.core :as notifications]
|
[status-im.notifications.core :as notifications]
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im.wallet.core :as wallet]
|
[status-im.wallet.core :as wallet]
|
||||||
[status-im2.common.keychain.events :as keychain]
|
[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
|
(re-frame/reg-fx
|
||||||
::logout
|
::logout
|
||||||
|
@ -15,12 +15,13 @@
|
||||||
(native-module/logout)))
|
(native-module/logout)))
|
||||||
|
|
||||||
(rf/defn initialize-app-db
|
(rf/defn initialize-app-db
|
||||||
[{{:keys [keycard]
|
[{{:keys [keycard initials-avatar-font-file]
|
||||||
:biometric/keys [supported-type]
|
:biometric/keys [supported-type]
|
||||||
:network/keys [type]}
|
:network/keys [type]}
|
||||||
:db}]
|
:db}]
|
||||||
{:db (assoc db/app-db
|
{:db (assoc db/app-db
|
||||||
:network/type type
|
:network/type type
|
||||||
|
:initials-avatar-font-file initials-avatar-font-file
|
||||||
:keycard (dissoc keycard :secrets :pin :application-info)
|
:keycard (dissoc keycard :secrets :pin :application-info)
|
||||||
:biometric/supported-type supported-type)})
|
:biometric/supported-type supported-type)})
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
(ns status-im.multiaccounts.update.core
|
(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]
|
[status-im2.constants :as constants]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
@ -19,8 +20,10 @@
|
||||||
display-name]} (:profile/profile db)
|
display-name]} (:profile/profile db)
|
||||||
account (some #(and (= (:key-uid %) key-uid) %) raw-multiaccounts-from-status-go)]
|
account (some #(and (= (:key-uid %) key-uid) %) raw-multiaccounts-from-status-go)]
|
||||||
(when-let [new-name (and account (or preferred-name display-name name))]
|
(when-let [new-name (and account (or preferred-name display-name name))]
|
||||||
(rf/merge cofx
|
(rf/merge
|
||||||
{:json-rpc/call [{:method "multiaccounts_updateAccount"
|
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)]
|
:params [(assoc account :name new-name)]
|
||||||
:on-success #(log/debug "sent multiaccount update")}]}))))
|
:on-success #(log/debug "sent multiaccount update")}]}))))
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,11 @@
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[quo.react-native :as rn]
|
[quo.react-native :as rn]
|
||||||
|
[quo2.components.avatars.user-avatar.style :as user-avatar.style]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
|
[quo2.theme :as theme]
|
||||||
[re-frame.core :as re-frame.core]
|
[re-frame.core :as re-frame.core]
|
||||||
|
[status-im.ethereum.ens :as ens]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.components.chat-icon.styles :as styles]
|
[status-im.ui.components.chat-icon.styles :as styles]
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
[status-im.ui.components.icons.icons :as icons]
|
||||||
|
@ -47,7 +50,7 @@
|
||||||
[rn/text {:style (:default-chat-icon-text styles)} emoji]]))
|
[rn/text {:style (:default-chat-icon-text styles)} emoji]]))
|
||||||
|
|
||||||
(defn profile-photo-plus-dot-view
|
(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)
|
(let [photo-container (if (nil? photo-container)
|
||||||
styles/container-chat-list
|
styles/container-chat-list
|
||||||
photo-container)
|
photo-container)
|
||||||
|
@ -55,11 +58,28 @@
|
||||||
dot-styles (visibility-status-utils/icon-visibility-status-dot
|
dot-styles (visibility-status-utils/icon-visibility-status-dot
|
||||||
public-key
|
public-key
|
||||||
size)
|
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
|
[rn/view
|
||||||
{:style photo-container
|
{:style photo-container
|
||||||
:accessibility-label :profile-photo}
|
: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?
|
(when-not community?
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style dot-styles
|
{:style dot-styles
|
||||||
|
@ -186,7 +206,21 @@
|
||||||
:default-chat-icon-text (if (string/blank? emoji)
|
:default-chat-icon-text (if (string/blank? emoji)
|
||||||
(styles/default-chat-icon-text size)
|
(styles/default-chat-icon-text size)
|
||||||
(styles/emoji-chat-icon-text size))}
|
(styles/emoji-chat-icon-text size))}
|
||||||
override-styles)]
|
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)
|
[rn/view (:container styles)
|
||||||
(if (and photo-path (seq photo-path))
|
(if (and photo-path (seq photo-path))
|
||||||
[profile-photo-plus-dot-view
|
[profile-photo-plus-dot-view
|
||||||
|
|
|
@ -2,22 +2,24 @@
|
||||||
(:require [quo.core :as quo]
|
(:require [quo.core :as quo]
|
||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||||
[status-im.ui.components.invite.views :as invite]
|
[status-im.ui.components.invite.views :as invite]
|
||||||
[status-im.ui.components.list.views :as list.views]
|
[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]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defn contacts-list-item
|
(defn contacts-list-item
|
||||||
[{:keys [public-key] :as contact}]
|
[{:keys [public-key] :as contact}]
|
||||||
(let [{:keys [primary-name secondary-name]} contact]
|
(let [{:keys [primary-name secondary-name customization-color]} contact]
|
||||||
[quo/list-item
|
[quo/list-item
|
||||||
{:title primary-name
|
{:title primary-name
|
||||||
:subtitle secondary-name
|
:subtitle secondary-name
|
||||||
:icon [chat-icon.screen/profile-photo-plus-dot-view
|
:icon [chat-icon.screen/profile-photo-plus-dot-view
|
||||||
{:public-key public-key
|
{:public-key public-key
|
||||||
|
:full-name primary-name
|
||||||
|
:customization-color (or customization-color :primary)
|
||||||
:photo-path (multiaccounts/displayed-photo contact)}]
|
:photo-path (multiaccounts/displayed-photo contact)}]
|
||||||
:chevron true
|
:chevron true
|
||||||
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
|
:on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}]))
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
[quo.components.list.item :as list-item]
|
[quo.components.list.item :as list-item]
|
||||||
[quo.core :as quo]
|
[quo.core :as quo]
|
||||||
[quo.design-system.colors :as colors]
|
[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]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
|
||||||
[status-im.ui.components.profile-header.view :as profile-header]
|
[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.toolbar :as toolbar]
|
||||||
[status-im.ui.components.topbar :as topbar]
|
[status-im.ui.components.topbar :as topbar]
|
||||||
[status-im.ui.screens.profile.components.sheets :as sheets]
|
[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
|
(defn actions
|
||||||
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
|
[{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?]
|
||||||
|
@ -179,9 +181,11 @@
|
||||||
:as contact}
|
:as contact}
|
||||||
@(re-frame/subscribe
|
@(re-frame/subscribe
|
||||||
[:contacts/current-contact])
|
[:contacts/current-contact])
|
||||||
|
|
||||||
muted? @(re-frame/subscribe [:chats/muted
|
muted? @(re-frame/subscribe [:chats/muted
|
||||||
public-key])
|
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
|
on-share #(re-frame/dispatch
|
||||||
[:show-popover
|
[:show-popover
|
||||||
(merge
|
(merge
|
||||||
|
@ -204,6 +208,9 @@
|
||||||
{:on-press on-share
|
{:on-press on-share
|
||||||
:bottom-separator false
|
:bottom-separator false
|
||||||
:title primary-name
|
:title primary-name
|
||||||
|
:color
|
||||||
|
(user-avatar.style/customization-color customization-color
|
||||||
|
(theme/get-theme))
|
||||||
:photo (multiaccounts/displayed-photo contact)
|
:photo (multiaccounts/displayed-photo contact)
|
||||||
:monospace (not ens-verified)
|
:monospace (not ens-verified)
|
||||||
:subtitle secondary-name
|
:subtitle secondary-name
|
||||||
|
|
|
@ -2,16 +2,16 @@
|
||||||
(:require [quo.core :as quo]
|
(:require [quo.core :as quo]
|
||||||
[quo.design-system.colors :as colors]
|
[quo.design-system.colors :as colors]
|
||||||
[quo.design-system.spacing :as spacing]
|
[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]
|
[re-frame.core :as re-frame]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.ethereum.stateofus :as stateofus]
|
[status-im.ethereum.stateofus :as stateofus]
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.components.common.common :as components.common]
|
[status-im.ui.components.common.common :as components.common]
|
||||||
[status-im.ui.components.copyable-text :as copyable-text]
|
[status-im.ui.components.copyable-text :as copyable-text]
|
||||||
[status-im.ui.components.list-selection :as list-selection]
|
[status-im.ui.components.list-selection :as list-selection]
|
||||||
[status-im.ui.components.profile-header.view :as profile-header]
|
[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.components.react :as react]
|
||||||
[status-im.ui.screens.profile.user.edit-picture :as edit]
|
[status-im.ui.screens.profile.user.edit-picture :as edit]
|
||||||
[status-im.ui.screens.profile.user.styles :as styles]
|
[status-im.ui.screens.profile.user.styles :as styles]
|
||||||
|
@ -19,7 +19,9 @@
|
||||||
[status-im.utils.gfycat.core :as gfy]
|
[status-im.utils.gfycat.core :as gfy]
|
||||||
[status-im.utils.universal-links.utils :as universal-links]
|
[status-im.utils.universal-links.utils :as universal-links]
|
||||||
[status-im.utils.utils :as utils]
|
[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]))
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(views/defview share-chat-key
|
(views/defview share-chat-key
|
||||||
|
@ -190,9 +192,12 @@
|
||||||
(let [{:keys [public-key
|
(let [{:keys [public-key
|
||||||
compressed-key
|
compressed-key
|
||||||
ens-verified
|
ens-verified
|
||||||
preferred-name]
|
preferred-name
|
||||||
|
key-uid]
|
||||||
:as account}
|
:as account}
|
||||||
@(re-frame/subscribe [:profile/multiaccount])
|
@(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
|
on-share #(re-frame/dispatch [:show-popover
|
||||||
{:view :share-chat-key
|
{:view :share-chat-key
|
||||||
:address (or compressed-key
|
:address (or compressed-key
|
||||||
|
@ -213,6 +218,8 @@
|
||||||
:on-edit #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
:on-edit #(re-frame/dispatch [:bottom-sheet/show-sheet-old
|
||||||
{:content (edit/bottom-sheet
|
{:content (edit/bottom-sheet
|
||||||
has-picture)}])
|
has-picture)}])
|
||||||
|
:color (user-avatar.style/customization-color customization-color
|
||||||
|
(theme/get-theme))
|
||||||
:title (multiaccounts/displayed-name account)
|
:title (multiaccounts/displayed-name account)
|
||||||
:photo (multiaccounts/displayed-photo account)
|
:photo (multiaccounts/displayed-photo account)
|
||||||
:monospace (not ens-verified)
|
:monospace (not ens-verified)
|
||||||
|
|
|
@ -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
|
(ns status-im2.common.confirmation-drawer.view
|
||||||
(:require [utils.i18n :as i18n]
|
(:require [quo2.core :as quo]
|
||||||
[quo2.core :as quo]
|
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im2.common.confirmation-drawer.style :as style]
|
[status-im2.common.confirmation-drawer.style :as style]
|
||||||
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn avatar
|
(defn avatar
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
{:full-name display-name
|
{:full-name display-name
|
||||||
:profile-picture photo-path
|
:profile-picture photo-path
|
||||||
:size :xxs
|
:size :xxs
|
||||||
:status-indicator false}]))
|
:status-indicator? false}]))
|
||||||
|
|
||||||
(defn extra-action-view
|
(defn extra-action-view
|
||||||
[extra-action extra-text extra-action-selected?]
|
[extra-action extra-text extra-action-selected?]
|
||||||
|
@ -41,12 +41,7 @@
|
||||||
(= contact-name-by-identity
|
(= contact-name-by-identity
|
||||||
nil) name
|
nil) name
|
||||||
:else contact-name-by-identity)
|
:else contact-name-by-identity)
|
||||||
contact (when-not group-chat
|
photo-path (or profile-picture (rf/sub [:chats/photo-path id]))]
|
||||||
(rf/sub [:contacts/contact-by-address
|
|
||||||
id]))
|
|
||||||
photo-path (or profile-picture
|
|
||||||
(when-not (empty? (:images contact))
|
|
||||||
(rf/sub [:chats/photo-path id])))]
|
|
||||||
[rn/view
|
[rn/view
|
||||||
{:style {:margin-horizontal 20}
|
{:style {:margin-horizontal 20}
|
||||||
:accessibility-label accessibility-label}
|
:accessibility-label accessibility-label}
|
||||||
|
|
|
@ -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)}))
|
|
@ -60,10 +60,7 @@
|
||||||
{:accessibility-label :open-profile
|
{:accessibility-label :open-profile
|
||||||
:style style/left-section}
|
:style style/left-section}
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
||||||
(merge {:status-indicator? true
|
(merge {:size :small :online? online?} avatar)]]]))
|
||||||
:size :small
|
|
||||||
:online? online?}
|
|
||||||
avatar)]]]))
|
|
||||||
|
|
||||||
(defn connectivity-sheet
|
(defn connectivity-sheet
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -11,10 +11,17 @@
|
||||||
|
|
||||||
(defn toast
|
(defn toast
|
||||||
[toast-id]
|
[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)
|
(if (= type :notification)
|
||||||
[quo/notification toast-opts]
|
[quo/notification toast-opts-with-profile-picture]
|
||||||
[quo/toast toast-opts])))
|
[quo/toast toast-opts-with-profile-picture])))
|
||||||
|
|
||||||
(defn f-container
|
(defn f-container
|
||||||
[toast-id]
|
[toast-id]
|
||||||
|
|
|
@ -345,3 +345,11 @@
|
||||||
|
|
||||||
(def ^:const onboarding-modal-animation-duration 300)
|
(def ^:const onboarding-modal-animation-duration 300)
|
||||||
(def ^:const onboarding-modal-animation-delay 400)
|
(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
|
(:require
|
||||||
[clojure.string :as string]
|
[clojure.string :as string]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
[react-native.core :as rn]
|
|
||||||
[react-native.clipboard :as clipboard]
|
[react-native.clipboard :as clipboard]
|
||||||
|
[react-native.core :as rn]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im.qr-scanner.core :as qr-scanner]
|
[status-im.qr-scanner.core :as qr-scanner]
|
||||||
[status-im2.contexts.add-new-contact.style :as style]
|
[status-im2.contexts.add-new-contact.style :as style]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
|
@ -15,8 +14,8 @@
|
||||||
|
|
||||||
(defn found-contact
|
(defn found-contact
|
||||||
[public-key]
|
[public-key]
|
||||||
(let [{:keys [primary-name compressed-key]
|
(let [{:keys [primary-name compressed-key]} (rf/sub [:contacts/contact-by-identity public-key])
|
||||||
:as contact} (rf/sub [:contacts/contact-by-identity public-key])]
|
photo-path (rf/sub [:chats/photo-path public-key])]
|
||||||
(when primary-name
|
(when primary-name
|
||||||
[rn/view style/found-user
|
[rn/view style/found-user
|
||||||
[quo/text (style/text-description)
|
[quo/text (style/text-description)
|
||||||
|
@ -24,7 +23,7 @@
|
||||||
[rn/view (style/found-user-container)
|
[rn/view (style/found-user-container)
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
||||||
{:full-name primary-name
|
{:full-name primary-name
|
||||||
:profile-picture (multiaccounts/displayed-photo contact)
|
:profile-picture photo-path
|
||||||
:size :small
|
:size :small
|
||||||
:status-indicator? false}]
|
:status-indicator? false}]
|
||||||
[rn/view style/found-user-text
|
[rn/view style/found-user-text
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
(ns status-im2.contexts.chat.composer.reply.view
|
(ns status-im2.contexts.chat.composer.reply.view
|
||||||
(:require [clojure.string :as string]
|
(: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.core :as quo]
|
||||||
[quo2.foundations.colors :as colors]
|
[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]
|
[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]
|
[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
|
(defn get-quoted-text-with-mentions
|
||||||
[parsed-text]
|
[parsed-text]
|
||||||
|
@ -63,8 +63,7 @@
|
||||||
(defn reply-from
|
(defn reply-from
|
||||||
[{:keys [from contact-name current-public-key]}]
|
[{:keys [from contact-name current-public-key]}]
|
||||||
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
|
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
|
||||||
contact (rf/sub [:contacts/contact-by-address from])
|
photo-path (rf/sub [:chats/photo-path from])]
|
||||||
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))]
|
|
||||||
[rn/view {:style style/reply-from}
|
[rn/view {:style style/reply-from}
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
||||||
{:full-name display-name
|
{:full-name display-name
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
(ns status-im2.contexts.chat.home.chat-list-item.view
|
(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]
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[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.datetime :as datetime]
|
||||||
[utils.debounce :as debounce]
|
[utils.debounce :as debounce]
|
||||||
[status-im2.common.home.actions.view :as actions]
|
|
||||||
[status-im2.contexts.chat.home.chat-list-item.style :as style]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im2.constants :as constants]
|
|
||||||
[clojure.string :as string]
|
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[quo2.components.icon :as icons]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def max-subheader-length 50)
|
(def max-subheader-length 50)
|
||||||
|
|
||||||
|
@ -201,14 +201,14 @@
|
||||||
[{:keys [contact chat-id full-name color muted?]}]
|
[{:keys [contact chat-id full-name color muted?]}]
|
||||||
(if contact ; `contact` is passed when it's not a group chat
|
(if contact ; `contact` is passed when it's not a group chat
|
||||||
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])
|
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])
|
||||||
photo-path (rf/sub [:chats/photo-path chat-id])
|
photo-path (rf/sub [:chats/photo-path chat-id])]
|
||||||
image-key (if (seq (:images contact)) :profile-picture :ring-background)]
|
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
||||||
{:full-name full-name
|
(cond-> {:full-name full-name
|
||||||
:size :small
|
:size :small
|
||||||
:online? online?
|
:online? online?
|
||||||
image-key photo-path
|
:profile-picture photo-path}
|
||||||
:muted? muted?}])
|
muted?
|
||||||
|
(assoc :ring? false))])
|
||||||
[quo/group-avatar
|
[quo/group-avatar
|
||||||
{:customization-color color
|
{:customization-color color
|
||||||
:size :small}]))
|
:size :small}]))
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
(ns status-im2.contexts.chat.messages.avatar.view
|
(ns status-im2.contexts.chat.messages.avatar.view
|
||||||
(:require [utils.re-frame :as rf]
|
(:require [quo2.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[quo2.core :as quo]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn avatar
|
(defn avatar
|
||||||
[public-key size]
|
[public-key size]
|
||||||
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
|
(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 (rf/sub [:chats/photo-path public-key])
|
||||||
photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path public-key]))
|
|
||||||
online? (rf/sub [:visibility-status-updates/online? public-key])]
|
online? (rf/sub [:visibility-status-updates/online? public-key])]
|
||||||
[rn/view {:style {:padding-top 2}}
|
[rn/view {:style {:padding-top 2}}
|
||||||
[rn/touchable-opacity
|
[rn/touchable-opacity
|
||||||
|
@ -16,6 +15,5 @@
|
||||||
[quo/user-avatar
|
[quo/user-avatar
|
||||||
{:full-name display-name
|
{:full-name display-name
|
||||||
:profile-picture photo-path
|
:profile-picture photo-path
|
||||||
:status-indicator? true
|
|
||||||
:online? online?
|
:online? online?
|
||||||
:size size}]]]))
|
:size size}]]]))
|
||||||
|
|
|
@ -28,9 +28,7 @@
|
||||||
on-long-press-fn]
|
on-long-press-fn]
|
||||||
(let [;; deleted message with nil deleted-by is deleted by (:from message)
|
(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)]))
|
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 (rf/sub [:chats/photo-path (or deleted-by from)])]
|
||||||
photo-path (when-not (empty? (:images contact))
|
|
||||||
(rf/sub [:chats/photo-path (or deleted-by from)]))]
|
|
||||||
[quo/system-message
|
[quo/system-message
|
||||||
{:type :deleted
|
{:type :deleted
|
||||||
:timestamp timestamp-str
|
:timestamp timestamp-str
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
(ns status-im2.contexts.chat.messages.list.view
|
(ns status-im2.contexts.chat.messages.list.view
|
||||||
(:require [oops.core :as oops]
|
(:require [oops.core :as oops]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.background-timer :as background-timer]
|
[react-native.background-timer :as background-timer]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.hooks :as hooks]
|
[react-native.hooks :as hooks]
|
||||||
[react-native.platform :as platform]
|
[react-native.platform :as platform]
|
||||||
|
[react-native.reanimated :as reanimated]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[reagent.core :as reagent]
|
[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.group :as chat.group]
|
||||||
[status-im.ui.screens.chat.message.gap :as message.gap]
|
[status-im.ui.screens.chat.message.gap :as message.gap]
|
||||||
[status-im2.constants :as constants]
|
[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.content.view :as message]
|
||||||
[status-im2.contexts.chat.messages.list.state :as state]
|
[status-im2.contexts.chat.messages.list.state :as state]
|
||||||
[status-im2.contexts.chat.messages.list.style :as style]
|
[status-im2.contexts.chat.messages.list.style :as style]
|
||||||
[status-im2.contexts.chat.messages.navigation.style :as navigation.style]
|
[status-im2.contexts.chat.messages.navigation.style :as navigation.style]
|
||||||
[status-im2.contexts.chat.composer.constants :as composer.constants]
|
[utils.i18n :as i18n]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]))
|
||||||
[utils.i18n :as i18n]))
|
|
||||||
|
|
||||||
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
|
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
|
||||||
(defonce ^:const loading-indicator-extra-spacing 250)
|
(defonce ^:const loading-indicator-extra-spacing 250)
|
||||||
|
@ -203,8 +203,7 @@
|
||||||
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
||||||
contact (when-not group-chat
|
contact (when-not group-chat
|
||||||
(rf/sub [:contacts/contact-by-address chat-id]))
|
(rf/sub [:contacts/contact-by-address chat-id]))
|
||||||
photo-path (when-not (empty? (:images contact))
|
photo-path (rf/sub [:chats/photo-path chat-id])
|
||||||
(rf/sub [:chats/photo-path chat-id]))
|
|
||||||
border-animation (reanimated/interpolate scroll-y
|
border-animation (reanimated/interpolate scroll-y
|
||||||
[30 125]
|
[30 125]
|
||||||
[14 0]
|
[14 0]
|
||||||
|
|
|
@ -5,15 +5,15 @@
|
||||||
[re-frame.db]
|
[re-frame.db]
|
||||||
[react-native.blur :as blur]
|
[react-native.blur :as blur]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im2.config :as config]
|
|
||||||
[react-native.reanimated :as reanimated]
|
|
||||||
[react-native.platform :as platform]
|
[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.navigation.style :as style]
|
||||||
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
|
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
|
||||||
[status-im2.constants :as constants]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
[status-im2.common.home.actions.view :as actions]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(defn f-view
|
(defn f-view
|
||||||
[{:keys [scroll-y]}]
|
[{:keys [scroll-y]}]
|
||||||
|
@ -27,10 +27,7 @@
|
||||||
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
|
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
|
||||||
(str emoji " " chat-name))
|
(str emoji " " chat-name))
|
||||||
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
online? (rf/sub [:visibility-status-updates/online? chat-id])
|
||||||
contact (when-not group-chat
|
photo-path (rf/sub [:chats/photo-path chat-id])
|
||||||
(rf/sub [:contacts/contact-by-address chat-id]))
|
|
||||||
photo-path (when-not (empty? (:images contact))
|
|
||||||
(rf/sub [:chats/photo-path chat-id]))
|
|
||||||
opacity-animation (reanimated/interpolate scroll-y
|
opacity-animation (reanimated/interpolate scroll-y
|
||||||
[style/navigation-bar-height
|
[style/navigation-bar-height
|
||||||
(+ style/navigation-bar-height 30)]
|
(+ style/navigation-bar-height 30)]
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(ns status-im2.contexts.contacts.drawers.nickname-drawer.view
|
(ns status-im2.contexts.contacts.drawers.nickname-drawer.view
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo2.components.icon :as icons]
|
[quo2.components.icon :as icons]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
|
@ -28,8 +28,7 @@
|
||||||
[{:keys [contact]}]
|
[{:keys [contact]}]
|
||||||
(let [{:keys [primary-name nickname public-key]} contact
|
(let [{:keys [primary-name nickname public-key]} contact
|
||||||
entered-nickname (reagent/atom (or nickname ""))
|
entered-nickname (reagent/atom (or nickname ""))
|
||||||
photo-path (when-not (empty? (:images contact))
|
photo-path (rf/sub [:chats/photo-path public-key])
|
||||||
(rf/sub [:chats/photo-path public-key]))
|
|
||||||
insets (safe-area/get-insets)]
|
insets (safe-area/get-insets)]
|
||||||
(fn [{:keys [title description accessibility-label
|
(fn [{:keys [title description accessibility-label
|
||||||
close-button-text]}]
|
close-button-text]}]
|
||||||
|
@ -44,7 +43,7 @@
|
||||||
{:full-name primary-name
|
{:full-name primary-name
|
||||||
:profile-picture photo-path
|
:profile-picture photo-path
|
||||||
:size :xxs
|
:size :xxs
|
||||||
:status-indicator false}]
|
:status-indicator? false}]
|
||||||
[quo/text
|
[quo/text
|
||||||
{:weight :medium
|
{:weight :medium
|
||||||
:size :paragraph-2
|
:size :paragraph-2
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
(ns status-im2.contexts.onboarding.create-profile.view
|
(ns status-im2.contexts.onboarding.create-profile.view
|
||||||
(:require [quo2.core :as quo]
|
(:require [clojure.string :as string]
|
||||||
[clojure.string :as string]
|
[oops.core :as oops]
|
||||||
|
[quo2.core :as quo]
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.colors :as colors]
|
||||||
[status-im2.contexts.onboarding.create-profile.style :as style]
|
[react-native.blur :as blur]
|
||||||
[utils.i18n :as i18n]
|
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
|
[react-native.platform :as platform]
|
||||||
[react-native.safe-area :as safe-area]
|
[react-native.safe-area :as safe-area]
|
||||||
[react-native.hooks :as hooks]
|
[react-native.hooks :as hooks]
|
||||||
[reagent.core :as reagent]
|
[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]
|
[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
|
;; NOTE - validation should match with Desktop
|
||||||
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
|
;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468
|
||||||
|
@ -162,9 +162,12 @@
|
||||||
[:show-bottom-sheet
|
[:show-bottom-sheet
|
||||||
{:content
|
{:content
|
||||||
(fn []
|
(fn []
|
||||||
[method-menu/view on-change-profile-pic])
|
[method-menu/view on-change-profile-pic])}]))
|
||||||
:theme :dark}]))
|
:image-picker-props {:profile-picture (or
|
||||||
:image-picker-props {:profile-picture (when @profile-pic {:uri @profile-pic})
|
@profile-pic
|
||||||
|
(rf/sub
|
||||||
|
[:profile/onboarding-placeholder-avatar
|
||||||
|
@profile-pic]))
|
||||||
:full-name (if (seq @full-name)
|
:full-name (if (seq @full-name)
|
||||||
@full-name
|
@full-name
|
||||||
(i18n/label :t/your-name))
|
(i18n/label :t/your-name))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
(ns status-im2.contexts.onboarding.identifiers.profile-card.style
|
(ns status-im2.contexts.onboarding.identifiers.profile-card.style
|
||||||
(:require [quo2.foundations.colors :as colors]
|
(: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
|
(def card-view
|
||||||
{:margin-horizontal 20
|
{:margin-horizontal 20
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
:background-color :transparent
|
:background-color :transparent
|
||||||
:height 48
|
:height 48
|
||||||
:border-color :black
|
:border-color :black
|
||||||
:border-width 2
|
:border-width 3
|
||||||
:border-radius 44}))
|
:border-radius 44}))
|
||||||
|
|
||||||
(def picture-avatar-mask
|
(def picture-avatar-mask
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
(ns status-im2.contexts.onboarding.identifiers.profile-card.view
|
(ns status-im2.contexts.onboarding.identifiers.profile-card.view
|
||||||
(:require [react-native.core :as rn]
|
(:require [quo2.core :as quo]
|
||||||
[react-native.reanimated :as reanimated]
|
|
||||||
[react-native.masked-view :as masked-view]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[quo2.core :as quo]
|
|
||||||
[quo2.foundations.colors :as colors]
|
[quo2.foundations.colors :as colors]
|
||||||
[utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting]
|
[react-native.core :as rn]
|
||||||
[status-im2.contexts.onboarding.identifiers.profile-card.style :as style]))
|
[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
|
(defn- f-profile-card-component
|
||||||
[{:keys [profile-picture name hash emoji-hash
|
[{:keys [profile-picture name hash emoji-hash
|
||||||
|
@ -20,29 +20,24 @@
|
||||||
ring-opacity (worklets.identifiers-highlighting/ring-opacity @progress)
|
ring-opacity (worklets.identifiers-highlighting/ring-opacity @progress)
|
||||||
user-hash-color (worklets.identifiers-highlighting/user-hash-color @progress)
|
user-hash-color (worklets.identifiers-highlighting/user-hash-color @progress)
|
||||||
user-hash-opacity (worklets.identifiers-highlighting/user-hash-opacity @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)
|
||||||
[rn/view
|
avatar [quo/user-avatar
|
||||||
{: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
|
{:full-name name
|
||||||
:profile-picture profile-picture
|
:profile-picture profile-picture
|
||||||
:size :medium
|
:size :medium
|
||||||
:status-indicator? false
|
:status-indicator? false
|
||||||
:customization-color customization-color}]]
|
: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)} avatar]
|
||||||
[masked-view/masked-view
|
[masked-view/masked-view
|
||||||
{:style {:position :absolute}
|
{:style {:position :absolute}
|
||||||
:mask-element (reagent/as-element
|
:mask-element (reagent/as-element
|
||||||
[reanimated/view {:style (style/mask-view ring-opacity)}])}
|
[reanimated/view {:style (style/mask-view ring-opacity)}])}
|
||||||
(when profile-picture
|
(when profile-picture avatar)]]
|
||||||
[rn/image
|
|
||||||
{:accessibility-label :ring-background
|
|
||||||
:style style/picture-avatar-mask
|
|
||||||
:source profile-picture}])]]
|
|
||||||
[reanimated/view
|
[reanimated/view
|
||||||
{:style (style/user-name-container opacity)}
|
{:style (style/user-name-container opacity)}
|
||||||
[quo/text
|
[quo/text
|
||||||
|
|
|
@ -111,7 +111,7 @@
|
||||||
:customization-color (or customization-color :primary)
|
:customization-color (or customization-color :primary)
|
||||||
:keycard-account? keycard-pairing
|
:keycard-account? keycard-pairing
|
||||||
:show-options-button? true
|
:show-options-button? true
|
||||||
:profile-picture (when profile-picture {:uri profile-picture})
|
:profile-picture profile-picture
|
||||||
:card-style (style/profiles-profile-card last-item?)
|
:card-style (style/profiles-profile-card last-item?)
|
||||||
:on-options-press #(show-profile-options
|
:on-options-press #(show-profile-options
|
||||||
key-uid
|
key-uid
|
||||||
|
@ -257,7 +257,7 @@
|
||||||
[quo/profile-card
|
[quo/profile-card
|
||||||
{:name name
|
{:name name
|
||||||
:customization-color (or customization-color :primary)
|
:customization-color (or customization-color :primary)
|
||||||
:profile-picture (when profile-picture {:uri profile-picture})
|
:profile-picture profile-picture
|
||||||
:card-style style/login-profile-card}]
|
:card-style style/login-profile-card}]
|
||||||
[quo/input
|
[quo/input
|
||||||
{:type :password
|
{:type :password
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
(ns status-im2.contexts.profile.rpc
|
(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
|
(defn rpc->profiles-overview
|
||||||
[{:keys [customizationColor keycard-pairing] :as profile}]
|
[{:keys [customizationColor keycard-pairing] :as profile}]
|
||||||
(-> profile
|
(-> profile
|
||||||
(dissoc :customizationColor)
|
(dissoc :customizationColor)
|
||||||
(assoc :customization-color (keyword 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))))
|
(assoc :keycard-pairing (when-not (string/blank? keycard-pairing) keycard-pairing))))
|
||||||
|
|
|
@ -67,12 +67,7 @@
|
||||||
{:padding-vertical 60
|
{:padding-vertical 60
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:justify-content :center}
|
:justify-content :center}
|
||||||
(let [{:keys [profile-picture ring?]} @state
|
[quo2/user-avatar @state]]]])))
|
||||||
ring-bg (resources/get-mock-image :ring)
|
|
||||||
params (cond-> @state
|
|
||||||
(and (not profile-picture) ring?)
|
|
||||||
(assoc :ring-background ring-bg))]
|
|
||||||
[quo2/user-avatar params])]]])))
|
|
||||||
|
|
||||||
(defn preview-user-avatar
|
(defn preview-user-avatar
|
||||||
[]
|
[]
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
(ns status-im2.contexts.quo-preview.notifications.notification
|
(ns status-im2.contexts.quo-preview.notifications.notification
|
||||||
(:require [quo2.core :as quo]
|
(:require [quo2.core :as quo]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[status-im2.common.resources :as resources]
|
|
||||||
[status-im2.contexts.quo-preview.code.snippet :as snippet-preview]
|
[status-im2.contexts.quo-preview.code.snippet :as snippet-preview]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
@ -34,8 +33,7 @@
|
||||||
:status-indicator? true
|
:status-indicator? true
|
||||||
:online? true
|
:online? true
|
||||||
:size :small
|
:size :small
|
||||||
:customization-color :blue
|
:customization-color :blue}]
|
||||||
:ring-background (resources/get-mock-image :ring)}]
|
|
||||||
:title "Alisher Yakupov accepted your contact request"
|
:title "Alisher Yakupov accepted your contact request"
|
||||||
:duration 4000
|
:duration 4000
|
||||||
:title-weight :medium
|
:title-weight :medium
|
||||||
|
@ -50,8 +48,7 @@
|
||||||
:status-indicator? true
|
:status-indicator? true
|
||||||
:online? true
|
:online? true
|
||||||
:size :small
|
:size :small
|
||||||
:customization-color :blue
|
:customization-color :blue}]
|
||||||
:ring-background (resources/get-mock-image :ring)}]
|
|
||||||
:title "Default to semibold title"
|
:title "Default to semibold title"
|
||||||
:text "The quick brown fox jumped over the lazy dog and ate a potatoe."
|
:text "The quick brown fox jumped over the lazy dog and ate a potatoe."
|
||||||
:duration 4000
|
:duration 4000
|
||||||
|
@ -66,8 +63,7 @@
|
||||||
:status-indicator? true
|
:status-indicator? true
|
||||||
:online? true
|
:online? true
|
||||||
:size :small
|
:size :small
|
||||||
:customization-color :blue
|
:customization-color :blue}]
|
||||||
:ring-background (resources/get-mock-image :ring)}]
|
|
||||||
:header [rn/view
|
:header [rn/view
|
||||||
[quo/info-message
|
[quo/info-message
|
||||||
{:type :success
|
{:type :success
|
||||||
|
|
|
@ -4,8 +4,8 @@
|
||||||
[status-im.data-store.chats :as data-store.chats]
|
[status-im.data-store.chats :as data-store.chats]
|
||||||
[status-im2.common.toasts.events :as toasts]
|
[status-im2.common.toasts.events :as toasts]
|
||||||
[status-im2.constants :as constants]
|
[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.chat.events :as chat.events]
|
||||||
|
[status-im2.contexts.shell.activity-center.notification-types :as types]
|
||||||
[taoensso.timbre :as log]
|
[taoensso.timbre :as log]
|
||||||
[utils.collection :as collection]
|
[utils.collection :as collection]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
|
@ -502,12 +502,12 @@
|
||||||
{:events [:activity-center.notifications/show-toasts]}
|
{:events [:activity-center.notifications/show-toasts]}
|
||||||
[{:keys [db]} new-notifications]
|
[{:keys [db]} new-notifications]
|
||||||
(let [my-public-key (get-in db [:profile/profile :public-key])]
|
(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
|
(let [user-avatar {:full-name name
|
||||||
:status-indicator? true
|
:status-indicator? true
|
||||||
:online? nil
|
:online? nil
|
||||||
:size :small
|
:size :small
|
||||||
:ring? false}]
|
:ring? true}]
|
||||||
(cond
|
(cond
|
||||||
(and (not= author my-public-key)
|
(and (not= author my-public-key)
|
||||||
(= type types/contact-request)
|
(= type types/contact-request)
|
||||||
|
@ -515,6 +515,7 @@
|
||||||
(not dismissed))
|
(not dismissed))
|
||||||
(toasts/upsert cofx
|
(toasts/upsert cofx
|
||||||
{:user user-avatar
|
{:user user-avatar
|
||||||
|
:user-public-key author
|
||||||
:icon-color colors/primary-50-opa-40
|
:icon-color colors/primary-50-opa-40
|
||||||
:title (i18n/label :t/contact-request-sent-toast
|
:title (i18n/label :t/contact-request-sent-toast
|
||||||
{:name name})
|
{:name name})
|
||||||
|
@ -526,6 +527,7 @@
|
||||||
(not dismissed))
|
(not dismissed))
|
||||||
(toasts/upsert cofx
|
(toasts/upsert cofx
|
||||||
{:user user-avatar
|
{:user user-avatar
|
||||||
|
:user-public-key chat-id ;; user public key who accepted the request
|
||||||
:icon-color colors/success-50-opa-40
|
:icon-color colors/success-50-opa-40
|
||||||
:title (i18n/label :t/contact-request-accepted-toast
|
:title (i18n/label :t/contact-request-accepted-toast
|
||||||
{:name (or name (:alias message))})})
|
{:name (or name (:alias message))})})
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(ns status-im2.contexts.shell.activity-center.notification.common.view
|
(ns status-im2.contexts.shell.activity-center.notification.common.view
|
||||||
(:require [quo2.core :as quo]
|
(:require [quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.gesture :as gesture]
|
[react-native.gesture :as gesture]
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im2.contexts.shell.activity-center.notification.common.style :as style]
|
[status-im2.contexts.shell.activity-center.notification.common.style :as style]
|
||||||
[utils.i18n :as i18n]
|
[utils.i18n :as i18n]
|
||||||
|
@ -22,7 +22,8 @@
|
||||||
{:color :purple
|
{:color :purple
|
||||||
:size :small
|
:size :small
|
||||||
:style style/user-avatar-tag
|
:style style/user-avatar-tag
|
||||||
:text-style style/user-avatar-tag-text}
|
:text-style style/user-avatar-tag-text
|
||||||
|
:ring? false}
|
||||||
primary-name
|
primary-name
|
||||||
(multiaccounts/displayed-photo contact)]))
|
(multiaccounts/displayed-photo contact)]))
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
(ns status-im2.events
|
(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.common.toasts.events]
|
||||||
[status-im2.contexts.add-new-contact.events]
|
[status-im2.contexts.add-new-contact.events]
|
||||||
|
status-im2.contexts.chat.events
|
||||||
|
status-im2.contexts.chat.photo-selector.events
|
||||||
|
status-im2.contexts.communities.overview.events
|
||||||
status-im2.contexts.onboarding.events
|
status-im2.contexts.onboarding.events
|
||||||
[status-im.bottom-sheet.events]
|
status-im2.contexts.profile.events
|
||||||
[status-im2.db :as db]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
status-im2.contexts.shell.share.events
|
status-im2.contexts.shell.share.events
|
||||||
status-im2.contexts.syncing.events
|
status-im2.contexts.syncing.events
|
||||||
status-im2.contexts.chat.events
|
[status-im2.db :as db]
|
||||||
status-im2.common.password-authentication.events
|
[utils.re-frame :as rf]))
|
||||||
status-im2.contexts.communities.overview.events
|
|
||||||
status-im2.contexts.chat.photo-selector.events
|
|
||||||
status-im2.common.theme.events
|
|
||||||
status-im2.contexts.profile.events
|
|
||||||
[status-im.keycard.core :as keycard]))
|
|
||||||
|
|
||||||
(rf/defn start-app
|
(rf/defn start-app
|
||||||
{:events [:app-started]}
|
{:events [:app-started]}
|
||||||
|
@ -26,5 +27,7 @@
|
||||||
:biometric/get-supported-biometric-type nil
|
:biometric/get-supported-biometric-type nil
|
||||||
;;app starting flow continues in get-profiles-overview
|
;;app starting flow continues in get-profiles-overview
|
||||||
:profile/get-profiles-overview #(rf/dispatch
|
: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)))
|
(keycard/init)))
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.communities.core :as communities]
|
[status-im.communities.core :as communities]
|
||||||
|
[status-im.contact.core :as contact]
|
||||||
[status-im.group-chats.core :as group-chat]
|
[status-im.group-chats.core :as group-chat]
|
||||||
[status-im.group-chats.db :as group-chats.db]
|
[status-im.group-chats.db :as group-chats.db]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
[status-im2.contexts.chat.composer.constants :as composer.constants]
|
[status-im2.contexts.chat.composer.constants :as composer.constants]
|
||||||
[status-im2.contexts.chat.events :as chat.events]))
|
[status-im2.contexts.chat.events :as chat.events]))
|
||||||
|
@ -298,10 +298,9 @@
|
||||||
:chats/photo-path
|
:chats/photo-path
|
||||||
:<- [:contacts/contacts]
|
:<- [:contacts/contacts]
|
||||||
:<- [:profile/multiaccount]
|
:<- [:profile/multiaccount]
|
||||||
:<- [:mediaserver/port]
|
|
||||||
(fn [[contacts {:keys [public-key] :as multiaccount}] [_ id]]
|
(fn [[contacts {:keys [public-key] :as multiaccount}] [_ id]]
|
||||||
(multiaccounts/displayed-photo (or (when (= id public-key) multiaccount)
|
(let [contact (or (when (= id public-key) multiaccount) (get contacts id))]
|
||||||
(get contacts id)))))
|
(contact/displayed-photo contact))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:chats/unread-messages-number
|
:chats/unread-messages-number
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
(ns status-im2.subs.contact
|
(ns status-im2.subs.contact
|
||||||
(:require [clojure.string :as string]
|
(:require [clojure.string :as string]
|
||||||
[utils.i18n :as i18n]
|
[quo2.theme :as theme]
|
||||||
[re-frame.core :as re-frame]
|
[re-frame.core :as re-frame]
|
||||||
[status-im.contact.db :as contact.db]
|
[status-im.contact.db :as contact.db]
|
||||||
[status-im.ethereum.core :as ethereum]
|
[status-im.ethereum.core :as ethereum]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
|
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
|
||||||
[status-im.utils.gfycat.core :as gfycat]
|
[status-im.utils.gfycat.core :as gfycat]
|
||||||
[utils.image-server :as image-server]
|
|
||||||
[utils.collection]
|
|
||||||
[status-im2.constants :as constants]
|
[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
|
(re-frame/reg-sub
|
||||||
::query-current-chat-contacts
|
::query-current-chat-contacts
|
||||||
|
@ -32,28 +32,42 @@
|
||||||
(get multiaccount :profile-pictures-visibility)))
|
(get multiaccount :profile-pictures-visibility)))
|
||||||
|
|
||||||
(defn- replace-contact-image-uri
|
(defn- replace-contact-image-uri
|
||||||
[contact port contact-identity]
|
[contact port public-key font-file]
|
||||||
(let [theme (theme/get-theme)
|
(let [theme (theme/get-theme)
|
||||||
contact-images (:images contact)
|
{:keys [images ens-name]} contact
|
||||||
contact-images (reduce (fn [acc image]
|
images
|
||||||
|
(reduce (fn [acc image]
|
||||||
(let [image-name (:type image)
|
(let [image-name (:type image)
|
||||||
; We pass the clock so that we reload the image if the image
|
|
||||||
; is updated
|
|
||||||
clock (:clock image)
|
clock (:clock image)
|
||||||
uri (image-server/get-contact-image-uri port
|
uri (image-server/get-contact-image-uri-fn
|
||||||
contact-identity
|
{:port port
|
||||||
image-name
|
:public-key public-key
|
||||||
clock
|
:image-name image-name
|
||||||
theme)]
|
; We pass the clock so that we reload the
|
||||||
(assoc-in acc [(keyword image-name) :uri] uri)))
|
; image if the image is updated
|
||||||
contact-images
|
:clock clock
|
||||||
(vals contact-images))]
|
:theme theme
|
||||||
(assoc contact :images contact-images)))
|
: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
|
(defn- reduce-contacts-image-uri
|
||||||
[contacts port]
|
[contacts port font-file]
|
||||||
(reduce-kv (fn [acc public-key contact]
|
(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)))
|
(assoc acc public-key contact)))
|
||||||
{}
|
{}
|
||||||
contacts))
|
contacts))
|
||||||
|
@ -64,9 +78,10 @@
|
||||||
:<- [::profile-pictures-visibility]
|
:<- [::profile-pictures-visibility]
|
||||||
:<- [:multiaccount/public-key]
|
:<- [:multiaccount/public-key]
|
||||||
:<- [:mediaserver/port]
|
:<- [: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)]
|
(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
|
(re-frame/reg-sub
|
||||||
:contacts/active
|
:contacts/active
|
||||||
|
@ -175,10 +190,10 @@
|
||||||
contacts)))))
|
contacts)))))
|
||||||
|
|
||||||
(defn- enrich-contact
|
(defn- enrich-contact
|
||||||
[_ contact-identity ens-name port]
|
[_ contact-identity ens-name port font-file]
|
||||||
(let [contact (contact.db/enrich-contact
|
(let [contact (contact.db/enrich-contact
|
||||||
(contact.db/public-key-and-ens-name->new-contact contact-identity ens-name))]
|
(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
|
(re-frame/reg-sub
|
||||||
:contacts/current-contact
|
:contacts/current-contact
|
||||||
|
@ -186,11 +201,12 @@
|
||||||
:<- [:contacts/current-contact-identity]
|
:<- [:contacts/current-contact-identity]
|
||||||
:<- [:contacts/current-contact-ens-name]
|
:<- [:contacts/current-contact-ens-name]
|
||||||
:<- [:mediaserver/port]
|
:<- [: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)]
|
(let [contact (get contacts contact-identity)]
|
||||||
(cond-> contact
|
(cond-> contact
|
||||||
(nil? contact)
|
(nil? contact)
|
||||||
(enrich-contact contact-identity ens-name port)))))
|
(enrich-contact contact-identity ens-name port font-file)))))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:contacts/contact-by-identity
|
:contacts/contact-by-identity
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
(ns status-im2.subs.contact-test
|
(ns status-im2.subs.contact-test
|
||||||
(:require [cljs.test :refer [is testing]]
|
(:require [cljs.test :refer [is testing]]
|
||||||
[re-frame.db :as rf-db]
|
[re-frame.db :as rf-db]
|
||||||
[test-helpers.unit :as h]
|
|
||||||
status-im2.subs.contact
|
status-im2.subs.contact
|
||||||
|
[test-helpers.unit :as h]
|
||||||
[utils.re-frame :as rf]))
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
(def contacts-sample-data
|
(def contacts-sample-data
|
||||||
|
@ -74,14 +74,13 @@
|
||||||
:has-added-us? true
|
:has-added-us? true
|
||||||
:contact-request-state 1}}})
|
:contact-request-state 1}}})
|
||||||
|
|
||||||
(def expected-sorted-contacts
|
(def expected-sorted-contacts-without-images
|
||||||
[{:title "F"
|
[{:title "F"
|
||||||
:data [{:active? true
|
:data [{:active? true
|
||||||
:last-updated 1672582629695
|
:last-updated 1672582629695
|
||||||
:mutual? true
|
:mutual? true
|
||||||
:blocked? false
|
:blocked? false
|
||||||
:contactRequestClock 0
|
:contactRequestClock 0
|
||||||
:images {}
|
|
||||||
:added? true
|
:added? true
|
||||||
:name "slim.shady"
|
:name "slim.shady"
|
||||||
:primary-name "fslim.shady"
|
:primary-name "fslim.shady"
|
||||||
|
@ -105,7 +104,6 @@
|
||||||
:mutual? true
|
:mutual? true
|
||||||
:blocked? false
|
:blocked? false
|
||||||
:contactRequestClock 0
|
:contactRequestClock 0
|
||||||
:images {}
|
|
||||||
:added? true
|
:added? true
|
||||||
:name "slim.shady"
|
:name "slim.shady"
|
||||||
:primary-name "islim.shady"
|
:primary-name "islim.shady"
|
||||||
|
@ -129,7 +127,6 @@
|
||||||
:mutual? true
|
:mutual? true
|
||||||
:blocked? false
|
:blocked? false
|
||||||
:contactRequestClock 0
|
:contactRequestClock 0
|
||||||
:images {}
|
|
||||||
:added? true
|
:added? true
|
||||||
:name "slim.shady"
|
:name "slim.shady"
|
||||||
:primary-name "rslim.shady"
|
:primary-name "rslim.shady"
|
||||||
|
@ -148,6 +145,10 @@
|
||||||
:has-added-us? true
|
:has-added-us? true
|
||||||
:contact-request-state 1}]}])
|
: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
|
(h/deftest-sub :contacts/sorted-and-grouped-by-first-letter
|
||||||
[sub-name]
|
[sub-name]
|
||||||
(testing "Returning empty sequence when no contacts"
|
(testing "Returning empty sequence when no contacts"
|
||||||
|
@ -170,4 +171,5 @@
|
||||||
(dissoc contact :identicon))
|
(dissoc contact :identicon))
|
||||||
%)))
|
%)))
|
||||||
(rf/sub [sub-name]))]
|
(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))))))
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
[status-im.ethereum.core :as ethereum]
|
[status-im.ethereum.core :as ethereum]
|
||||||
[status-im.fleet.core :as fleet]
|
[status-im.fleet.core :as fleet]
|
||||||
[status-im.multiaccounts.db :as multiaccounts.db]
|
[status-im.multiaccounts.db :as multiaccounts.db]
|
||||||
|
[status-im2.constants :as constants]
|
||||||
[utils.image-server :as image-server]
|
[utils.image-server :as image-server]
|
||||||
[utils.security.core :as security]
|
[utils.security.core :as security]))
|
||||||
[status-im2.constants :as constants]))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:profile/customization-color
|
:profile/customization-color
|
||||||
|
@ -16,21 +16,44 @@
|
||||||
(fn [{:keys [customization-color]}]
|
(fn [{:keys [customization-color]}]
|
||||||
(or customization-color constants/profile-default-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
|
(re-frame/reg-sub
|
||||||
:profile/login-profiles-picture
|
:profile/login-profiles-picture
|
||||||
:<- [:profile/profiles-overview]
|
:<- [:profile/profiles-overview]
|
||||||
:<- [:mediaserver/port]
|
:<- [:mediaserver/port]
|
||||||
(fn [[multiaccounts port] [_ target-key-uid]]
|
:<- [:initials-avatar-font-file]
|
||||||
(let [image-name (-> multiaccounts
|
(fn [[multiaccounts port font-file] [_ target-key-uid]]
|
||||||
(get-in [target-key-uid :images])
|
(let [{:keys [images ens-name?] :as multiaccount} (get multiaccounts target-key-uid)
|
||||||
first
|
image-name (-> images first :type)
|
||||||
:type)]
|
override-ring? (not ens-name?)]
|
||||||
(when image-name
|
(when multiaccount
|
||||||
(image-server/get-account-image-uri {:port port
|
{:fn
|
||||||
|
(if image-name
|
||||||
|
(image-server/get-account-image-uri-fn {:port port
|
||||||
:image-name image-name
|
:image-name image-name
|
||||||
:key-uid target-key-uid
|
:key-uid target-key-uid
|
||||||
:theme (theme/get-theme)
|
:theme (theme/get-theme)
|
||||||
:ring? true})))))
|
: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
|
(re-frame/reg-sub
|
||||||
:multiaccount/public-key
|
:multiaccount/public-key
|
||||||
|
@ -224,30 +247,36 @@
|
||||||
(pos? (count (get multiaccount :images)))))
|
(pos? (count (get multiaccount :images)))))
|
||||||
|
|
||||||
(defn- replace-multiaccount-image-uri
|
(defn- replace-multiaccount-image-uri
|
||||||
[multiaccount port]
|
[multiaccount port font-file avatar-opts]
|
||||||
(let [public-key (:public-key multiaccount)
|
(let [{:keys [key-uid ens-name? images]} multiaccount
|
||||||
theme (theme/get-theme)
|
theme (theme/get-theme)
|
||||||
images (:images multiaccount)
|
avatar-opts (assoc avatar-opts :override-ring? (when ens-name? false))
|
||||||
images (reduce (fn [acc current]
|
images-with-uri (mapv (fn [{key-uid :keyUid image-name :type :as image}]
|
||||||
(let [key-uid (:keyUid current)
|
(let [uri-fn (image-server/get-account-image-uri-fn
|
||||||
image-name (:type current)
|
(merge {:port port
|
||||||
uri (image-server/get-account-image-uri {:port port
|
|
||||||
:public-key public-key
|
|
||||||
:image-name image-name
|
: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
|
:key-uid key-uid
|
||||||
:theme theme
|
:theme theme
|
||||||
:ring? true})]
|
:font-file font-file}
|
||||||
(conj acc (assoc current :uri uri))))
|
avatar-opts))}])]
|
||||||
[]
|
(assoc multiaccount :images new-images)))
|
||||||
images)]
|
|
||||||
(assoc multiaccount :images images)))
|
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:profile/multiaccount
|
:profile/multiaccount
|
||||||
:<- [:profile/profile]
|
:<- [:profile/profile]
|
||||||
:<- [:mediaserver/port]
|
:<- [:mediaserver/port]
|
||||||
(fn [[multiaccount port]]
|
:<- [:initials-avatar-font-file]
|
||||||
(replace-multiaccount-image-uri multiaccount port)))
|
(fn [[multiaccount port font-file] [_ avatar-opts]]
|
||||||
|
(replace-multiaccount-image-uri multiaccount port font-file avatar-opts)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:profile/login-profile
|
:profile/login-profile
|
||||||
|
|
|
@ -75,6 +75,7 @@
|
||||||
(reg-root-key-sub :password-authentication :password-authentication)
|
(reg-root-key-sub :password-authentication :password-authentication)
|
||||||
(reg-root-key-sub :shell/floating-screens :shell/floating-screens)
|
(reg-root-key-sub :shell/floating-screens :shell/floating-screens)
|
||||||
(reg-root-key-sub :shell/loaded-screens :shell/loaded-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
|
;;NOTE this one is not related to ethereum network
|
||||||
;; it is about cellular network/ wifi network
|
;; it is about cellular network/ wifi network
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
(ns status-im2.subs.shell
|
(ns status-im2.subs.shell
|
||||||
(:require [utils.i18n :as i18n]
|
(:require [re-frame.core :as re-frame]
|
||||||
[re-frame.core :as re-frame]
|
[status-im.multiaccounts.core :as multiaccounts]
|
||||||
[utils.datetime :as datetime]
|
[status-im2.common.resources :as resources]
|
||||||
[status-im2.config :as config]
|
[status-im2.config :as config]
|
||||||
[status-im2.constants :as constants]
|
[status-im2.constants :as constants]
|
||||||
[status-im2.common.resources :as resources]
|
[status-im2.contexts.shell.jump-to.constants :as shell.constants]
|
||||||
[status-im.multiaccounts.core :as multiaccounts]
|
[utils.datetime :as datetime]
|
||||||
[status-im2.contexts.shell.jump-to.constants :as shell.constants]))
|
[utils.i18n :as i18n]))
|
||||||
|
|
||||||
;; Helper Functions
|
;; Helper Functions
|
||||||
(defn community-avatar
|
(defn community-avatar
|
||||||
|
@ -79,13 +79,11 @@
|
||||||
:counter-label (:unviewed-mentions-count chat)})))
|
:counter-label (:unviewed-mentions-count chat)})))
|
||||||
|
|
||||||
(defn one-to-one-chat-card
|
(defn one-to-one-chat-card
|
||||||
[contact names chat id communities]
|
[contact names profile-picture chat id communities]
|
||||||
(let [images (:images contact)
|
(let [display-name (first names)]
|
||||||
profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))]
|
{:title display-name
|
||||||
{:title (first names)
|
:avatar-params {:full-name display-name
|
||||||
:avatar-params {:full-name (first names)
|
:profile-picture profile-picture}
|
||||||
:profile-picture (when profile-picture
|
|
||||||
(str profile-picture "&addRing=0"))}
|
|
||||||
:customization-color (or (:customization-color contact) :primary)
|
:customization-color (or (:customization-color contact) :primary)
|
||||||
:content (get-card-content
|
:content (get-card-content
|
||||||
{:chat chat
|
{:chat chat
|
||||||
|
@ -151,10 +149,16 @@
|
||||||
(fn [[_ id] _]
|
(fn [[_ id] _]
|
||||||
[(re-frame/subscribe [:contacts/contact-by-identity id])
|
[(re-frame/subscribe [:contacts/contact-by-identity id])
|
||||||
(re-frame/subscribe [:contacts/contact-two-names-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 [:chats/chat id])
|
||||||
(re-frame/subscribe [:communities])])
|
(re-frame/subscribe [:communities])])
|
||||||
(fn [[contact names chat communities] [_ id]]
|
(fn [[contact names profile-picture chat communities] [_ id]]
|
||||||
(one-to-one-chat-card contact names chat id communities)))
|
(one-to-one-chat-card contact
|
||||||
|
names
|
||||||
|
profile-picture
|
||||||
|
chat
|
||||||
|
id
|
||||||
|
communities)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:shell/private-group-chat-card
|
:shell/private-group-chat-card
|
||||||
|
|
|
@ -1,13 +1,43 @@
|
||||||
(ns utils.image-server
|
(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 image-server-uri-prefix "https://localhost:")
|
||||||
(def ^:const account-images-action "/accountImages")
|
(def ^:const account-images-action "/accountImages")
|
||||||
|
(def ^:const account-initials-action "/accountInitials")
|
||||||
(def ^:const contact-images-action "/contactImages")
|
(def ^:const contact-images-action "/contactImages")
|
||||||
(def ^:const generate-qr-action "/GenerateQRCode")
|
(def ^:const generate-qr-action "/GenerateQRCode")
|
||||||
(def ^:const status-profile-base-url "https://join.status.im/u/")
|
(def ^:const status-profile-base-url "https://join.status.im/u/")
|
||||||
(def ^:const status-profile-base-url-without-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 timestamp [] (datetime/timestamp))
|
||||||
|
|
||||||
(defn current-theme-index
|
(defn current-theme-index
|
||||||
|
@ -26,7 +56,22 @@
|
||||||
4))
|
4))
|
||||||
|
|
||||||
(defn get-account-image-uri
|
(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
|
(str image-server-uri-prefix
|
||||||
port
|
port
|
||||||
account-images-action
|
account-images-action
|
||||||
|
@ -36,15 +81,130 @@
|
||||||
key-uid
|
key-uid
|
||||||
"&imageName="
|
"&imageName="
|
||||||
image-name
|
image-name
|
||||||
|
"&size="
|
||||||
|
(Math/round (* size status-im.utils.pixel-ratio/ratio))
|
||||||
"&theme="
|
"&theme="
|
||||||
(current-theme-index theme)
|
(current-theme-index theme)
|
||||||
"&clock="
|
"&clock="
|
||||||
(timestamp)
|
(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="
|
"&addRing="
|
||||||
(if ring? 1 0)))
|
(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
|
(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
|
(str image-server-uri-prefix
|
||||||
port
|
port
|
||||||
contact-images-action
|
contact-images-action
|
||||||
|
@ -52,11 +212,34 @@
|
||||||
public-key
|
public-key
|
||||||
"&imageName="
|
"&imageName="
|
||||||
image-name
|
image-name
|
||||||
|
"&size="
|
||||||
|
(Math/round (* size status-im.utils.pixel-ratio/ratio))
|
||||||
"&theme="
|
"&theme="
|
||||||
(current-theme-index theme)
|
(current-theme-index theme)
|
||||||
"&clock="
|
"&clock="
|
||||||
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
|
(defn get-account-qr-image-uri
|
||||||
[{:keys [key-uid public-key port qr-size]}]
|
[{:keys [key-uid public-key port qr-size]}]
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
(ns utils.image-server-test
|
(ns utils.image-server-test
|
||||||
(:require [cljs.test :as t]
|
(:require [cljs.test :as t]
|
||||||
|
status-im.utils.pixel-ratio
|
||||||
[utils.image-server :as sut]))
|
[utils.image-server :as sut]))
|
||||||
|
|
||||||
(t/deftest get-account-image-uri
|
(t/deftest get-account-image-uri
|
||||||
(with-redefs
|
(with-redefs
|
||||||
[sut/current-theme-index identity
|
[sut/current-theme-index identity
|
||||||
|
status-im.utils.pixel-ratio/ratio 2
|
||||||
sut/timestamp (constantly "timestamp")]
|
sut/timestamp (constantly "timestamp")]
|
||||||
(t/is
|
(t/is
|
||||||
(=
|
(=
|
||||||
|
@ -12,6 +14,33 @@
|
||||||
:public-key "public-key"
|
:public-key "public-key"
|
||||||
:image-name "image-name"
|
:image-name "image-name"
|
||||||
:key-uid "key-uid"
|
:key-uid "key-uid"
|
||||||
:theme "theme"
|
:theme :dark
|
||||||
|
:indicator-size 2
|
||||||
|
:indicator-color "rgba(9,16,28,0.08)"
|
||||||
:ring? true})
|
:ring? true})
|
||||||
"https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&theme=theme&clock=timestamp&addRing=1"))))
|
"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,7 +3,7 @@
|
||||||
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
"_comment": "Instead use: scripts/update-status-go.sh <rev>",
|
||||||
"owner": "status-im",
|
"owner": "status-im",
|
||||||
"repo": "status-go",
|
"repo": "status-go",
|
||||||
"version": "v0.163.8",
|
"version": "v0.163.9",
|
||||||
"commit-sha1": "d61f983d9555e98cf84a3b1273687914887c2e67",
|
"commit-sha1": "f2f599fe867a0eba90aaa717a29bb6e99cb5749e",
|
||||||
"src-sha256": "1y0s5ivrkywj9simvv2i31ggfzg38li12if2lvfqn8nx10a5y9ai"
|
"src-sha256": "0p282pv2lz5f2b0vhpcx0nj74dp5mf7hb41l12js2hxsp21sprmj"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue