Improve chat Avatar (#15036)

This commit is contained in:
Ulises Manuel Cárdenas 2023-03-01 14:54:40 -06:00 committed by GitHub
parent aec1b5fafa
commit 7d9709ee67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 164 additions and 173 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 989 B

View File

@ -1,6 +1,5 @@
(ns quo2.components.avatars.user-avatar
(:require [clojure.string :refer [blank? split upper-case]]
[quo2.components.icon :as icons]
(:require [clojure.string :as string]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[quo2.theme :refer [dark?]]
@ -40,115 +39,100 @@
:font-size :label}})
(defn dot-indicator
[size status-indicator? online? ring? dark?]
(when status-indicator?
(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 (if ring?
-2
-2)
0)]
[rn/view
{:style {:background-color (if online?
colors/success-50
colors/neutral-40)
:width dimensions
:height dimensions
:border-width border-width
:border-radius dimensions
:border-color (if dark?
colors/neutral-100
colors/white)
:position :absolute
:bottom bottom
:right right}}])))
[{:keys [size online? ring? dark?]}]
(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)]
[rn/view
{:style {:background-color (if online?
colors/success-50
colors/neutral-40)
:width dimensions
:height dimensions
:border-width border-width
:border-radius dimensions
:border-color (if dark?
colors/neutral-100
colors/white)
:position :absolute
:bottom bottom
:right right}}]))
(defn container-styling
(defn initials-style
[inner-dimensions outer-dimensions]
{:width inner-dimensions
:position :absolute
:top (/ (- outer-dimensions inner-dimensions) 2)
:left (/ (- outer-dimensions inner-dimensions) 2)
:height inner-dimensions
:border-radius inner-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
:justify-content :center
:align-items :center
:background-color (colors/custom-color-by-theme :turquoise 50 60)})
(defn container
[inner-dimensions outer-dimensions & children]
[rn/view
{:style (merge {:background-color (colors/custom-color-by-theme :turquoise 50 60)
:justify-content :center
:align-items :center}
(container-styling inner-dimensions outer-dimensions))}
children])
(defn outer-styles
[outer-dimensions]
{:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions})
(def small-sizes #{:xs :xxs :xxxs})
(def identicon-sizes #{:big :medium :small})
(def one-initial-letter-sizes #{:xs :xxs :xxxs})
(def valid-ring-sizes #{:big :medium :small})
(defn initials-avatar
[{:keys [full-name size inner-dimensions outer-dimensions]}]
(let [amount-initials (if (one-initial-letter-sizes size) 1 2)
initials (as-> full-name $
(string/split $ " ")
(map (comp string/upper-case first) $)
(take amount-initials $)
(string/join $))
font-size (get-in sizes [size :font-size])]
[rn/view {:style (initials-style inner-dimensions outer-dimensions)}
[text/text
{:style {:color colors/white-opa-70}
:weight :semi-bold
:size font-size}
initials]]))
(defn user-avatar
[{:keys [ring?
online?
size
status-indicator?
profile-picture
full-name]
:or {full-name "empty name"
status-indicator? true
"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 over it."
[{:keys [full-name status-indicator? online? size profile-picture ring-background]
:or {status-indicator? true
online? true
size :big
ring? true}}]
(let [initials (if full-name
(reduce str (map first (split full-name " ")))
"")
first-initial-letter (if full-name
(or (first full-name) "")
"")
identicon? (contains? identicon-sizes size)
small? (contains? small-sizes size)
outer-dimensions (get-in sizes [size :outer])
inner-dimensions (get-in sizes
[size
(if ring?
:inner
:outer)])
font-size (get-in sizes [size :font-size])
icon-text (if-not (or (blank? first-initial-letter)
(blank? initials))
(if small?
first-initial-letter
initials)
"")]
size :big}}]
(let [full-name (or full-name "empty name")
draw-ring? (and ring-background (valid-ring-sizes size))
outer-dimensions (get-in sizes [size :outer])
inner-dimensions (get-in sizes [size (if draw-ring? :inner :outer)])]
[rn/view
{:accessibility-label :user-avatar
:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
(when (and false (and ring? identicon?)) ;;TODO not implemented yet
[icons/icon :i/identicon-ring
{:size outer-dimensions
:no-color true}])
(if profile-picture
;; display image
{:style (outer-styles outer-dimensions)
:accessibility-label :user-avatar}
;; The `profile-picture` already has the ring in it
(when-let [image (or profile-picture ring-background)]
[fast-image/fast-image
{:source profile-picture
:style (container-styling inner-dimensions outer-dimensions)}]
;; else display initials
[container inner-dimensions outer-dimensions
^{:key :icon-text}
[text/text
{:weight :semi-bold
:size font-size
:style {:color colors/white-opa-70}}
(upper-case icon-text)]])
[dot-indicator size status-indicator? online? ring? (dark?)]]))
{:style (outer-styles outer-dimensions)
:source image}])
(when-not profile-picture
[initials-avatar
{:full-name full-name
:size size
:inner-dimensions inner-dimensions
:outer-dimensions outer-dimensions}])
(when status-indicator?
[dot-indicator
{:size size
:online? online?
:ring? draw-ring?
:dark? (dark?)}])]))

View File

@ -49,8 +49,7 @@
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small
:ring? false}]
:size :small}]
[rn/view {:style {:margin-left 8}}
[author/author
{:primary-name primary-name

View File

@ -25,8 +25,7 @@
:profile-picture profile-picture
:override-theme :dark
:size :medium
:status-indicator? false
:ring? true}]
:status-indicator? false}]
[button/button
{:size 32
:type :blur-bg

View File

@ -24,29 +24,31 @@
(let [internal-selected? (reagent/atom (or default-selected? false))]
(fn [{:keys [selected?
profile-picture
ring-background
name
customization-color
on-change]
:or {customization-color :turquoise}}]
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
(reset! internal-selected? selected?))
[rn/touchable-opacity
{:style (style/container customization-color @internal-selected?)
:on-press #(on-change-handler internal-selected? on-change)
:active-opacity 1
:accessibility-label :select-profile}
[rn/view {:style style/header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
:status-indicator? false
:ring? true
:size :medium}]
[rn/view {:style (style/select-radio @internal-selected?)}
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
[text/text
{:size :heading-2
:weight :semi-bold
:style style/profile-name
} name]])))
(let [avatar-image-key (if profile-picture :profile-picture :ring-background)
picture (or profile-picture ring-background)]
(when (and (not (nil? selected?)) (not= @internal-selected? selected?))
(reset! internal-selected? selected?))
[rn/touchable-opacity
{:style (style/container customization-color @internal-selected?)
:on-press #(on-change-handler internal-selected? on-change)
:active-opacity 1
:accessibility-label :select-profile}
[rn/view {:style style/header}
[user-avatar/user-avatar
{:full-name name
:status-indicator? false
:size :medium
avatar-image-key picture}]
[rn/view {:style (style/select-radio @internal-selected?)}
(when @internal-selected? [rn/view {:style style/select-radio-inner}])]]
[text/text
{:size :heading-2
:weight :semi-bold
:style style/profile-name}
name]]))))

