From a6710f902fad102a6de11fec530954e7486957e2 Mon Sep 17 00:00:00 2001 From: yqrashawn Date: Tue, 15 Aug 2023 09:59:40 +0800 Subject: [PATCH] feat: render all avatars using media server (#16193) --- .carve_ignore | 10 +- src/mocks/js_dependencies.cljs | 3 +- .../avatars/user_avatar/component_spec.cljs | 130 +----------- .../components/avatars/user_avatar/style.cljs | 93 +++------ .../components/avatars/user_avatar/view.cljs | 130 +++++++----- .../components/common/no_flicker_image.cljs | 49 +++++ .../inputs/profile_input/component_spec.cljs | 17 -- .../components/inputs/profile_input/view.cljs | 74 +++---- src/quo2/components/list_items/user_list.cljs | 19 +- .../profile/select_profile/view.cljs | 48 ++--- .../components/tags/context_tag/view.cljs | 7 +- src/react_native/fs.cljs | 8 + src/status_im/contact/core.cljs | 10 +- src/status_im/multiaccounts/logout/core.cljs | 19 +- src/status_im/multiaccounts/update/core.cljs | 13 +- .../ui/components/chat_icon/screen.cljs | 56 ++++- .../ui/screens/contacts_list/views.cljs | 12 +- .../ui/screens/profile/contact/views.cljs | 29 ++- .../ui/screens/profile/user/views.cljs | 15 +- src/status_im/utils/pixel_ratio.cljs | 4 + .../common/confirmation_drawer/view.cljs | 19 +- src/status_im2/common/font.cljs | 17 ++ src/status_im2/common/home/view.cljs | 5 +- src/status_im2/common/toasts/view.cljs | 13 +- src/status_im2/constants.cljs | 8 + .../contexts/add_new_contact/views.cljs | 9 +- .../contexts/chat/composer/reply/view.cljs | 17 +- .../chat/home/chat_list_item/view.cljs | 28 +-- .../contexts/chat/messages/avatar/view.cljs | 16 +- .../chat/messages/content/deleted/view.cljs | 4 +- .../contexts/chat/messages/list/view.cljs | 13 +- .../chat/messages/navigation/view.cljs | 15 +- .../drawers/nickname_drawer/view.cljs | 13 +- .../onboarding/create_profile/view.cljs | 29 +-- .../identifiers/profile_card/style.cljs | 6 +- .../identifiers/profile_card/view.cljs | 37 ++-- .../contexts/profile/profiles/view.cljs | 4 +- src/status_im2/contexts/profile/rpc.cljs | 4 +- .../quo_preview/avatars/user_avatar.cljs | 7 +- .../notifications/notification.cljs | 10 +- .../shell/activity_center/events.cljs | 26 +-- .../notification/common/view.cljs | 5 +- src/status_im2/events.cljs | 27 +-- src/status_im2/subs/chat/chats.cljs | 7 +- src/status_im2/subs/contact.cljs | 74 ++++--- src/status_im2/subs/contact_test.cljs | 14 +- src/status_im2/subs/profile.cljs | 93 ++++++--- src/status_im2/subs/root.cljs | 1 + src/status_im2/subs/shell.cljs | 34 ++-- src/utils/image_server.cljs | 191 +++++++++++++++++- src/utils/image_server_test.cljs | 47 ++++- status-go-version.json | 6 +- 52 files changed, 903 insertions(+), 642 deletions(-) create mode 100644 src/quo2/components/common/no_flicker_image.cljs create mode 100644 src/status_im/utils/pixel_ratio.cljs create mode 100644 src/status_im2/common/font.cljs diff --git a/.carve_ignore b/.carve_ignore index ad0c30d692..7c3f13fa73 100644 --- a/.carve_ignore +++ b/.carve_ignore @@ -95,11 +95,11 @@ status-im.hardwallet.simulated-keycard/sign-typed-data status-im.utils.core/safe-read-message-content status-im.ui.components.react/native-modules status-im.ui.components.react/progress-bar -status-im.utils.fs/move-file -status-im.utils.fs/read-dir -status-im.utils.fs/mkdir -status-im.utils.fs/unlink -status-im.utils.fs/file-exists? +react-native.fs/move-file +react-native.fs/read-dir +react-native.fs/mkdir +react-native.fs/unlink +react-native.fs/file-exists? quo.animated/code quo.animated/eq quo.animated/neq diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index 51475527b5..96f91c7db3 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -90,7 +90,8 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return ( :configureNext (fn [])} :requireNativeComponent (fn [] {:propTypes ""}) :Appearance {:getColorScheme (fn []) - :addChangeListener (fn [])}})) + :addChangeListener (fn [])} + :PixelRatio {:get (fn [])}})) (set! js/ReactNative react-native) diff --git a/src/quo2/components/avatars/user_avatar/component_spec.cljs b/src/quo2/components/avatars/user_avatar/component_spec.cljs index 5f983b2264..594b3c7cf1 100644 --- a/src/quo2/components/avatars/user_avatar/component_spec.cljs +++ b/src/quo2/components/avatars/user_avatar/component_spec.cljs @@ -2,14 +2,9 @@ (:require [quo2.components.avatars.user-avatar.view :as user-avatar] [test-helpers.component :as h])) -(defonce mock-picture (js/require "../resources/images/mock2/user_picture_male4.png")) +(defonce mock-picture {:uri (js/require "../resources/images/mock2/user_picture_male4.png")}) (h/describe "user avatar" - (h/test "Default render" - (h/render [user-avatar/user-avatar]) - (h/is-truthy (h/get-by-label-text :user-avatar)) - (h/is-truthy (h/get-by-text "EN"))) - (h/describe "Profile picture" (h/test "Renders" (h/render @@ -18,124 +13,5 @@ (h/test "Renders even if `:full-name` is passed" (h/render - [user-avatar/user-avatar - {:profile-picture mock-picture - :full-name "New User1"}]) - (h/is-truthy (h/get-by-label-text :profile-picture)) - (h/is-null (h/query-by-label-text :initials-avatar))) - - (h/describe "Status indicator" - (h/test "Render" - (h/render - [user-avatar/user-avatar - {:profile-picture mock-picture - :status-indicator? true}]) - (h/is-truthy (h/get-by-label-text :profile-picture)) - (h/is-truthy (h/get-by-label-text :status-indicator))) - - (h/test "Do not render" - (h/render - [user-avatar/user-avatar - {:profile-picture mock-picture - :status-indicator? false}]) - (h/is-truthy (h/get-by-label-text :profile-picture)) - (h/is-null (h/query-by-label-text :status-indicator))))) - - (h/describe "Initials Avatar" - (h/describe "Render initials" - (letfn [(user-avatar-component [size] - [user-avatar/user-avatar - {:full-name "New User" - :size size}])] - (h/describe "Two letters" - (h/test "Size :big" - (h/render (user-avatar-component :big)) - (h/is-truthy (h/get-by-text "NU"))) - - (h/test "Size :medium" - (h/render (user-avatar-component :medium)) - (h/is-truthy (h/get-by-text "NU"))) - - (h/test "Size :small" - (h/render (user-avatar-component :small)) - (h/is-truthy (h/get-by-text "NU"))) - - (h/test "Two letters with excess whitespace" - (h/render [user-avatar/user-avatar - {:full-name "New User" - :size :big}]) - (h/is-truthy (h/get-by-text "NU"))) - - (h/test "Two letters with leading whitespace" - (h/render [user-avatar/user-avatar - {:full-name " New User" - :size :big}]) - (h/is-truthy (h/get-by-text "NU")))) - - (h/describe "One letter" - (h/test "Size :xs" - (h/render (user-avatar-component :xs)) - (h/is-truthy (h/get-by-text "N"))) - - (h/test "Size :xxs" - (h/render (user-avatar-component :xxs)) - (h/is-truthy (h/get-by-text "N"))) - - (h/test "Size :xxxs" - (h/render (user-avatar-component :xxxs)) - (h/is-truthy (h/get-by-text "N")))))) - - (h/describe "Render ring" - (letfn [(user-avatar-component [size] - [user-avatar/user-avatar - {:full-name "New User" - :ring-background mock-picture - :size size}])] - (h/describe "Passed and drawn" - (h/test "Size :big" - (h/render (user-avatar-component :big)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-truthy (h/get-by-label-text :ring-background))) - - (h/test "Size :medium" - (h/render (user-avatar-component :medium)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-truthy (h/get-by-label-text :ring-background))) - - (h/test "Size :small" - (h/render (user-avatar-component :small)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-truthy (h/get-by-label-text :ring-background)))) - - (h/describe "Passed and not drawn (because of invalid size for ring)" - (h/test "Size :xs" - (h/render (user-avatar-component :xs)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-null (h/query-by-label-text :ring-background))) - - (h/test "Size :xxs" - (h/render (user-avatar-component :xxs)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-null (h/query-by-label-text :ring-background))) - - (h/test "Size :xxxs" - (h/render (user-avatar-component :xxxs)) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-null (h/query-by-label-text :ring-background)))))) - - (h/describe "Status indicator" - (h/test "Render" - (h/render - [user-avatar/user-avatar - {:full-name "Test User" - :status-indicator? true}]) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-truthy (h/get-by-label-text :status-indicator))) - - (h/test "Do not render" - (h/render - [user-avatar/user-avatar - {:full-name "Test User" - :status-indicator? false}]) - (h/is-truthy (h/get-by-label-text :initials-avatar)) - (h/is-null (h/query-by-label-text :status-indicator)))))) + [user-avatar/user-avatar {:profile-picture mock-picture}]) + (h/is-truthy (h/get-by-label-text :profile-picture))))) diff --git a/src/quo2/components/avatars/user_avatar/style.cljs b/src/quo2/components/avatars/user_avatar/style.cljs index 4740cb20fc..c4614e203e 100644 --- a/src/quo2/components/avatars/user_avatar/style.cljs +++ b/src/quo2/components/avatars/user_avatar/style.cljs @@ -2,92 +2,61 @@ (:require [quo2.foundations.colors :as colors])) (def sizes - {:big {:outer 80 - :inner 72 + {:big {:dimensions 80 :status-indicator 20 :status-indicator-border 4 :font-size :heading-1} - :medium {:outer 48 - :inner 44 + :medium {:dimensions 48 :status-indicator 12 :status-indicator-border 2 :font-size :heading-2} - :small {:outer 32 - :inner 28 + :small {:dimensions 32 :status-indicator 12 :status-indicator-border 2 :font-size :paragraph-2} - :xs {:outer 24 - :inner 24 + :xs {:dimensions 24 :status-indicator 0 :status-indicator-border 0 :font-size :paragraph-2} - :xxs {:outer 20 - :inner 20 + :xxs {:dimensions 20 :status-indicator 0 :status-indicator-border 0 :font-size :label} - :xxxs {:outer 16 - :inner 16 + :xxxs {:dimensions 16 :status-indicator 0 :status-indicator-border 0 :font-size :label}}) -(defn outer - [size] - (let [dimensions (get-in sizes [size :outer])] - {:width dimensions - :height dimensions - :border-radius dimensions})) - (defn initials-avatar - [size draw-ring? customization-color theme] - (let [outer-dimensions (get-in sizes [size :outer]) - inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])] + [size customization-color theme] + (let [dimensions (get-in sizes [size :dimensions])] {:position :absolute - :top (/ (- outer-dimensions inner-dimensions) 2) - :left (/ (- outer-dimensions inner-dimensions) 2) - :width inner-dimensions - :height inner-dimensions - :border-radius inner-dimensions + :top 0 + :left 0 + :width dimensions + :height dimensions + :border-radius dimensions :justify-content :center :align-items :center :background-color (colors/custom-color-by-theme customization-color 50 60 nil nil theme)})) +(def indicator-color + {:online colors/success-50 + :offline colors/neutral-40}) + +(defn outer + [size static-profile-picture?] + (let [dimensions (get-in sizes [size :dimensions]) + outer-style {:width dimensions + :height dimensions} + outer-style-with-border-radius (assoc outer-style :border-radius dimensions)] + (if static-profile-picture? + outer-style-with-border-radius + outer-style))) + +(defn customization-color + [color-id theme] + (colors/custom-color-by-theme color-id 50 60 nil nil theme)) + (def initials-avatar-text {:color colors/white-opa-70}) - -(defn inner-dot - [size online?] - (let [background (if online? colors/success-50 colors/neutral-40) - dimensions (get-in sizes [size :status-indicator])] - {:width (- dimensions 4) - :height (- dimensions 4) - :border-radius (- dimensions 4) - :background-color background})) - -(defn dot - [size ring? theme] - (let [dimensions (get-in sizes [size :status-indicator]) - border-width (get-in sizes [size :status-indicator-border]) - right (case size - :big 2 - :medium 0 - :small -2 - 0) - bottom (case size - :big (if ring? -1 2) - :medium (if ring? 0 -2) - :small -2 - 0)] - {:position :absolute - :justify-content :center - :align-items :center - :bottom bottom - :right right - :width dimensions - :height dimensions - :border-width border-width - :border-radius dimensions - :background-color (colors/theme-colors colors/white colors/neutral-100 theme) - :border-color (colors/theme-colors colors/white colors/neutral-100 theme)})) diff --git a/src/quo2/components/avatars/user_avatar/view.cljs b/src/quo2/components/avatars/user_avatar/view.cljs index 78abd836e1..1ab2d7608e 100644 --- a/src/quo2/components/avatars/user_avatar/view.cljs +++ b/src/quo2/components/avatars/user_avatar/view.cljs @@ -1,64 +1,104 @@ (ns quo2.components.avatars.user-avatar.view - (:require [quo2.components.avatars.user-avatar.style :as style] - [quo2.components.markdown.text :as text] - [quo2.theme :as quo.theme] - [react-native.core :as rn] - [react-native.fast-image :as fast-image] - utils.string)) + (:require + [quo2.components.avatars.user-avatar.style :as style] + [quo2.components.common.no-flicker-image :as no-flicker-image] + [quo2.components.markdown.text :as text] + [quo2.theme] + [react-native.core :as rn] + [react-native.fast-image :as fast-image] + utils.string)) (defn initials-avatar - [{:keys [full-name size draw-ring? customization-color theme]}] + [{:keys [full-name size customization-color theme]}] (let [font-size (get-in style/sizes [size :font-size]) amount-initials (if (#{:xs :xxs :xxxs} size) 1 2)] [rn/view {:accessibility-label :initials-avatar - :style (style/initials-avatar size draw-ring? customization-color theme)} + :style (style/initials-avatar size customization-color theme)} [text/text {:style style/initials-avatar-text :size font-size :weight :semi-bold} (utils.string/get-initials full-name amount-initials)]])) -(def valid-ring-sizes #{:big :medium :small}) +(defn user-avatar-internal + "Render user avatar with `profile-picture` + `profile-picture` should be one of {:uri profile-picture-uri} or {:fn profile-picture-fn} -(defn- user-avatar-internal - "If no `profile-picture` is given, draws the initials based on the `full-name` and - uses `ring-background` to display the ring behind the initials when given. Otherwise, - shows the `profile-picture` which already comes with the ring drawn." - [{:keys [full-name status-indicator? online? size profile-picture ring-background - customization-color static? muted? theme ring?] - :or {status-indicator? true + `profile-picture-fn` should return an image URI, there's helper fn to generate + it in `utils.image-server` + + params for `profile-picture-fn` + {:length initials' length + :full-name used to generate initials + :font-size initials font size + :indicator-size status indicator outer radius, set to nil or 0 when no indicator + :indicator-border `indicator-size`-`indicator-border` is the inner radius + :indicator-color color for status indicator + :override-theme override theme for ring + :background-color intials avatar background color + :color intials avatar text color + :size intials avatar radius + :ring? render ident ring around avatar?} + + supported color formats: + #RRGGBB + #RRGGBBAA + rgb(255,255,255) + rgba(255,255,255,0.1) note alpha is 0-1 + + the reason we use the `profile-picture-fn` here is to separate + logic (pubkey, key-uid... in subs) and style (color, size... in this component)" + [{:keys [full-name size profile-picture customization-color static? + status-indicator? online? ring? theme] + :or {size :big + status-indicator? true online? true ring? true - size :big - customization-color :turquoise}}] - (let [full-name (or full-name "empty name") - draw-ring? (and ring? (when-not muted? (and ring-background (valid-ring-sizes size)))) - outer-styles (style/outer size) - ;; Once image is loaded, fast image rerenders view with the help of reagent atom, + customization-color :turquoise} + :as props}] + (let [full-name (or full-name "Your Name") + ;; image generated with profile-picture-fn is round cropped + ;; no need to add border-radius for them + outer-styles (style/outer size (not (:fn profile-picture))) + ;; Once image is loaded, fast image re-renders view with the help of reagent atom, ;; But dynamic updates don't work when user-avatar is used inside hole-view ;; https://github.com/status-im/status-mobile/issues/15553 - image-view (if static? rn/image fast-image/fast-image)] - [rn/view {:style outer-styles :accessibility-label :user-avatar} - ;; The `profile-picture` already has the ring in it - (when-let [image (or profile-picture ring-background)] - [image-view - {:accessibility-label (if draw-ring? :ring-background :profile-picture) - :style outer-styles - :source image}]) - (when-not profile-picture - [initials-avatar - {:full-name full-name - :size size - :draw-ring? draw-ring? - :customization-color customization-color - :theme theme}]) - (when status-indicator? - [rn/view - {:accessibility-label :status-indicator - :style (style/dot size draw-ring? theme)} - [rn/view - {:accessibility-label :inner-status-indicator-dot - :style (style/inner-dot size online?)}]])])) + image-view (if static? no-flicker-image/image fast-image/fast-image) + font-size (get-in style/sizes [size :font-size]) + amount-initials (if (#{:xs :xxs :xxxs} size) 1 2) + sizes (get style/sizes size) + indicator-color (get style/indicator-color (if online? :online :offline)) + profile-picture-fn (:fn profile-picture)] -(def user-avatar (quo.theme/with-theme user-avatar-internal)) + [rn/view {:style outer-styles :accessibility-label :user-avatar} + (if (and full-name (not (or profile-picture-fn profile-picture))) + ;; this is for things that's not user-avatar + ;; but are currently using user-avatar to render the initials + ;; e.g. community avatar + [initials-avatar props] + [image-view + {:accessibility-label :profile-picture + :style outer-styles + :source + (cond profile-picture-fn + {:uri (profile-picture-fn + {:length amount-initials + :full-name full-name + :font-size (:font-size (text/text-style {:size + font-size})) + :indicator-size (when status-indicator? + (:status-indicator sizes)) + :indicator-border (when status-indicator? + (:status-indicator-border sizes)) + :indicator-color indicator-color + :override-theme theme + :background-color (style/customization-color customization-color theme) + :color (:color style/initials-avatar-text) + :size (:width outer-styles) + :ring? ring?})} + (:uri profile-picture) + profile-picture + :else {:uri profile-picture})}])])) + +(def user-avatar (quo2.theme/with-theme user-avatar-internal)) diff --git a/src/quo2/components/common/no_flicker_image.cljs b/src/quo2/components/common/no_flicker_image.cljs new file mode 100644 index 0000000000..fc15b4bd90 --- /dev/null +++ b/src/quo2/components/common/no_flicker_image.cljs @@ -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]])))) diff --git a/src/quo2/components/inputs/profile_input/component_spec.cljs b/src/quo2/components/inputs/profile_input/component_spec.cljs index c21fa65ad7..e4109036e5 100644 --- a/src/quo2/components/inputs/profile_input/component_spec.cljs +++ b/src/quo2/components/inputs/profile_input/component_spec.cljs @@ -3,23 +3,6 @@ [test-helpers.component :as h])) (h/describe "Profile Input" - (h/test "renders user avatar with placeholder name if no value is specified" - (h/render [profile-input/profile-input - {:placeholder "Your Name" - :image-picker-props {:full-name "Your Name"}}]) - (-> (js/expect (h/get-by-text "YN")) - (.toBeTruthy))) - - (h/test "renders user avatar with full name if a value is specified" - (let [event (h/mock-fn)] - (h/render [profile-input/profile-input - {:on-change event - :placeholder "Your Name" - :image-picker-props {:full-name "Test Name"}}]) - (h/fire-event :change (h/get-by-text "TN")) - (-> (js/expect (h/get-by-text "TN")) - (.toBeTruthy)))) - (h/test "on press event fires" (let [event (h/mock-fn)] (h/render [profile-input/profile-input diff --git a/src/quo2/components/inputs/profile_input/view.cljs b/src/quo2/components/inputs/profile_input/view.cljs index 3afe5390be..ac8f8c4539 100644 --- a/src/quo2/components/inputs/profile_input/view.cljs +++ b/src/quo2/components/inputs/profile_input/view.cljs @@ -1,7 +1,7 @@ (ns quo2.components.inputs.profile-input.view (:require - [quo2.components.buttons.button.view :as buttons] [quo2.components.avatars.user-avatar.view :as user-avatar] + [quo2.components.buttons.button.view :as buttons] [quo2.components.inputs.profile-input.style :as style] [quo2.components.inputs.title-input.view :as title-input] [react-native.core :as rn] @@ -13,38 +13,40 @@ on-press title-input-props image-picker-props]}] - [rn/view - {:style (style/container customization-color)} - [rn/view - [hole-view/hole-view - ;; Force re-render hole view when props are changed - ;; https://github.com/status-im/status-mobile/issues/15577 - {:key (hash - (if (:profile-picture image-picker-props) - (:profile-picture image-picker-props) - image-picker-props)) - :holes [{:x 33 - :y 24 - :width 24 - :height 24 - :borderRadius 12}]} - [user-avatar/user-avatar - (assoc image-picker-props - :static? true - :status-indicator? false - :size :medium)]] - [buttons/button - {:accessibility-label :select-profile-picture-button - :type :grey - :background :blur - :on-press on-press - :size 24 - :icon-only? true - :container-style style/button - :inner-style style/button-inner} :i/camera]] - [rn/view {:style style/input-container} - [title-input/title-input - (merge title-input-props - {:blur? true - :placeholder placeholder - :customization-color customization-color})]]]) + (let [full-name (:full-name image-picker-props)] + [rn/view + {:style (style/container customization-color)} + [rn/view + [hole-view/hole-view + ;; Force re-render hole view when props are changed + ;; https://github.com/status-im/status-mobile/issues/15577 + {:key (hash + (if (:profile-picture image-picker-props) + (:profile-picture image-picker-props) + image-picker-props)) + :holes [{:x 33 + :y 24 + :width 24 + :height 24 + :borderRadius 12}]} + [user-avatar/user-avatar + (assoc image-picker-props + :static? true + :status-indicator? false + :full-name (if (seq full-name) full-name placeholder) + :size :medium)]] + [buttons/button + {:accessibility-label :select-profile-picture-button + :type :grey + :background :blur + :on-press on-press + :size 24 + :icon-only? true + :container-style style/button + :inner-style style/button-inner} :i/camera]] + [rn/view {:style style/input-container} + [title-input/title-input + (merge title-input-props + {:blur? true + :placeholder placeholder + :customization-color customization-color})]]])) diff --git a/src/quo2/components/list_items/user_list.cljs b/src/quo2/components/list_items/user_list.cljs index a91b75f12e..25fc845598 100644 --- a/src/quo2/components/list_items/user_list.cljs +++ b/src/quo2/components/list_items/user_list.cljs @@ -1,11 +1,11 @@ (ns quo2.components.list-items.user-list - (:require [react-native.core :as rn] - [quo2.components.avatars.user-avatar.view :as user-avatar] - [quo2.components.markdown.text :as text] + (:require [quo2.components.avatars.user-avatar.view :as user-avatar] [quo2.components.icon :as icons] - [quo2.foundations.colors :as colors] + [quo2.components.markdown.text :as text] [quo2.components.messages.author.view :as author] - [quo2.components.selectors.selectors.view :as selectors])) + [quo2.components.selectors.selectors.view :as selectors] + [quo2.foundations.colors :as colors] + [react-native.core :as rn])) (def container-style {:margin-horizontal 8 @@ -45,11 +45,10 @@ :on-press (when on-press on-press) :on-long-press (when on-long-press on-long-press)} [user-avatar/user-avatar - {:full-name primary-name - :profile-picture photo-path - :status-indicator? true - :online? online? - :size :small}] + {:full-name primary-name + :profile-picture photo-path + :online? online? + :size :small}] [rn/view {:style {:margin-left 8}} [author/author {:primary-name primary-name diff --git a/src/quo2/components/profile/select_profile/view.cljs b/src/quo2/components/profile/select_profile/view.cljs index e627caa246..84cc5e7111 100644 --- a/src/quo2/components/profile/select_profile/view.cljs +++ b/src/quo2/components/profile/select_profile/view.cljs @@ -1,9 +1,9 @@ (ns quo2.components.profile.select-profile.view (:require + [quo2.components.avatars.user-avatar.view :as user-avatar] + [quo2.components.markdown.text :as text] [quo2.components.profile.select-profile.style :as style] [react-native.core :as rn] - [quo2.components.markdown.text :as text] - [quo2.components.avatars.user-avatar.view :as user-avatar] [reagent.core :as reagent])) (defn- on-change-handler @@ -24,31 +24,27 @@ (let [internal-selected? (reagent/atom (or default-selected? false))] (fn [{:keys [selected? profile-picture - ring-background name customization-color on-change] :or {customization-color :turquoise}}] - (let [avatar-image-key (if profile-picture :profile-picture :ring-background) - picture (or profile-picture ring-background)] - (when (and (not (nil? selected?)) (not= @internal-selected? selected?)) - (reset! internal-selected? selected?)) - [rn/touchable-opacity - {:style (style/container customization-color @internal-selected?) - :on-press #(on-change-handler internal-selected? on-change) - :active-opacity 1 - :accessibility-label :select-profile} - [rn/view {:style style/header} - [user-avatar/user-avatar - {:full-name name - :status-indicator? false - :size :medium - avatar-image-key picture}] - [rn/view {:style (style/select-radio @internal-selected?)} - (when @internal-selected? [rn/view {:style style/select-radio-inner}])]] - [text/text - {:size :heading-2 - :weight :semi-bold - :style style/profile-name} - name]])))) - + (when (and (not (nil? selected?)) (not= @internal-selected? selected?)) + (reset! internal-selected? selected?)) + [rn/touchable-opacity + {:style (style/container customization-color @internal-selected?) + :on-press #(on-change-handler internal-selected? on-change) + :active-opacity 1 + :accessibility-label :select-profile} + [rn/view {:style style/header} + [user-avatar/user-avatar + {:full-name name + :status-indicator? false + :size :medium + :profile-picture profile-picture}] + [rn/view {:style (style/select-radio @internal-selected?)} + (when @internal-selected? [rn/view {:style style/select-radio-inner}])]] + [text/text + {:size :heading-2 + :weight :semi-bold + :style style/profile-name} + name]]))) diff --git a/src/quo2/components/tags/context_tag/view.cljs b/src/quo2/components/tags/context_tag/view.cljs index dc2d20e327..506089865e 100644 --- a/src/quo2/components/tags/context_tag/view.cljs +++ b/src/quo2/components/tags/context_tag/view.cljs @@ -1,6 +1,6 @@ (ns quo2.components.tags.context-tag.view (:require [quo2.components.avatars.group-avatar.view :as group-avatar] - [quo2.components.avatars.user-avatar.style :as user-avatar-style] + [quo2.components.avatars.user-avatar.style :as user-avatar.style] [quo2.components.avatars.user-avatar.view :as user-avatar] [quo2.components.icon :as icons] [quo2.components.markdown.text :as text] @@ -40,7 +40,7 @@ (trim-public-key public-key)]]) (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} photo name @@ -52,7 +52,7 @@ :ellipsize-mode :tail} empty-photo? (nil? photo) 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)) (if (and empty-photo? no-avatar-placeholder?) [rn/view {:style {:width avatar-outer-size}}] @@ -60,6 +60,7 @@ {:full-name name :profile-picture photo :size avatar-size + :ring? ring? :status-indicator? false}]) [rn/view {:style (or text-container-style style/context-tag-text-container)} (if ellipsize-text? diff --git a/src/react_native/fs.cljs b/src/react_native/fs.cljs index 2d61585d38..8652545e62 100644 --- a/src/react_native/fs.cljs +++ b/src/react_native/fs.cljs @@ -42,3 +42,11 @@ (defn cache-dir [] (.-CachesDirectoryPath ^js react-native-fs)) + +(defn copy-assets + [src dest] + (.copyFileAssets ^js react-native-fs src dest)) + +(defn main-bundle-path + [] + (.-MainBundlePath ^js react-native-fs)) diff --git a/src/status_im/contact/core.cljs b/src/status_im/contact/core.cljs index 39c93c4099..0562e82f48 100644 --- a/src/status_im/contact/core.cljs +++ b/src/status_im/contact/core.cljs @@ -1,6 +1,6 @@ (ns status-im.contact.core - (:require [utils.re-frame :as rf] - [status-im2.navigation.events :as navigation])) + (:require [status-im2.navigation.events :as navigation] + [utils.re-frame :as rf])) (rf/defn open-contact-toggle-list {:events [:contact.ui/start-group-chat-pressed]} @@ -10,3 +10,9 @@ :group/selected-contacts #{} :new-chat-name "")} (navigation/navigate-to :contact-toggle-list nil))) + +(defn displayed-photo + [{:keys [images]}] + (or (:large images) + (:thumbnail images) + (first images))) diff --git a/src/status_im/multiaccounts/logout/core.cljs b/src/status_im/multiaccounts/logout/core.cljs index faaea55589..ed931d7cf1 100644 --- a/src/status_im/multiaccounts/logout/core.cljs +++ b/src/status_im/multiaccounts/logout/core.cljs @@ -1,13 +1,13 @@ (ns status-im.multiaccounts.logout.core - (:require [re-frame.core :as re-frame] - [utils.i18n :as i18n] + (:require [native-module.core :as native-module] + [re-frame.core :as re-frame] [status-im.multiaccounts.core :as multiaccounts] - [native-module.core :as native-module] [status-im.notifications.core :as notifications] - [utils.re-frame :as rf] [status-im.wallet.core :as wallet] [status-im2.common.keychain.events :as keychain] - [status-im2.db :as db])) + [status-im2.db :as db] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) (re-frame/reg-fx ::logout @@ -15,14 +15,15 @@ (native-module/logout))) (rf/defn initialize-app-db - [{{:keys [keycard] + [{{:keys [keycard initials-avatar-font-file] :biometric/keys [supported-type] :network/keys [type]} :db}] {:db (assoc db/app-db - :network/type type - :keycard (dissoc keycard :secrets :pin :application-info) - :biometric/supported-type supported-type)}) + :network/type type + :initials-avatar-font-file initials-avatar-font-file + :keycard (dissoc keycard :secrets :pin :application-info) + :biometric/supported-type supported-type)}) (rf/defn logout-method {:events [::logout-method]} diff --git a/src/status_im/multiaccounts/update/core.cljs b/src/status_im/multiaccounts/update/core.cljs index d5aa941840..ca1d5a5bb0 100644 --- a/src/status_im/multiaccounts/update/core.cljs +++ b/src/status_im/multiaccounts/update/core.cljs @@ -1,5 +1,6 @@ (ns status-im.multiaccounts.update.core - (:require [status-im.utils.types :as types] + (:require [status-im.ethereum.ens :as ens] + [status-im.utils.types :as types] [status-im2.constants :as constants] [taoensso.timbre :as log] [utils.re-frame :as rf])) @@ -19,10 +20,12 @@ display-name]} (:profile/profile db) account (some #(and (= (:key-uid %) key-uid) %) raw-multiaccounts-from-status-go)] (when-let [new-name (and account (or preferred-name display-name name))] - (rf/merge cofx - {:json-rpc/call [{:method "multiaccounts_updateAccount" - :params [(assoc account :name new-name)] - :on-success #(log/debug "sent multiaccount update")}]})))) + (rf/merge + cofx + {:db (assoc-in db [:profile/profile :ens-name?] (ens/is-valid-eth-name? new-name)) + :json-rpc/call [{:method "multiaccounts_updateAccount" + :params [(assoc account :name new-name)] + :on-success #(log/debug "sent multiaccount update")}]})))) (rf/defn multiaccount-update "Takes effects (containing :db) + new multiaccount fields, adds all effects necessary for multiaccount update. diff --git a/src/status_im/ui/components/chat_icon/screen.cljs b/src/status_im/ui/components/chat_icon/screen.cljs index aa914832e2..d3845a1795 100644 --- a/src/status_im/ui/components/chat_icon/screen.cljs +++ b/src/status_im/ui/components/chat_icon/screen.cljs @@ -2,8 +2,11 @@ (:require [clojure.string :as string] [quo.design-system.colors :as colors] [quo.react-native :as rn] + [quo2.components.avatars.user-avatar.style :as user-avatar.style] [quo2.core :as quo] + [quo2.theme :as theme] [re-frame.core :as re-frame.core] + [status-im.ethereum.ens :as ens] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.chat-icon.styles :as styles] [status-im.ui.components.icons.icons :as icons] @@ -47,7 +50,7 @@ [rn/text {:style (:default-chat-icon-text styles)} emoji]])) (defn profile-photo-plus-dot-view - [{:keys [public-key photo-container photo-path community?]}] + [{:keys [public-key full-name customization-color photo-container photo-path community?]}] (let [photo-container (if (nil? photo-container) styles/container-chat-list photo-container) @@ -55,11 +58,28 @@ dot-styles (visibility-status-utils/icon-visibility-status-dot public-key size) - dot-accessibility-label (:accessibility-label dot-styles)] + dot-accessibility-label (:accessibility-label dot-styles) + text-style (styles/default-chat-icon-text size)] [rn/view {:style photo-container :accessibility-label :profile-photo} - [photos/photo photo-path {:size size}] + (if (:fn photo-path) + ;; temp support new media server avatar for old component + [photos/photo + {:uri ((:fn photo-path) + {:size size + :full-name full-name + :font-size (get text-style :font-size) + :background-color (user-avatar.style/customization-color customization-color + (theme/get-theme)) + :indicator-size 0 + :indicator-border 0 + :indicator-color "#000000" + :color (get text-style :color) + :length 2 + :ring? (not (ens/is-valid-eth-name? full-name))})} + {:size size}] + [photos/photo photo-path {:size size}]) (when-not community? [rn/view {:style dot-styles @@ -179,14 +199,28 @@ (defn profile-icon-view [photo-path name color emoji edit? size override-styles public-key community?] - (let [styles (merge {:container {:width size :height size} - :size size - :chat-icon styles/chat-icon-profile - :default-chat-icon (styles/default-chat-icon-profile color size) - :default-chat-icon-text (if (string/blank? emoji) - (styles/default-chat-icon-text size) - (styles/emoji-chat-icon-text size))} - override-styles)] + (let [styles (merge {:container {:width size :height size} + :size size + :chat-icon styles/chat-icon-profile + :default-chat-icon (styles/default-chat-icon-profile color size) + :default-chat-icon-text (if (string/blank? emoji) + (styles/default-chat-icon-text size) + (styles/emoji-chat-icon-text size))} + override-styles) + photo-path (if (:fn photo-path) + ;; temp support new media server avatar for old component + {:uri ((:fn photo-path) + {:size size + :full-name name + :font-size (get-in styles [:default-chat-icon-text :font-size]) + :background-color (get-in styles [:default-chat-icon :background-color]) + :indicator-size 0 + :indicator-border 0 + :indicator-color "#000000" + :color (get-in styles [:default-chat-icon-text :color]) + :length 2 + :ring? (not (ens/is-valid-eth-name? name))})} + photo-path)] [rn/view (:container styles) (if (and photo-path (seq photo-path)) [profile-photo-plus-dot-view diff --git a/src/status_im/ui/screens/contacts_list/views.cljs b/src/status_im/ui/screens/contacts_list/views.cljs index 8cf1b17edb..ee5a78f576 100644 --- a/src/status_im/ui/screens/contacts_list/views.cljs +++ b/src/status_im/ui/screens/contacts_list/views.cljs @@ -2,23 +2,25 @@ (:require [quo.core :as quo] [quo.design-system.colors :as colors] [re-frame.core :as re-frame] - [utils.i18n :as i18n] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.chat-icon.screen :as chat-icon.screen] [status-im.ui.components.invite.views :as invite] [status-im.ui.components.list.views :as list.views] - [status-im.ui.components.react :as react]) + [status-im.ui.components.react :as react] + [utils.i18n :as i18n]) (:require-macros [status-im.utils.views :refer [defview letsubs]])) (defn contacts-list-item [{:keys [public-key] :as contact}] - (let [{:keys [primary-name secondary-name]} contact] + (let [{:keys [primary-name secondary-name customization-color]} contact] [quo/list-item {:title primary-name :subtitle secondary-name :icon [chat-icon.screen/profile-photo-plus-dot-view - {:public-key public-key - :photo-path (multiaccounts/displayed-photo contact)}] + {:public-key public-key + :full-name primary-name + :customization-color (or customization-color :primary) + :photo-path (multiaccounts/displayed-photo contact)}] :chevron true :on-press #(re-frame/dispatch [:chat.ui/show-profile public-key])}])) diff --git a/src/status_im/ui/screens/profile/contact/views.cljs b/src/status_im/ui/screens/profile/contact/views.cljs index d25469c7e5..dd93d92c94 100644 --- a/src/status_im/ui/screens/profile/contact/views.cljs +++ b/src/status_im/ui/screens/profile/contact/views.cljs @@ -3,9 +3,10 @@ [quo.components.list.item :as list-item] [quo.core :as quo] [quo.design-system.colors :as colors] + [quo2.components.avatars.user-avatar.style :as user-avatar.style] + [quo2.theme :as theme] [re-frame.core :as re-frame] [reagent.core :as reagent] - [utils.i18n :as i18n] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.keyboard-avoid-presentation :as kb-presentation] [status-im.ui.components.profile-header.view :as profile-header] @@ -13,8 +14,9 @@ [status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.topbar :as topbar] [status-im.ui.screens.profile.components.sheets :as sheets] - [utils.re-frame :as rf] - [status-im2.constants :as constants])) + [status-im2.constants :as constants] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) (defn actions [{:keys [public-key added? blocked? ens-name mutual?] :as contact} muted?] @@ -179,9 +181,11 @@ :as contact} @(re-frame/subscribe [:contacts/current-contact]) + muted? @(re-frame/subscribe [:chats/muted public-key]) - {:keys [primary-name secondary-name]} contact + {:keys [primary-name secondary-name customization-color]} contact + customization-color (or customization-color :primary) on-share #(re-frame/dispatch [:show-popover (merge @@ -201,14 +205,17 @@ :on-press #(re-frame/dispatch [:navigate-back])}]}] [:<> [(profile-header/extended-header - {:on-press on-share + {:on-press on-share :bottom-separator false - :title primary-name - :photo (multiaccounts/displayed-photo contact) - :monospace (not ens-verified) - :subtitle secondary-name - :compressed-key compressed-key - :public-key public-key})] + :title primary-name + :color + (user-avatar.style/customization-color customization-color + (theme/get-theme)) + :photo (multiaccounts/displayed-photo contact) + :monospace (not ens-verified) + :subtitle secondary-name + :compressed-key compressed-key + :public-key public-key})] [react/view {:height 1 :background-color colors/gray-lighter :margin-top 8}] [nickname-settings contact] diff --git a/src/status_im/ui/screens/profile/user/views.cljs b/src/status_im/ui/screens/profile/user/views.cljs index 5eb6dc57cc..45c06d1832 100644 --- a/src/status_im/ui/screens/profile/user/views.cljs +++ b/src/status_im/ui/screens/profile/user/views.cljs @@ -2,16 +2,16 @@ (:require [quo.core :as quo] [quo.design-system.colors :as colors] [quo.design-system.spacing :as spacing] + [quo2.components.avatars.user-avatar.style :as user-avatar.style] + [quo2.theme :as theme] [re-frame.core :as re-frame] [reagent.core :as reagent] [status-im.ethereum.stateofus :as stateofus] - [utils.i18n :as i18n] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.components.common.common :as components.common] [status-im.ui.components.copyable-text :as copyable-text] [status-im.ui.components.list-selection :as list-selection] [status-im.ui.components.profile-header.view :as profile-header] - [status-im2.common.qr-code-viewer.view :as qr-code-viewer] [status-im.ui.components.react :as react] [status-im.ui.screens.profile.user.edit-picture :as edit] [status-im.ui.screens.profile.user.styles :as styles] @@ -19,7 +19,9 @@ [status-im.utils.gfycat.core :as gfy] [status-im.utils.universal-links.utils :as universal-links] [status-im.utils.utils :as utils] - [status-im2.config :as config]) + [status-im2.common.qr-code-viewer.view :as qr-code-viewer] + [status-im2.config :as config] + [utils.i18n :as i18n]) (:require-macros [status-im.utils.views :as views])) (views/defview share-chat-key @@ -190,9 +192,12 @@ (let [{:keys [public-key compressed-key ens-verified - preferred-name] + preferred-name + key-uid] :as account} @(re-frame/subscribe [:profile/multiaccount]) + customization-color (or (:color @(re-frame/subscribe [:onboarding-2/profile])) + @(re-frame/subscribe [:profile/customization-color key-uid])) on-share #(re-frame/dispatch [:show-popover {:view :share-chat-key :address (or compressed-key @@ -213,6 +218,8 @@ :on-edit #(re-frame/dispatch [:bottom-sheet/show-sheet-old {:content (edit/bottom-sheet has-picture)}]) + :color (user-avatar.style/customization-color customization-color + (theme/get-theme)) :title (multiaccounts/displayed-name account) :photo (multiaccounts/displayed-photo account) :monospace (not ens-verified) diff --git a/src/status_im/utils/pixel_ratio.cljs b/src/status_im/utils/pixel_ratio.cljs new file mode 100644 index 0000000000..ccd2563aa0 --- /dev/null +++ b/src/status_im/utils/pixel_ratio.cljs @@ -0,0 +1,4 @@ +(ns status-im.utils.pixel-ratio + (:require ["react-native" :as rn])) + +(def ratio (rn/PixelRatio.get)) diff --git a/src/status_im2/common/confirmation_drawer/view.cljs b/src/status_im2/common/confirmation_drawer/view.cljs index 29d7d9c5f8..e84162bbbe 100644 --- a/src/status_im2/common/confirmation_drawer/view.cljs +++ b/src/status_im2/common/confirmation_drawer/view.cljs @@ -1,9 +1,9 @@ (ns status-im2.common.confirmation-drawer.view - (:require [utils.i18n :as i18n] - [quo2.core :as quo] + (:require [quo2.core :as quo] [react-native.core :as rn] [reagent.core :as reagent] [status-im2.common.confirmation-drawer.style :as style] + [utils.i18n :as i18n] [utils.re-frame :as rf])) (defn avatar @@ -13,10 +13,10 @@ {:customization-color color :size :x-small}] [quo/user-avatar - {:full-name display-name - :profile-picture photo-path - :size :xxs - :status-indicator false}])) + {:full-name display-name + :profile-picture photo-path + :size :xxs + :status-indicator? false}])) (defn extra-action-view [extra-action extra-text extra-action-selected?] @@ -41,12 +41,7 @@ (= contact-name-by-identity nil) name :else contact-name-by-identity) - contact (when-not group-chat - (rf/sub [:contacts/contact-by-address - id])) - photo-path (or profile-picture - (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path id])))] + photo-path (or profile-picture (rf/sub [:chats/photo-path id]))] [rn/view {:style {:margin-horizontal 20} :accessibility-label accessibility-label} diff --git a/src/status_im2/common/font.cljs b/src/status_im2/common/font.cljs new file mode 100644 index 0000000000..cc26cf7101 --- /dev/null +++ b/src/status_im2/common/font.cljs @@ -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)})) diff --git a/src/status_im2/common/home/view.cljs b/src/status_im2/common/home/view.cljs index a3235c286e..5e7d72f2eb 100644 --- a/src/status_im2/common/home/view.cljs +++ b/src/status_im2/common/home/view.cljs @@ -60,10 +60,7 @@ {:accessibility-label :open-profile :style style/left-section} [quo/user-avatar - (merge {:status-indicator? true - :size :small - :online? online?} - avatar)]]])) + (merge {:size :small :online? online?} avatar)]]])) (defn connectivity-sheet [] diff --git a/src/status_im2/common/toasts/view.cljs b/src/status_im2/common/toasts/view.cljs index 5df33033a3..4d68b3133c 100644 --- a/src/status_im2/common/toasts/view.cljs +++ b/src/status_im2/common/toasts/view.cljs @@ -11,10 +11,17 @@ (defn toast [toast-id] - (let [{:keys [type] :as toast-opts} (rf/sub [:toasts/toast toast-id])] + (let [{:keys [type user-public-key] :as toast-opts} (rf/sub [:toasts/toast toast-id]) + profile-picture (when user-public-key + (rf/sub [:chats/photo-path user-public-key])) + toast-opts-with-profile-picture (if profile-picture + (assoc-in toast-opts + [:user :profile-picture] + profile-picture) + toast-opts)] (if (= type :notification) - [quo/notification toast-opts] - [quo/toast toast-opts]))) + [quo/notification toast-opts-with-profile-picture] + [quo/toast toast-opts-with-profile-picture]))) (defn f-container [toast-id] diff --git a/src/status_im2/constants.cljs b/src/status_im2/constants.cljs index d1985d7a7a..d4753e76bf 100644 --- a/src/status_im2/constants.cljs +++ b/src/status_im2/constants.cljs @@ -345,3 +345,11 @@ (def ^:const onboarding-modal-animation-duration 300) (def ^:const onboarding-modal-animation-delay 400) + +(def ^:const initials-avatar-font-conf + "we pass absolute font file path and uppercase ratio to status-go for media + server to serve initials avatar image + `:uppercase-ratio` is uppercase-height/line-height for Inter-Medium" + {:ios "Inter-Medium.otf" + :android "Inter-Medium.ttf" + :uppercase-ratio 0.603861228044709}) diff --git a/src/status_im2/contexts/add_new_contact/views.cljs b/src/status_im2/contexts/add_new_contact/views.cljs index a0d84d54e1..2d0820b2a4 100644 --- a/src/status_im2/contexts/add_new_contact/views.cljs +++ b/src/status_im2/contexts/add_new_contact/views.cljs @@ -2,10 +2,9 @@ (:require [clojure.string :as string] [quo2.core :as quo] - [react-native.core :as rn] [react-native.clipboard :as clipboard] + [react-native.core :as rn] [reagent.core :as reagent] - [status-im.multiaccounts.core :as multiaccounts] [status-im.qr-scanner.core :as qr-scanner] [status-im2.contexts.add-new-contact.style :as style] [utils.debounce :as debounce] @@ -15,8 +14,8 @@ (defn found-contact [public-key] - (let [{:keys [primary-name compressed-key] - :as contact} (rf/sub [:contacts/contact-by-identity public-key])] + (let [{:keys [primary-name compressed-key]} (rf/sub [:contacts/contact-by-identity public-key]) + photo-path (rf/sub [:chats/photo-path public-key])] (when primary-name [rn/view style/found-user [quo/text (style/text-description) @@ -24,7 +23,7 @@ [rn/view (style/found-user-container) [quo/user-avatar {:full-name primary-name - :profile-picture (multiaccounts/displayed-photo contact) + :profile-picture photo-path :size :small :status-indicator? false}] [rn/view style/found-user-text diff --git a/src/status_im2/contexts/chat/composer/reply/view.cljs b/src/status_im2/contexts/chat/composer/reply/view.cljs index 883f191d97..832baa9cf3 100644 --- a/src/status_im2/contexts/chat/composer/reply/view.cljs +++ b/src/status_im2/contexts/chat/composer/reply/view.cljs @@ -1,16 +1,16 @@ (ns status-im2.contexts.chat.composer.reply.view (:require [clojure.string :as string] - [react-native.core :as rn] - [react-native.reanimated :as reanimated] - [status-im2.contexts.chat.composer.constants :as constants] - [utils.i18n :as i18n] [quo2.core :as quo] [quo2.foundations.colors :as colors] - [status-im2.constants :as constant] + [react-native.core :as rn] + [react-native.linear-gradient :as linear-gradient] + [react-native.reanimated :as reanimated] [status-im.ethereum.stateofus :as stateofus] - [utils.re-frame :as rf] + [status-im2.constants :as constant] + [status-im2.contexts.chat.composer.constants :as constants] [status-im2.contexts.chat.composer.reply.style :as style] - [react-native.linear-gradient :as linear-gradient])) + [utils.i18n :as i18n] + [utils.re-frame :as rf])) (defn get-quoted-text-with-mentions [parsed-text] @@ -63,8 +63,7 @@ (defn reply-from [{:keys [from contact-name current-public-key]}] (let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from])) - contact (rf/sub [:contacts/contact-by-address from]) - photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))] + photo-path (rf/sub [:chats/photo-path from])] [rn/view {:style style/reply-from} [quo/user-avatar {:full-name display-name diff --git a/src/status_im2/contexts/chat/home/chat_list_item/view.cljs b/src/status_im2/contexts/chat/home/chat_list_item/view.cljs index 7339750c4d..a24cdb23b8 100644 --- a/src/status_im2/contexts/chat/home/chat_list_item/view.cljs +++ b/src/status_im2/contexts/chat/home/chat_list_item/view.cljs @@ -1,16 +1,16 @@ (ns status-im2.contexts.chat.home.chat-list-item.view - (:require [quo2.core :as quo] + (:require [clojure.string :as string] + [quo2.components.icon :as icons] + [quo2.core :as quo] [quo2.foundations.colors :as colors] [react-native.core :as rn] + [status-im2.common.home.actions.view :as actions] + [status-im2.constants :as constants] + [status-im2.contexts.chat.home.chat-list-item.style :as style] [utils.datetime :as datetime] [utils.debounce :as debounce] - [status-im2.common.home.actions.view :as actions] - [status-im2.contexts.chat.home.chat-list-item.style :as style] - [utils.re-frame :as rf] - [status-im2.constants :as constants] - [clojure.string :as string] [utils.i18n :as i18n] - [quo2.components.icon :as icons])) + [utils.re-frame :as rf])) (def max-subheader-length 50) @@ -201,14 +201,14 @@ [{:keys [contact chat-id full-name color muted?]}] (if contact ; `contact` is passed when it's not a group chat (let [online? (rf/sub [:visibility-status-updates/online? chat-id]) - photo-path (rf/sub [:chats/photo-path chat-id]) - image-key (if (seq (:images contact)) :profile-picture :ring-background)] + photo-path (rf/sub [:chats/photo-path chat-id])] [quo/user-avatar - {:full-name full-name - :size :small - :online? online? - image-key photo-path - :muted? muted?}]) + (cond-> {:full-name full-name + :size :small + :online? online? + :profile-picture photo-path} + muted? + (assoc :ring? false))]) [quo/group-avatar {:customization-color color :size :small}])) diff --git a/src/status_im2/contexts/chat/messages/avatar/view.cljs b/src/status_im2/contexts/chat/messages/avatar/view.cljs index 975ff42817..864c0673db 100644 --- a/src/status_im2/contexts/chat/messages/avatar/view.cljs +++ b/src/status_im2/contexts/chat/messages/avatar/view.cljs @@ -1,21 +1,19 @@ (ns status-im2.contexts.chat.messages.avatar.view - (:require [utils.re-frame :as rf] + (:require [quo2.core :as quo] [react-native.core :as rn] - [quo2.core :as quo])) + [utils.re-frame :as rf])) (defn avatar [public-key size] (let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key])) - contact (rf/sub [:contacts/contact-by-address public-key]) - photo-path (when (seq (:images contact)) (rf/sub [:chats/photo-path public-key])) + photo-path (rf/sub [:chats/photo-path public-key]) online? (rf/sub [:visibility-status-updates/online? public-key])] [rn/view {:style {:padding-top 2}} [rn/touchable-opacity {:active-opacity 1 :on-press #(rf/dispatch [:chat.ui/show-profile public-key])} [quo/user-avatar - {:full-name display-name - :profile-picture photo-path - :status-indicator? true - :online? online? - :size size}]]])) + {:full-name display-name + :profile-picture photo-path + :online? online? + :size size}]]])) diff --git a/src/status_im2/contexts/chat/messages/content/deleted/view.cljs b/src/status_im2/contexts/chat/messages/content/deleted/view.cljs index 8bffa88b1c..8880b4b120 100644 --- a/src/status_im2/contexts/chat/messages/content/deleted/view.cljs +++ b/src/status_im2/contexts/chat/messages/content/deleted/view.cljs @@ -28,9 +28,7 @@ on-long-press-fn] (let [;; deleted message with nil deleted-by is deleted by (:from message) display-name (first (rf/sub [:contacts/contact-two-names-by-identity (or deleted-by from)])) - contact (rf/sub [:contacts/contact-by-address (or deleted-by from)]) - photo-path (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path (or deleted-by from)]))] + photo-path (rf/sub [:chats/photo-path (or deleted-by from)])] [quo/system-message {:type :deleted :timestamp timestamp-str diff --git a/src/status_im2/contexts/chat/messages/list/view.cljs b/src/status_im2/contexts/chat/messages/list/view.cljs index 8e8babcbea..925c125bce 100644 --- a/src/status_im2/contexts/chat/messages/list/view.cljs +++ b/src/status_im2/contexts/chat/messages/list/view.cljs @@ -1,24 +1,24 @@ (ns status-im2.contexts.chat.messages.list.view (:require [oops.core :as oops] [quo2.core :as quo] + [quo2.foundations.colors :as colors] [react-native.background-timer :as background-timer] [react-native.core :as rn] [react-native.hooks :as hooks] [react-native.platform :as platform] + [react-native.reanimated :as reanimated] [react-native.safe-area :as safe-area] [reagent.core :as reagent] - [quo2.foundations.colors :as colors] - [react-native.reanimated :as reanimated] [status-im.ui.screens.chat.group :as chat.group] [status-im.ui.screens.chat.message.gap :as message.gap] [status-im2.constants :as constants] + [status-im2.contexts.chat.composer.constants :as composer.constants] [status-im2.contexts.chat.messages.content.view :as message] [status-im2.contexts.chat.messages.list.state :as state] [status-im2.contexts.chat.messages.list.style :as style] [status-im2.contexts.chat.messages.navigation.style :as navigation.style] - [status-im2.contexts.chat.composer.constants :as composer.constants] - [utils.re-frame :as rf] - [utils.i18n :as i18n])) + [utils.i18n :as i18n] + [utils.re-frame :as rf])) (defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75) (defonce ^:const loading-indicator-extra-spacing 250) @@ -203,8 +203,7 @@ online? (rf/sub [:visibility-status-updates/online? chat-id]) contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id])) - photo-path (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path chat-id])) + photo-path (rf/sub [:chats/photo-path chat-id]) border-animation (reanimated/interpolate scroll-y [30 125] [14 0] diff --git a/src/status_im2/contexts/chat/messages/navigation/view.cljs b/src/status_im2/contexts/chat/messages/navigation/view.cljs index f9113c7c8d..367606c1f0 100644 --- a/src/status_im2/contexts/chat/messages/navigation/view.cljs +++ b/src/status_im2/contexts/chat/messages/navigation/view.cljs @@ -5,15 +5,15 @@ [re-frame.db] [react-native.blur :as blur] [react-native.core :as rn] - [status-im2.config :as config] - [react-native.reanimated :as reanimated] [react-native.platform :as platform] + [react-native.reanimated :as reanimated] + [status-im2.common.home.actions.view :as actions] + [status-im2.config :as config] + [status-im2.constants :as constants] [status-im2.contexts.chat.messages.navigation.style :as style] [status-im2.contexts.chat.messages.pin.banner.view :as pin.banner] - [status-im2.constants :as constants] - [utils.re-frame :as rf] [utils.i18n :as i18n] - [status-im2.common.home.actions.view :as actions])) + [utils.re-frame :as rf])) (defn f-view [{:keys [scroll-y]}] @@ -27,10 +27,7 @@ (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) (str emoji " " chat-name)) online? (rf/sub [:visibility-status-updates/online? chat-id]) - contact (when-not group-chat - (rf/sub [:contacts/contact-by-address chat-id])) - photo-path (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path chat-id])) + photo-path (rf/sub [:chats/photo-path chat-id]) opacity-animation (reanimated/interpolate scroll-y [style/navigation-bar-height (+ style/navigation-bar-height 30)] diff --git a/src/status_im2/contexts/contacts/drawers/nickname_drawer/view.cljs b/src/status_im2/contexts/contacts/drawers/nickname_drawer/view.cljs index 74f2cb7ca8..1fcf1aa60d 100644 --- a/src/status_im2/contexts/contacts/drawers/nickname_drawer/view.cljs +++ b/src/status_im2/contexts/contacts/drawers/nickname_drawer/view.cljs @@ -1,8 +1,8 @@ (ns status-im2.contexts.contacts.drawers.nickname-drawer.view (:require [clojure.string :as string] - [quo2.foundations.colors :as colors] [quo2.components.icon :as icons] [quo2.core :as quo] + [quo2.foundations.colors :as colors] [react-native.core :as rn] [react-native.safe-area :as safe-area] [reagent.core :as reagent] @@ -28,8 +28,7 @@ [{:keys [contact]}] (let [{:keys [primary-name nickname public-key]} contact entered-nickname (reagent/atom (or nickname "")) - photo-path (when-not (empty? (:images contact)) - (rf/sub [:chats/photo-path public-key])) + photo-path (rf/sub [:chats/photo-path public-key]) insets (safe-area/get-insets)] (fn [{:keys [title description accessibility-label close-button-text]}] @@ -41,10 +40,10 @@ :size :heading-1} title] [rn/view {:style (style/context-container)} [quo/user-avatar - {:full-name primary-name - :profile-picture photo-path - :size :xxs - :status-indicator false}] + {:full-name primary-name + :profile-picture photo-path + :size :xxs + :status-indicator? false}] [quo/text {:weight :medium :size :paragraph-2 diff --git a/src/status_im2/contexts/onboarding/create_profile/view.cljs b/src/status_im2/contexts/onboarding/create_profile/view.cljs index 64853cd975..b06d5c2f27 100644 --- a/src/status_im2/contexts/onboarding/create_profile/view.cljs +++ b/src/status_im2/contexts/onboarding/create_profile/view.cljs @@ -1,20 +1,20 @@ (ns status-im2.contexts.onboarding.create-profile.view - (:require [quo2.core :as quo] - [clojure.string :as string] + (:require [clojure.string :as string] + [oops.core :as oops] + [quo2.core :as quo] [quo2.foundations.colors :as colors] - [status-im2.contexts.onboarding.create-profile.style :as style] - [utils.i18n :as i18n] + [react-native.blur :as blur] [react-native.core :as rn] + [react-native.platform :as platform] [react-native.safe-area :as safe-area] [react-native.hooks :as hooks] [reagent.core :as reagent] - [status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar] - [status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu] - [utils.re-frame :as rf] - [oops.core :as oops] - [react-native.blur :as blur] [status-im2.constants :as c] - [react-native.platform :as platform])) + [status-im2.contexts.onboarding.common.navigation-bar.view :as navigation-bar] + [status-im2.contexts.onboarding.create-profile.style :as style] + [status-im2.contexts.onboarding.select-photo.method-menu.view :as method-menu] + [utils.i18n :as i18n] + [utils.re-frame :as rf])) ;; NOTE - validation should match with Desktop ;; https://github.com/status-im/status-desktop/blob/2ba96803168461088346bf5030df750cb226df4c/ui/imports/utils/Constants.qml#L468 @@ -162,9 +162,12 @@ [:show-bottom-sheet {:content (fn [] - [method-menu/view on-change-profile-pic]) - :theme :dark}])) - :image-picker-props {:profile-picture (when @profile-pic {:uri @profile-pic}) + [method-menu/view on-change-profile-pic])}])) + :image-picker-props {:profile-picture (or + @profile-pic + (rf/sub + [:profile/onboarding-placeholder-avatar + @profile-pic])) :full-name (if (seq @full-name) @full-name (i18n/label :t/your-name)) diff --git a/src/status_im2/contexts/onboarding/identifiers/profile_card/style.cljs b/src/status_im2/contexts/onboarding/identifiers/profile_card/style.cljs index 5a50e09d66..857a42147f 100644 --- a/src/status_im2/contexts/onboarding/identifiers/profile_card/style.cljs +++ b/src/status_im2/contexts/onboarding/identifiers/profile_card/style.cljs @@ -1,7 +1,7 @@ (ns status-im2.contexts.onboarding.identifiers.profile-card.style (:require [quo2.foundations.colors :as colors] - [react-native.reanimated :as reanimated] - [quo2.foundations.typography :as typography])) + [quo2.foundations.typography :as typography] + [react-native.reanimated :as reanimated])) (def card-view {:margin-horizontal 20 @@ -36,7 +36,7 @@ :background-color :transparent :height 48 :border-color :black - :border-width 2 + :border-width 3 :border-radius 44})) (def picture-avatar-mask diff --git a/src/status_im2/contexts/onboarding/identifiers/profile_card/view.cljs b/src/status_im2/contexts/onboarding/identifiers/profile_card/view.cljs index c0d89e7bd6..340fde8111 100644 --- a/src/status_im2/contexts/onboarding/identifiers/profile_card/view.cljs +++ b/src/status_im2/contexts/onboarding/identifiers/profile_card/view.cljs @@ -1,12 +1,12 @@ (ns status-im2.contexts.onboarding.identifiers.profile-card.view - (:require [react-native.core :as rn] - [react-native.reanimated :as reanimated] - [react-native.masked-view :as masked-view] - [reagent.core :as reagent] - [quo2.core :as quo] + (:require [quo2.core :as quo] [quo2.foundations.colors :as colors] - [utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting] - [status-im2.contexts.onboarding.identifiers.profile-card.style :as style])) + [react-native.core :as rn] + [react-native.masked-view :as masked-view] + [react-native.reanimated :as reanimated] + [reagent.core :as reagent] + [status-im2.contexts.onboarding.identifiers.profile-card.style :as style] + [utils.worklets.identifiers-highlighting :as worklets.identifiers-highlighting])) (defn- f-profile-card-component [{:keys [profile-picture name hash emoji-hash @@ -20,29 +20,24 @@ ring-opacity (worklets.identifiers-highlighting/ring-opacity @progress) user-hash-color (worklets.identifiers-highlighting/user-hash-color @progress) user-hash-opacity (worklets.identifiers-highlighting/user-hash-opacity @progress) - emoji-hash-style (worklets.identifiers-highlighting/emoji-hash-style @progress)] + emoji-hash-style (worklets.identifiers-highlighting/emoji-hash-style @progress) + avatar [quo/user-avatar + {:full-name name + :profile-picture profile-picture + :size :medium + :status-indicator? false + :customization-color customization-color}]] [rn/view {:style style/card-view} [reanimated/view {:style (style/card-container container-background)} [rn/view {:style style/card-header} - [reanimated/view - {:style (style/avatar avatar-opacity)} - [quo/user-avatar - {:full-name name - :profile-picture profile-picture - :size :medium - :status-indicator? false - :customization-color customization-color}]] + [reanimated/view {:style (style/avatar avatar-opacity)} avatar] [masked-view/masked-view {:style {:position :absolute} :mask-element (reagent/as-element [reanimated/view {:style (style/mask-view ring-opacity)}])} - (when profile-picture - [rn/image - {:accessibility-label :ring-background - :style style/picture-avatar-mask - :source profile-picture}])]] + (when profile-picture avatar)]] [reanimated/view {:style (style/user-name-container opacity)} [quo/text diff --git a/src/status_im2/contexts/profile/profiles/view.cljs b/src/status_im2/contexts/profile/profiles/view.cljs index d7e0ff9fa2..7cfd64b6a1 100644 --- a/src/status_im2/contexts/profile/profiles/view.cljs +++ b/src/status_im2/contexts/profile/profiles/view.cljs @@ -111,7 +111,7 @@ :customization-color (or customization-color :primary) :keycard-account? keycard-pairing :show-options-button? true - :profile-picture (when profile-picture {:uri profile-picture}) + :profile-picture profile-picture :card-style (style/profiles-profile-card last-item?) :on-options-press #(show-profile-options key-uid @@ -257,7 +257,7 @@ [quo/profile-card {:name name :customization-color (or customization-color :primary) - :profile-picture (when profile-picture {:uri profile-picture}) + :profile-picture profile-picture :card-style style/login-profile-card}] [quo/input {:type :password diff --git a/src/status_im2/contexts/profile/rpc.cljs b/src/status_im2/contexts/profile/rpc.cljs index b53045b11f..074379434d 100644 --- a/src/status_im2/contexts/profile/rpc.cljs +++ b/src/status_im2/contexts/profile/rpc.cljs @@ -1,9 +1,11 @@ (ns status-im2.contexts.profile.rpc - (:require [clojure.string :as string])) + (:require [clojure.string :as string] + [status-im.ethereum.ens :as ens])) (defn rpc->profiles-overview [{:keys [customizationColor keycard-pairing] :as profile}] (-> profile (dissoc :customizationColor) (assoc :customization-color (keyword customizationColor)) + (assoc :ens-name? (ens/is-valid-eth-name? (:name profile))) (assoc :keycard-pairing (when-not (string/blank? keycard-pairing) keycard-pairing)))) diff --git a/src/status_im2/contexts/quo_preview/avatars/user_avatar.cljs b/src/status_im2/contexts/quo_preview/avatars/user_avatar.cljs index e1a84206a6..5227c16d3f 100644 --- a/src/status_im2/contexts/quo_preview/avatars/user_avatar.cljs +++ b/src/status_im2/contexts/quo_preview/avatars/user_avatar.cljs @@ -67,12 +67,7 @@ {:padding-vertical 60 :flex-direction :row :justify-content :center} - (let [{:keys [profile-picture ring?]} @state - ring-bg (resources/get-mock-image :ring) - params (cond-> @state - (and (not profile-picture) ring?) - (assoc :ring-background ring-bg))] - [quo2/user-avatar params])]]]))) + [quo2/user-avatar @state]]]]))) (defn preview-user-avatar [] diff --git a/src/status_im2/contexts/quo_preview/notifications/notification.cljs b/src/status_im2/contexts/quo_preview/notifications/notification.cljs index 68ef47feb0..7373cdaf2c 100644 --- a/src/status_im2/contexts/quo_preview/notifications/notification.cljs +++ b/src/status_im2/contexts/quo_preview/notifications/notification.cljs @@ -1,7 +1,6 @@ (ns status-im2.contexts.quo-preview.notifications.notification (:require [quo2.core :as quo] [react-native.core :as rn] - [status-im2.common.resources :as resources] [status-im2.contexts.quo-preview.code.snippet :as snippet-preview] [utils.re-frame :as rf])) @@ -34,8 +33,7 @@ :status-indicator? true :online? true :size :small - :customization-color :blue - :ring-background (resources/get-mock-image :ring)}] + :customization-color :blue}] :title "Alisher Yakupov accepted your contact request" :duration 4000 :title-weight :medium @@ -50,8 +48,7 @@ :status-indicator? true :online? true :size :small - :customization-color :blue - :ring-background (resources/get-mock-image :ring)}] + :customization-color :blue}] :title "Default to semibold title" :text "The quick brown fox jumped over the lazy dog and ate a potatoe." :duration 4000 @@ -66,8 +63,7 @@ :status-indicator? true :online? true :size :small - :customization-color :blue - :ring-background (resources/get-mock-image :ring)}] + :customization-color :blue}] :header [rn/view [quo/info-message {:type :success diff --git a/src/status_im2/contexts/shell/activity_center/events.cljs b/src/status_im2/contexts/shell/activity_center/events.cljs index 669a6db61f..940ee0ed46 100644 --- a/src/status_im2/contexts/shell/activity_center/events.cljs +++ b/src/status_im2/contexts/shell/activity_center/events.cljs @@ -4,8 +4,8 @@ [status-im.data-store.chats :as data-store.chats] [status-im2.common.toasts.events :as toasts] [status-im2.constants :as constants] - [status-im2.contexts.shell.activity-center.notification-types :as types] [status-im2.contexts.chat.events :as chat.events] + [status-im2.contexts.shell.activity-center.notification-types :as types] [taoensso.timbre :as log] [utils.collection :as collection] [utils.i18n :as i18n] @@ -502,33 +502,35 @@ {:events [:activity-center.notifications/show-toasts]} [{:keys [db]} new-notifications] (let [my-public-key (get-in db [:profile/profile :public-key])] - (reduce (fn [cofx {:keys [author type accepted dismissed message name] :as x}] + (reduce (fn [cofx {:keys [author chat-id type accepted dismissed message name] :as x}] (let [user-avatar {:full-name name :status-indicator? true :online? nil :size :small - :ring? false}] + :ring? true}] (cond (and (not= author my-public-key) (= type types/contact-request) (not accepted) (not dismissed)) (toasts/upsert cofx - {:user user-avatar - :icon-color colors/primary-50-opa-40 - :title (i18n/label :t/contact-request-sent-toast - {:name name}) - :text (get-in message [:content :text])}) + {:user user-avatar + :user-public-key author + :icon-color colors/primary-50-opa-40 + :title (i18n/label :t/contact-request-sent-toast + {:name name}) + :text (get-in message [:content :text])}) (and (= author my-public-key) ;; we show it for user who sent the request (= type types/contact-request) accepted (not dismissed)) (toasts/upsert cofx - {:user user-avatar - :icon-color colors/success-50-opa-40 - :title (i18n/label :t/contact-request-accepted-toast - {:name (or name (:alias message))})}) + {:user user-avatar + :user-public-key chat-id ;; user public key who accepted the request + :icon-color colors/success-50-opa-40 + :title (i18n/label :t/contact-request-accepted-toast + {:name (or name (:alias message))})}) :else cofx))) {:db db} diff --git a/src/status_im2/contexts/shell/activity_center/notification/common/view.cljs b/src/status_im2/contexts/shell/activity_center/notification/common/view.cljs index 8a3de887b2..299b1bfe22 100644 --- a/src/status_im2/contexts/shell/activity_center/notification/common/view.cljs +++ b/src/status_im2/contexts/shell/activity_center/notification/common/view.cljs @@ -1,8 +1,8 @@ (ns status-im2.contexts.shell.activity-center.notification.common.view (:require [quo2.core :as quo] + [quo2.foundations.colors :as colors] [react-native.core :as rn] [react-native.gesture :as gesture] - [quo2.foundations.colors :as colors] [status-im.multiaccounts.core :as multiaccounts] [status-im2.contexts.shell.activity-center.notification.common.style :as style] [utils.i18n :as i18n] @@ -22,7 +22,8 @@ {:color :purple :size :small :style style/user-avatar-tag - :text-style style/user-avatar-tag-text} + :text-style style/user-avatar-tag-text + :ring? false} primary-name (multiaccounts/displayed-photo contact)])) diff --git a/src/status_im2/events.cljs b/src/status_im2/events.cljs index c152c6ab20..c061358c59 100644 --- a/src/status_im2/events.cljs +++ b/src/status_im2/events.cljs @@ -1,20 +1,21 @@ (ns status-im2.events - (:require [status-im2.common.json-rpc.events] + (:require [status-im.bottom-sheet.events] + [status-im.keycard.core :as keycard] + status-im2.common.font + [status-im2.common.json-rpc.events] + status-im2.common.password-authentication.events + status-im2.common.theme.events [status-im2.common.toasts.events] [status-im2.contexts.add-new-contact.events] + status-im2.contexts.chat.events + status-im2.contexts.chat.photo-selector.events + status-im2.contexts.communities.overview.events status-im2.contexts.onboarding.events - [status-im.bottom-sheet.events] - [status-im2.db :as db] - [utils.re-frame :as rf] + status-im2.contexts.profile.events status-im2.contexts.shell.share.events status-im2.contexts.syncing.events - status-im2.contexts.chat.events - status-im2.common.password-authentication.events - status-im2.contexts.communities.overview.events - status-im2.contexts.chat.photo-selector.events - status-im2.common.theme.events - status-im2.contexts.profile.events - [status-im.keycard.core :as keycard])) + [status-im2.db :as db] + [utils.re-frame :as rf])) (rf/defn start-app {:events [:app-started]} @@ -26,5 +27,7 @@ :biometric/get-supported-biometric-type nil ;;app starting flow continues in get-profiles-overview :profile/get-profiles-overview #(rf/dispatch - [:profile/get-profiles-overview-success %])} + [:profile/get-profiles-overview-success %]) + :font/get-font-file-for-initials-avatar #(rf/dispatch + [:font/init-font-file-for-initials-avatar %])} (keycard/init))) diff --git a/src/status_im2/subs/chat/chats.cljs b/src/status_im2/subs/chat/chats.cljs index 08f6f69e5b..fadd7065c7 100644 --- a/src/status_im2/subs/chat/chats.cljs +++ b/src/status_im2/subs/chat/chats.cljs @@ -2,9 +2,9 @@ (:require [clojure.string :as string] [re-frame.core :as re-frame] [status-im.communities.core :as communities] + [status-im.contact.core :as contact] [status-im.group-chats.core :as group-chat] [status-im.group-chats.db :as group-chats.db] - [status-im.multiaccounts.core :as multiaccounts] [status-im2.constants :as constants] [status-im2.contexts.chat.composer.constants :as composer.constants] [status-im2.contexts.chat.events :as chat.events])) @@ -298,10 +298,9 @@ :chats/photo-path :<- [:contacts/contacts] :<- [:profile/multiaccount] - :<- [:mediaserver/port] (fn [[contacts {:keys [public-key] :as multiaccount}] [_ id]] - (multiaccounts/displayed-photo (or (when (= id public-key) multiaccount) - (get contacts id))))) + (let [contact (or (when (= id public-key) multiaccount) (get contacts id))] + (contact/displayed-photo contact)))) (re-frame/reg-sub :chats/unread-messages-number diff --git a/src/status_im2/subs/contact.cljs b/src/status_im2/subs/contact.cljs index e3a1c96bd0..4e72398244 100644 --- a/src/status_im2/subs/contact.cljs +++ b/src/status_im2/subs/contact.cljs @@ -1,16 +1,16 @@ (ns status-im2.subs.contact (:require [clojure.string :as string] - [utils.i18n :as i18n] + [quo2.theme :as theme] [re-frame.core :as re-frame] [status-im.contact.db :as contact.db] [status-im.ethereum.core :as ethereum] [status-im.multiaccounts.core :as multiaccounts] [status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils] [status-im.utils.gfycat.core :as gfycat] - [utils.image-server :as image-server] - [utils.collection] [status-im2.constants :as constants] - [quo2.theme :as theme])) + [utils.collection] + [utils.i18n :as i18n] + [utils.image-server :as image-server])) (re-frame/reg-sub ::query-current-chat-contacts @@ -32,28 +32,42 @@ (get multiaccount :profile-pictures-visibility))) (defn- replace-contact-image-uri - [contact port contact-identity] - (let [theme (theme/get-theme) - contact-images (:images contact) - contact-images (reduce (fn [acc image] - (let [image-name (:type image) - ; We pass the clock so that we reload the image if the image - ; is updated - clock (:clock image) - uri (image-server/get-contact-image-uri port - contact-identity - image-name - clock - theme)] - (assoc-in acc [(keyword image-name) :uri] uri))) - contact-images - (vals contact-images))] - (assoc contact :images contact-images))) + [contact port public-key font-file] + (let [theme (theme/get-theme) + {:keys [images ens-name]} contact + images + (reduce (fn [acc image] + (let [image-name (:type image) + clock (:clock image) + uri (image-server/get-contact-image-uri-fn + {:port port + :public-key public-key + :image-name image-name + ; We pass the clock so that we reload the + ; image if the image is updated + :clock clock + :theme theme + :override-ring? (when ens-name false)})] + (assoc-in acc [(keyword image-name) :fn] uri))) + images + (vals images)) + + images (if (seq images) + images + {:thumbnail + {:fn (image-server/get-initials-avatar-uri-fn + {:port port + :public-key public-key + :override-ring? (when ens-name false) + :theme theme + :font-file font-file})}})] + + (assoc contact :images images))) (defn- reduce-contacts-image-uri - [contacts port] + [contacts port font-file] (reduce-kv (fn [acc public-key contact] - (let [contact (replace-contact-image-uri contact port public-key)] + (let [contact (replace-contact-image-uri contact port public-key font-file)] (assoc acc public-key contact))) {} contacts)) @@ -64,9 +78,10 @@ :<- [::profile-pictures-visibility] :<- [:multiaccount/public-key] :<- [:mediaserver/port] - (fn [[contacts profile-pictures-visibility public-key port]] + :<- [:initials-avatar-font-file] + (fn [[contacts profile-pictures-visibility public-key port font-file]] (let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)] - (reduce-contacts-image-uri contacts port)))) + (reduce-contacts-image-uri contacts port font-file)))) (re-frame/reg-sub :contacts/active @@ -175,10 +190,10 @@ contacts))))) (defn- enrich-contact - [_ contact-identity ens-name port] + [_ contact-identity ens-name port font-file] (let [contact (contact.db/enrich-contact (contact.db/public-key-and-ens-name->new-contact contact-identity ens-name))] - (replace-contact-image-uri contact port contact-identity))) + (replace-contact-image-uri contact port contact-identity font-file))) (re-frame/reg-sub :contacts/current-contact @@ -186,11 +201,12 @@ :<- [:contacts/current-contact-identity] :<- [:contacts/current-contact-ens-name] :<- [:mediaserver/port] - (fn [[contacts contact-identity ens-name port]] + :<- [:initials-avatar-font-file] + (fn [[contacts contact-identity ens-name port font-file]] (let [contact (get contacts contact-identity)] (cond-> contact (nil? contact) - (enrich-contact contact-identity ens-name port))))) + (enrich-contact contact-identity ens-name port font-file))))) (re-frame/reg-sub :contacts/contact-by-identity diff --git a/src/status_im2/subs/contact_test.cljs b/src/status_im2/subs/contact_test.cljs index 53af2c1f4f..e73cbeeac4 100644 --- a/src/status_im2/subs/contact_test.cljs +++ b/src/status_im2/subs/contact_test.cljs @@ -1,8 +1,8 @@ (ns status-im2.subs.contact-test (:require [cljs.test :refer [is testing]] [re-frame.db :as rf-db] - [test-helpers.unit :as h] status-im2.subs.contact + [test-helpers.unit :as h] [utils.re-frame :as rf])) (def contacts-sample-data @@ -74,14 +74,13 @@ :has-added-us? true :contact-request-state 1}}}) -(def expected-sorted-contacts +(def expected-sorted-contacts-without-images [{:title "F" :data [{:active? true :last-updated 1672582629695 :mutual? true :blocked? false :contactRequestClock 0 - :images {} :added? true :name "slim.shady" :primary-name "fslim.shady" @@ -105,7 +104,6 @@ :mutual? true :blocked? false :contactRequestClock 0 - :images {} :added? true :name "slim.shady" :primary-name "islim.shady" @@ -129,7 +127,6 @@ :mutual? true :blocked? false :contactRequestClock 0 - :images {} :added? true :name "slim.shady" :primary-name "rslim.shady" @@ -148,6 +145,10 @@ :has-added-us? true :contact-request-state 1}]}]) +(defn remove-contact-images + [{:keys [data] :as contact}] + (assoc contact :data (mapv #(dissoc % :images) data))) + (h/deftest-sub :contacts/sorted-and-grouped-by-first-letter [sub-name] (testing "Returning empty sequence when no contacts" @@ -170,4 +171,5 @@ (dissoc contact :identicon)) %))) (rf/sub [sub-name]))] - (is (= expected-sorted-contacts contact-list-without-identicons))))) + (is (= expected-sorted-contacts-without-images + (mapv remove-contact-images contact-list-without-identicons)))))) diff --git a/src/status_im2/subs/profile.cljs b/src/status_im2/subs/profile.cljs index e74d0f06c6..40d721995f 100644 --- a/src/status_im2/subs/profile.cljs +++ b/src/status_im2/subs/profile.cljs @@ -6,9 +6,9 @@ [status-im.ethereum.core :as ethereum] [status-im.fleet.core :as fleet] [status-im.multiaccounts.db :as multiaccounts.db] + [status-im2.constants :as constants] [utils.image-server :as image-server] - [utils.security.core :as security] - [status-im2.constants :as constants])) + [utils.security.core :as security])) (re-frame/reg-sub :profile/customization-color @@ -16,21 +16,44 @@ (fn [{:keys [customization-color]}] (or customization-color constants/profile-default-color))) +(re-frame/reg-sub + :profile/onboarding-placeholder-avatar + :<- [:mediaserver/port] + :<- [:initials-avatar-font-file] + (fn [[port font-file] [_ profile-pic]] + {:fn + (if profile-pic + (image-server/get-account-image-uri-fn {:port port + :image-name profile-pic + :override-ring? false + :theme (theme/get-theme)}) + (image-server/get-initials-avatar-uri-fn {:port port + :theme (theme/get-theme) + :override-ring? false + :font-file font-file}))})) + (re-frame/reg-sub :profile/login-profiles-picture :<- [:profile/profiles-overview] :<- [:mediaserver/port] - (fn [[multiaccounts port] [_ target-key-uid]] - (let [image-name (-> multiaccounts - (get-in [target-key-uid :images]) - first - :type)] - (when image-name - (image-server/get-account-image-uri {:port port - :image-name image-name - :key-uid target-key-uid - :theme (theme/get-theme) - :ring? true}))))) + :<- [:initials-avatar-font-file] + (fn [[multiaccounts port font-file] [_ target-key-uid]] + (let [{:keys [images ens-name?] :as multiaccount} (get multiaccounts target-key-uid) + image-name (-> images first :type) + override-ring? (not ens-name?)] + (when multiaccount + {:fn + (if image-name + (image-server/get-account-image-uri-fn {:port port + :image-name image-name + :key-uid target-key-uid + :theme (theme/get-theme) + :override-ring? override-ring?}) + (image-server/get-initials-avatar-uri-fn {:port port + :key-uid target-key-uid + :theme (theme/get-theme) + :override-ring? override-ring? + :font-file font-file}))})))) (re-frame/reg-sub :multiaccount/public-key @@ -224,30 +247,36 @@ (pos? (count (get multiaccount :images))))) (defn- replace-multiaccount-image-uri - [multiaccount port] - (let [public-key (:public-key multiaccount) - theme (theme/get-theme) - images (:images multiaccount) - images (reduce (fn [acc current] - (let [key-uid (:keyUid current) - image-name (:type current) - uri (image-server/get-account-image-uri {:port port - :public-key public-key - :image-name image-name - :key-uid key-uid - :theme theme - :ring? true})] - (conj acc (assoc current :uri uri)))) - [] - images)] - (assoc multiaccount :images images))) + [multiaccount port font-file avatar-opts] + (let [{:keys [key-uid ens-name? images]} multiaccount + theme (theme/get-theme) + avatar-opts (assoc avatar-opts :override-ring? (when ens-name? false)) + images-with-uri (mapv (fn [{key-uid :keyUid image-name :type :as image}] + (let [uri-fn (image-server/get-account-image-uri-fn + (merge {:port port + :image-name image-name + :key-uid key-uid + :theme theme} + avatar-opts))] + (assoc image :fn uri-fn))) + images) + new-images (if (seq images-with-uri) + images-with-uri + [{:fn (image-server/get-initials-avatar-uri-fn + (merge {:port port + :key-uid key-uid + :theme theme + :font-file font-file} + avatar-opts))}])] + (assoc multiaccount :images new-images))) (re-frame/reg-sub :profile/multiaccount :<- [:profile/profile] :<- [:mediaserver/port] - (fn [[multiaccount port]] - (replace-multiaccount-image-uri multiaccount port))) + :<- [:initials-avatar-font-file] + (fn [[multiaccount port font-file] [_ avatar-opts]] + (replace-multiaccount-image-uri multiaccount port font-file avatar-opts))) (re-frame/reg-sub :profile/login-profile diff --git a/src/status_im2/subs/root.cljs b/src/status_im2/subs/root.cljs index 583db44202..dc0dcc8bde 100644 --- a/src/status_im2/subs/root.cljs +++ b/src/status_im2/subs/root.cljs @@ -75,6 +75,7 @@ (reg-root-key-sub :password-authentication :password-authentication) (reg-root-key-sub :shell/floating-screens :shell/floating-screens) (reg-root-key-sub :shell/loaded-screens :shell/loaded-screens) +(reg-root-key-sub :initials-avatar-font-file :initials-avatar-font-file) ;;NOTE this one is not related to ethereum network ;; it is about cellular network/ wifi network diff --git a/src/status_im2/subs/shell.cljs b/src/status_im2/subs/shell.cljs index 309d564dee..d667c80f3f 100644 --- a/src/status_im2/subs/shell.cljs +++ b/src/status_im2/subs/shell.cljs @@ -1,12 +1,12 @@ (ns status-im2.subs.shell - (:require [utils.i18n :as i18n] - [re-frame.core :as re-frame] - [utils.datetime :as datetime] + (:require [re-frame.core :as re-frame] + [status-im.multiaccounts.core :as multiaccounts] + [status-im2.common.resources :as resources] [status-im2.config :as config] [status-im2.constants :as constants] - [status-im2.common.resources :as resources] - [status-im.multiaccounts.core :as multiaccounts] - [status-im2.contexts.shell.jump-to.constants :as shell.constants])) + [status-im2.contexts.shell.jump-to.constants :as shell.constants] + [utils.datetime :as datetime] + [utils.i18n :as i18n])) ;; Helper Functions (defn community-avatar @@ -79,13 +79,11 @@ :counter-label (:unviewed-mentions-count chat)}))) (defn one-to-one-chat-card - [contact names chat id communities] - (let [images (:images contact) - profile-picture (:uri (or (:thumbnail images) (:large images) (first images)))] - {:title (first names) - :avatar-params {:full-name (first names) - :profile-picture (when profile-picture - (str profile-picture "&addRing=0"))} + [contact names profile-picture chat id communities] + (let [display-name (first names)] + {:title display-name + :avatar-params {:full-name display-name + :profile-picture profile-picture} :customization-color (or (:customization-color contact) :primary) :content (get-card-content {:chat chat @@ -151,10 +149,16 @@ (fn [[_ id] _] [(re-frame/subscribe [:contacts/contact-by-identity id]) (re-frame/subscribe [:contacts/contact-two-names-by-identity id]) + (re-frame/subscribe [:chats/photo-path id]) (re-frame/subscribe [:chats/chat id]) (re-frame/subscribe [:communities])]) - (fn [[contact names chat communities] [_ id]] - (one-to-one-chat-card contact names chat id communities))) + (fn [[contact names profile-picture chat communities] [_ id]] + (one-to-one-chat-card contact + names + profile-picture + chat + id + communities))) (re-frame/reg-sub :shell/private-group-chat-card diff --git a/src/utils/image_server.cljs b/src/utils/image_server.cljs index 1fc5bdeadb..7077f82386 100644 --- a/src/utils/image_server.cljs +++ b/src/utils/image_server.cljs @@ -1,13 +1,43 @@ (ns utils.image-server - (:require [utils.datetime :as datetime])) + (:require + [react-native.fs :as utils.fs] + [react-native.platform :as platform] + status-im.utils.pixel-ratio + [status-im2.constants :as constants] + [utils.datetime :as datetime])) (def ^:const image-server-uri-prefix "https://localhost:") (def ^:const account-images-action "/accountImages") +(def ^:const account-initials-action "/accountInitials") (def ^:const contact-images-action "/contactImages") (def ^:const generate-qr-action "/GenerateQRCode") (def ^:const status-profile-base-url "https://join.status.im/u/") (def ^:const status-profile-base-url-without-https "join.status.im/u/") +(defn get-font-file-ready + "setup font file and get the absolute path to it + this font file is passed to status-go later to render the initials avatar + + for ios, it's located at main-bundle-path + for android, it's located in the assets dir which can not be accessed by status-go + so we copy one to the cache directory" + [callback] + (if platform/android? + (let [cache-dir (utils.fs/cache-dir) + font-file-name (:android constants/initials-avatar-font-conf) + src (str "fonts/" font-file-name) + dest (str cache-dir "/" font-file-name) + copy #(utils.fs/copy-assets src dest) + cb #(callback dest)] + (.then (utils.fs/file-exists? dest) + (fn [exists?] + (if exists? + (cb) + (.then (copy) cb))))) + (callback (str (utils.fs/main-bundle-path) + "/" + (:ios constants/initials-avatar-font-conf))))) + (defn timestamp [] (datetime/timestamp)) (defn current-theme-index @@ -26,7 +56,22 @@ 4)) (defn get-account-image-uri - [{:keys [port public-key image-name key-uid theme ring?]}] + "fn to get the avatar uri when multiaccount has custom image set + not directly called, check `get-account-image-uri-fn` + + color formats (for all color options): + #RRGGBB + #RRGGBBAA + rgb(255,255,255) + rgba(255,255,255,0.1) note alpha is 0-1 + + non-placeholder-avatar: requires at least one of `public-key` or `key-uid` + placeholder-avatar: pass image file path as `image-name` + + `indicator-size` is outer indicator radius + `indicator-size` - `indicator-border` is inner indicator radius" + [{:keys [port public-key image-name key-uid size theme indicator-size + indicator-border indicator-color ring?]}] (str image-server-uri-prefix port account-images-action @@ -36,15 +81,130 @@ key-uid "&imageName=" image-name + "&size=" + (Math/round (* size status-im.utils.pixel-ratio/ratio)) "&theme=" (current-theme-index theme) "&clock=" (timestamp) + "&indicatorColor=" + (js/encodeURIComponent indicator-color) + "&indicatorSize=" + (* indicator-size status-im.utils.pixel-ratio/ratio) + "&indicatorBorder=" + (* indicator-border status-im.utils.pixel-ratio/ratio) "&addRing=" (if ring? 1 0))) +(defn get-account-image-uri-fn + "pass the result fn to user-avatar component as `:profile-picture` + + use this fn in subs to set multiaccount `:images` as [{:fn ...}] + pass the image to user-avatar + user-avatar can fill the rest style related options + + set `override-ring?` to a non-nil value to override `ring?`, mainly used to + hide ring for account with ens name + + check `get-account-image-uri` for color formats" + [{:keys [port public-key key-uid image-name theme override-ring?]}] + (fn [{:keys [size indicator-size indicator-border indicator-color ring? + override-theme]}] + (get-account-image-uri + {:port port + :image-name image-name + :size size + :public-key public-key + :key-uid key-uid + :theme (if (nil? override-theme) theme override-theme) + :indicator-size indicator-size + :indicator-border indicator-border + :indicator-color indicator-color + :ring? (if (nil? override-ring?) ring? override-ring?)}))) + +(defn get-initials-avatar-uri + "fn to get the avatar uri when account/contact/placeholder has no custom pic set + not directly called, check `get-account-initials-uri-fn` + + multiaccount: at least one of `key-uid`, `public-key` is required to render the ring + contact: `public-key` is required to render the ring + + check `get-account-image-uri` for color formats + check `get-font-file-ready` for `font-file` + + `uppercase-ratio` is the uppercase-height/line-height for `font-file`" + [{:keys [port public-key key-uid theme ring? length size background-color color + font-size font-file uppercase-ratio indicator-size indicator-border + indicator-color full-name]}] + (str + image-server-uri-prefix + port + account-initials-action + "?publicKey=" + public-key + "&keyUid=" + key-uid + "&length=" + length + "&size=" + (Math/round (* size status-im.utils.pixel-ratio/ratio)) + "&bgColor=" + (js/encodeURIComponent background-color) + "&color=" + (js/encodeURIComponent color) + "&fontSize=" + (* font-size status-im.utils.pixel-ratio/ratio) + "&fontFile=" + (js/encodeURIComponent font-file) + "&uppercaseRatio=" + uppercase-ratio + "&theme=" + (current-theme-index theme) + "&clock=" + "&name=" + (js/encodeURIComponent full-name) + (timestamp) + "&indicatorColor=" + (js/encodeURIComponent indicator-color) + "&indicatorSize=" + (* indicator-size status-im.utils.pixel-ratio/ratio) + "&indicatorBorder=" + (* indicator-border status-im.utils.pixel-ratio/ratio) + "&addRing=" + (if ring? 1 0))) + +(defn get-initials-avatar-uri-fn + "return a fn that calls `get-account-initials-uri` + pass the fn to user-avatar component to fill the style related options + + check `get-account-image-uri` for color formats + check `get-font-file-ready` for `font-file` + + check `get-account-image-uri-fn` for `override-ring?`" + [{:keys [port public-key key-uid theme override-ring? font-file]}] + (fn [{:keys [full-name length size background-color font-size color + indicator-size indicator-border indicator-color ring? + override-theme]}] + (get-initials-avatar-uri {:port port + :public-key public-key + :key-uid key-uid + :full-name full-name + :length length + :size size + :background-color background-color + :theme (if (nil? override-theme) theme override-theme) + :ring? (if (nil? override-ring?) ring? override-ring?) + :font-size font-size + :color color + :font-file font-file + :uppercase-ratio (:uppercase-ratio constants/initials-avatar-font-conf) + :indicator-size indicator-size + :indicator-border indicator-border + :indicator-color indicator-color}))) + (defn get-contact-image-uri - [port public-key image-name clock theme] + [{:keys [port public-key image-name clock theme indicator-size indicator-border + indicator-color size ring?]}] (str image-server-uri-prefix port contact-images-action @@ -52,11 +212,34 @@ public-key "&imageName=" image-name + "&size=" + (Math/round (* size status-im.utils.pixel-ratio/ratio)) "&theme=" (current-theme-index theme) "&clock=" clock - "&addRing=1")) + "&indicatorColor=" + (js/encodeURIComponent indicator-color) + "&indicatorSize=" + (* indicator-size status-im.utils.pixel-ratio/ratio) + "&indicatorBorder=" + (* indicator-border status-im.utils.pixel-ratio/ratio) + "&addRing=" + (if ring? 1 0))) + +(defn get-contact-image-uri-fn + [{:keys [port public-key image-name theme override-ring? clock]}] + (fn [{:keys [size indicator-size indicator-border indicator-color ring? override-theme]}] + (get-contact-image-uri {:port port + :image-name image-name + :public-key public-key + :size size + :theme (if (nil? override-theme) theme override-theme) + :clock clock + :indicator-size indicator-size + :indicator-border indicator-border + :indicator-color indicator-color + :ring? (if (nil? override-ring?) ring? override-ring?)}))) (defn get-account-qr-image-uri [{:keys [key-uid public-key port qr-size]}] diff --git a/src/utils/image_server_test.cljs b/src/utils/image_server_test.cljs index 9d431e3332..83cf1bb11e 100644 --- a/src/utils/image_server_test.cljs +++ b/src/utils/image_server_test.cljs @@ -1,17 +1,46 @@ (ns utils.image-server-test (:require [cljs.test :as t] + status-im.utils.pixel-ratio [utils.image-server :as sut])) (t/deftest get-account-image-uri (with-redefs - [sut/current-theme-index identity - sut/timestamp (constantly "timestamp")] + [sut/current-theme-index identity + status-im.utils.pixel-ratio/ratio 2 + sut/timestamp (constantly "timestamp")] (t/is (= - (sut/get-account-image-uri {:port "port" - :public-key "public-key" - :image-name "image-name" - :key-uid "key-uid" - :theme "theme" - :ring? true}) - "https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&theme=theme&clock=timestamp&addRing=1")))) + (sut/get-account-image-uri {:port "port" + :public-key "public-key" + :image-name "image-name" + :key-uid "key-uid" + :theme :dark + :indicator-size 2 + :indicator-color "rgba(9,16,28,0.08)" + :ring? true}) + "https://localhost:port/accountImages?publicKey=public-key&keyUid=key-uid&imageName=image-name&size=0&theme=:dark&clock=timestamp&indicatorColor=rgba(9%2C16%2C28%2C0.08)&indicatorSize=4&indicatorBorder=0&addRing=1")))) + +(t/deftest get-account-initials-uri + (with-redefs + [sut/current-theme-index identity + status-im.utils.pixel-ratio/ratio 2 + sut/timestamp (constantly "timestamp")] + (t/is + (= + (sut/get-initials-avatar-uri + {:port "port" + :public-key "public-key" + :key-uid "key-uid" + :full-name "full-name" + :length "length" + :size 48 + :theme :light + :ring? "ring?" + :background-color "background-color" + :color "#0E162000" + :font-size 12 + :font-file "/font/Inter Medium.otf" + :uppercase-ratio "uppercase-ratio" + :indicator-size 2 + :indicator-color "#0E1620"}) + "https://localhost:port/accountInitials?publicKey=public-key&keyUid=key-uid&length=length&size=96&bgColor=background-color&color=%230E162000&fontSize=24&fontFile=%2Ffont%2FInter%20Medium.otf&uppercaseRatio=uppercase-ratio&theme=:light&clock=&name=full-nametimestamp&indicatorColor=%230E1620&indicatorSize=4&indicatorBorder=0&addRing=1")))) diff --git a/status-go-version.json b/status-go-version.json index 9c6300e1cc..0bb192e440 100644 --- a/status-go-version.json +++ b/status-go-version.json @@ -3,7 +3,7 @@ "_comment": "Instead use: scripts/update-status-go.sh ", "owner": "status-im", "repo": "status-go", - "version": "v0.163.8", - "commit-sha1": "d61f983d9555e98cf84a3b1273687914887c2e67", - "src-sha256": "1y0s5ivrkywj9simvv2i31ggfzg38li12if2lvfqn8nx10a5y9ai" + "version": "v0.163.9", + "commit-sha1": "f2f599fe867a0eba90aaa717a29bb6e99cb5749e", + "src-sha256": "0p282pv2lz5f2b0vhpcx0nj74dp5mf7hb41l12js2hxsp21sprmj" }