View File

@ -69,7 +69,8 @@
:user-picture-male5 (js/require "../resources/images/mock/user_picture_male5.png")
:coinbase (js/require "../resources/images/mock/coinbase.png")
:small-opt-card-icon (js/require "../resources/images/mock/small_opt_card_icon.png")
:small-opt-card-main (js/require "../resources/images/mock/small_opt_card_main.png")})
:small-opt-card-main (js/require "../resources/images/mock/small_opt_card_main.png")
:ring (js/require "../resources/images/mock/ring.png")})
(defn get-theme-image
[k]

View File

@ -52,10 +52,7 @@
new-notifications? (pos? notif-count)
notification-indicator :unread-dot
counter-label "0"]
[rn/view
{:style (merge
{:height 56}
style)}
[rn/view {:style (assoc style :height 56)}
;; Left Section
[rn/touchable-without-feedback {:on-press open-profile}
[rn/view
@ -64,8 +61,7 @@
:top 12}}
[quo/user-avatar
(merge
{:ring? true
:status-indicator? true
{:status-indicator? true
:size :small}
avatar)]]]
;; Right Section

View File

@ -102,33 +102,39 @@
(datetime/to-short-str timestamp)]])
(defn avatar-view
[group-chat color display-name photo-path chat-id]
(if group-chat
[{:keys [contact chat-id full-name color]}]
(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)]
[quo/user-avatar
{:full-name full-name
:size :small
:online? online?
image-key photo-path}])
[quo/group-avatar
{:color color
:size :medium}]
(let [online? (rf/sub [:visibility-status-updates/online? chat-id])]
[quo/user-avatar
{:full-name display-name
:online? online?
:profile-picture photo-path
:size :small}])))
:size :medium}]))
(defn chat-list-item
[item]
(let [{:keys [chat-id color group-chat last-message timestamp name unviewed-mentions-count
unviewed-messages-count]}
item
display-name
(if group-chat name (first (rf/sub [:contacts/contact-two-names-by-identity 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]))]
[{:keys [chat-id group-chat color name unviewed-messages-count unviewed-mentions-count
timestamp last-message]
:as item}]
(let [display-name (if group-chat
name
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id])))
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address chat-id]))]
[rn/touchable-opacity
(merge {:style (style/container)
:on-press (open-chat chat-id)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/chat-actions item false])}])})
[avatar-view group-chat color display-name photo-path chat-id]
{:style (style/container)
:on-press (open-chat chat-id)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/chat-actions item false])}])}
[avatar-view
{:contact contact
:chat-id chat-id
:full-name display-name
:color color}]
[rn/view {:style {:margin-left 8}}
[name-view display-name contact timestamp]
(if (string/blank? (get-in last-message [:content :parsed-text]))

View File

@ -17,7 +17,6 @@
{:full-name display-name
:profile-picture profile-picture
:status-indicator? false
:ring? false
:size :xxxs}]]
[quo/author {:primary-name display-name}]
[quo/text

View File

@ -39,8 +39,7 @@
:profile-picture photo-path
:status-indicator? true
:online? online?
:size :small
:ring? false}]]])
:size :small}]]])
[rn/view {:padding-top 2 :width 32}]))
(defn author

View File

@ -32,19 +32,22 @@
(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]))]
contact (when-not group-chat
(rf/sub [:contacts/contact-by-address chat-id]))
photo-path (rf/sub [:chats/photo-path chat-id])
avatar-image-key (if (seq (:images contact))
:profile-picture
:ring-background)]
[quo/page-nav
{:align-mid? true
:mid-section (if group-chat
{:type :text-only
:main-text display-name}
{:type :user-avatar
:avatar {:full-name display-name
:online? online?
:profile-picture photo-path
:size :medium}
:size :medium
avatar-image-key photo-path}
:main-text display-name
:on-press #(debounce/dispatch-and-chill [:chat.ui/show-profile chat-id]
1000)})

View File

@ -28,7 +28,7 @@
{:label "Status Indicator"
:key :status-indicator?
:type :boolean}
{:label "Identicon Ring"
{:label "Identicon Ring (applies only when there's no profile picture)"
:key :ring?
:type :boolean}
{:label "Full name separated by space"
@ -49,8 +49,7 @@
(let [state (reagent/atom {:full-name "A Y"
:status-indicator? true
:online? true
:size :medium
:ring? true})]
:size :medium})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
@ -60,7 +59,12 @@
{:padding-vertical 60
:flex-direction :row
:justify-content :center}
[quo2/user-avatar @state]]]])))
(let [{:keys [profile-picture ring?]} @state
ring-bg (resources/get-mock-image :ring)
params (cond-> @state
(and (not profile-picture) ring?)
(assoc :ring-background ring-bg))]
[quo2/user-avatar params])]]])))
(defn preview-user-avatar
[]

View File

@ -109,8 +109,7 @@
(case type
shell.constants/one-to-one-chat-card
[quo/user-avatar
(merge {:ring? false
:size :medium
(merge {:size :medium
:status-indicator? false}
avatar-params)]