[13939] Implement system message into quo2 components (#14061)

This commit is contained in:
erikseppanen 2022-10-06 10:59:39 -04:00 committed by GitHub
parent 1f6ebbb5e8
commit c2c281d9c6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 307 additions and 53 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 940 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 441 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 440 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -9,9 +9,10 @@
:small 20})
(defn icon-avatar
[{:keys [size icon color]}]
[{:keys [size icon color opacity]
:or {opacity 20}}]
(let [component-size (size sizes)
circle-color (colors/custom-color color 50 20)
circle-color (colors/custom-color color 50 opacity)
icon-color (colors/custom-color-by-theme color 50 60)
icon-size (case size
:big 20
@ -25,4 +26,4 @@
:align-items :center}}
[icons/icon icon {:container-style {:width icon-size
:height icon-size}
:color icon-color}]]))
:color icon-color}]]))

View File

@ -4,8 +4,7 @@
[quo2.foundations.colors :as colors]
[quo2.components.icon :as icons]
[clojure.string :refer [upper-case split blank?]]
[quo.theme :refer [dark?]]
[status-im.ui.components.react :as react]))
[quo.theme :refer [dark?]]))
(def sizes {:big {:outer 80
:inner 72
@ -98,47 +97,46 @@
status-indicator?
profile-picture
full-name]
:or {full-name "empty name"
status-indicator? true
online? true
size :big
ring? true}}]
(let [initials (if full-name
(reduce str (map first (split full-name " ")))
"")
:or {full-name "empty name"
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)
using-profile-picture? (-> profile-picture
blank?
false?)
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)
"")]
[rn/view {:style {:width outer-dimensions
:height outer-dimensions
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)
"")]
[rn/view {:style {:width outer-dimensions
:height outer-dimensions
:border-radius outer-dimensions}}
(when (and ring? identicon?)
[icons/icon :main-icons/identicon-ring {:width outer-dimensions
:height outer-dimensions
:size outer-dimensions
[icons/icon :main-icons/identicon-ring {:width outer-dimensions
:height outer-dimensions
:size outer-dimensions
:no-color true}])
(if using-profile-picture?
[react/image {:style (container-styling inner-dimensions outer-dimensions)
:source {:uri profile-picture}}]
(if profile-picture
;; display image
[rn/image {:style (container-styling inner-dimensions outer-dimensions)
:source profile-picture}]
;; else display initials
[container inner-dimensions outer-dimensions
[text/text {:weight :semi-bold
:size font-size
:style {:color colors/white-opa-70}}
:size font-size
:style {:color colors/white-opa-70}}
(upper-case icon-text)]])
[dot-indicator size status-indicator? online? ring? (dark?)]]))

View File

@ -0,0 +1,162 @@
(ns quo2.components.messages.system-message
(:require [status-im.i18n.i18n :as i18n]
[quo.react-native :as rn]
[status-im.utils.core :as utils]
[quo.theme :as theme]
[quo2.components.buttons.button :as button]
[quo2.components.markdown.text :as text]
[quo2.reanimated :as ra]
[quo2.foundations.colors :as colors]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.avatars.icon-avatar :as icon-avatar]))
(def themes-landed {:pinned colors/primary-50-opa-5
:added colors/primary-50-opa-5
:deleted colors/danger-50-opa-5})
(def themes
{:light {:text colors/neutral-100
:time colors/neutral-50
:bg {:default colors/white
:pressed colors/neutral-5
:landed themes-landed}}
:dark {:text colors/white
:time colors/neutral-40
:bg {:default colors/neutral-90
:pressed colors/neutral-80
:landed themes-landed}}})
(defn get-color [& keys]
(reduce (fn [acc k] (get acc k (reduced acc)))
((theme/get-theme) themes) (vec keys)))
(defn sm-timestamp [timestamp-str]
[rn/view {:margin-left 6}
[text/text {:size :label
:style {:color (get-color :time)
:text-transform :none}}
timestamp-str]])
(defn sm-icon [{:keys [icon color opacity]}]
[rn/view {:align-items :center
:margin-right 8}
[icon-avatar/icon-avatar {:size :medium
:icon icon
:color color
:opacity opacity}]])
(defn sm-user-avatar [image]
[rn/view {:margin-right 4}
[user-avatar/user-avatar {:status-indicator? false
:online? false
:size :xxxs
:profile-picture image
:ring? false}]])
(defmulti sm-render :type)
(defmethod sm-render :deleted [{:keys [state action timestamp-str]}]
[rn/view {:align-items :center
:justify-content :space-between
:flex 1
:flex-direction :row}
[rn/view {:align-items :center
:flex-direction :row}
[sm-icon {:icon :main-icons/delete16
:color :danger
:opacity (if (= state :landed) 0 5)}]
[text/text {:size :paragraph-2
:style {:color (get-color :text)
:margin-right 5}}
(i18n/label (if action :message-deleted-for-you :message-deleted))]
(when (nil? action) [sm-timestamp timestamp-str])]
(when action [button/button {:size 24
:before :main-icons/timeout
:type :grey} (i18n/label :undo)])])
(defmethod sm-render :added [{:keys [state mentions timestamp-str]}]
[rn/view {:align-items :center
:flex-direction :row}
[sm-icon {:icon :main-icons/add-user16
:color :primary
:opacity (if (= state :landed) 0 5)}]
[sm-user-avatar (:image (first mentions))]
[text/text {:weight :semi-bold
:size :paragraph-2}
(:name (first mentions))]
[text/text {:size :paragraph-2
:style {:color (get-color :text)
:margin-left 3
:margin-right 3}}
(i18n/label :added)]
[sm-user-avatar (:image (second mentions))]
[text/text {:weight :semi-bold
:size :paragraph-2}
(:name (second mentions))]
[sm-timestamp timestamp-str]])
(defmethod sm-render :pinned [{:keys [state pinned-by content timestamp-str]}]
[rn/view {:flex-direction :row
:flex 1
:align-items :center}
[sm-icon {:icon :main-icons/pin16
:color :primary
:opacity (if (= state :landed) 0 5)}]
[rn/view {:flex-direction :column
:flex 1}
[rn/view {:align-items :baseline
:flex-direction :row}
[text/text {:size :paragraph-2
:weight :semi-bold
:style {:color (get-color :text)}}
(utils/truncate-str pinned-by 18)]
[rn/view {:margin-left 4
:margin-right 2}
[text/text {:size :paragraph-2
:style {:color (get-color :text)}}
(i18n/label :pinned-a-message)]]
[sm-timestamp timestamp-str]]
[rn/view {:flex-direction :row}
[rn/view {:flex-direction :row
:margin-right 4}
[sm-user-avatar (:image (:mentions content))]
[text/text {:weight :semi-bold
:size :label}
(:name (:mentions content))]]
(when (seq (:text content))
[rn/view {:margin-right 20
:flex-direction :row
:flex 1}
[text/text {:size :label
:style {:color (get-color :text)}
:number-of-lines 1
:ellipsize-mode :tail}
(:text content)]])
[rn/view {:justify-content :flex-end
:flex-direction :row
:min-width 10}
(when (seq (:info content))
[text/text {:size :label
:style {:color (get-color :time)}}
(utils/truncate-str (:info content) 24)])]]]])
(defn system-message [{:keys [type] :as message}]
[:f>
(fn []
(let [sv-color (ra/use-shared-value (get-color :bg :landed type))]
(ra/animate-shared-value-with-delay
sv-color (get-color :bg :default type) 0 :linear 1000)
[ra/touchable-opacity
{:on-press #(ra/set-shared-value
sv-color (get-color :bg :pressed type))
:style (ra/apply-animations-to-style
{:background-color sv-color}
{:flex-direction :row
:flex 1
:border-radius 16
:padding-vertical 9
:padding-horizontal 11
:width 359
:height 52
:background-color sv-color})}
[sm-render message]]))])

View File

@ -119,6 +119,7 @@
;;;; Customization
;; Colors for customizing profiles and communities themes
(def customization
{:primary {50 primary-50 ;; User can also use primary color as customisation color
60 primary-60}
@ -145,6 +146,11 @@
:beige {50 "#CAAE93"
60 "#AA927C"}})
(def colors-map (merge {:danger {50 danger-50
60 danger-60}
:success {50 success-50
60 success-60}} customization))
(def custom-color
"(custom-color color suffix opacity)
color :primary/:purple/...
@ -155,7 +161,7 @@
([color suffix]
(custom-color color suffix nil))
([color suffix opacity]
(let [base-color (get-in customization [(keyword color) suffix])]
(let [base-color (get-in colors-map [(keyword color) suffix])]
(if opacity (alpha base-color (/ opacity 100)) base-color))))))
(defn custom-color-by-theme

View File

@ -19,7 +19,7 @@
:type :select
:options [{:key :main-icons/placeholder20
:value "Placeholder"}
{:key :main-icons/walelt
{:key :main-icons/wallet
:value "Wallet"}
{:key :main-icons/play
:value "Play"}]}

View File

@ -3,7 +3,8 @@
[quo2.foundations.colors :as colors]
[quo.previews.preview :as preview]
[quo2.components.avatars.user-avatar :as quo2]
[reagent.core :as reagent]))
[reagent.core :as reagent]
[status-im.react-native.resources :as resources]))
(def descriptor [{:label "Size:"
:key :size
@ -32,9 +33,15 @@
{:label "Full name separated by space"
:key :full-name
:type :text}
{:label "Profile Picture URL"
:key :profile-picture
:type :text}])
{:label "Profile Picture"
:key :profile-picture
:type :select
:options [{:value "None"
:key nil}
{:value "Alicia Keys"
:key (resources/get-mock-image :user-picture-female2)}
{:value "pedro.eth"
:key (resources/get-mock-image :user-picture-male4)}]}])
(defn cool-preview []
(let [state (reagent/atom {:full-name "A Y"

View File

@ -25,6 +25,7 @@
[quo2.screens.list-items.channel :as channel]
[quo2.screens.markdown.text :as text]
[quo2.screens.messages.gap :as messages-gap]
[quo2.screens.messages.system-message :as system-message]
[quo2.screens.notifications.activity-logs :as activity-logs]
[quo2.screens.reactions.react :as react]
[quo2.screens.selectors.disclaimer :as disclaimer]
@ -96,7 +97,10 @@
:component text/preview-text}]
:messages [{:name :gap
:insets {:top false}
:component messages-gap/preview-messages-gap}]
:component messages-gap/preview-messages-gap}
{:name :system-messages
:insets {:top false}
:component system-message/preview-system-message}]
:navigation [{:name :bottom-nav-tab
:insets {:top false}
:component bottom-nav-tab/preview-bottom-nav-tab}

View File

@ -0,0 +1,68 @@
(ns quo2.screens.messages.system-message
(:require [reagent.core :as reagent]
[status-im.react-native.resources :as resources]
[quo.react-native :as rn]
[quo.previews.preview :as preview]
[quo2.components.messages.system-message :as system-message]
[quo2.foundations.colors :as colors]))
(def descriptor [{:label "Message Type"
:key :type
:type :select
:options [{:value "Message pinned"
:key :pinned}
{:value "User added"
:key :added}
{:value "Message deleted"
:key :deleted}]}
{:label "Action"
:key :action
:type :select
:options [{:value "none"
:key nil}
{:value "Undo"
:key :undo}]}
{:label "Pinned By"
:key :pinned-by
:type :text}
{:label "Content Text"
:key :content-text
:type :text}
{:label "Content Info"
:key :content-info
:type :text}
{:label "Timestamp"
:key :timestamp-str
:type :text}])
(defn finalize-state [state]
(merge @state
{:mentions [{:name "Alicia Keys"
:image (resources/get-mock-image :user-picture-female2)}
{:name "pedro.eth"
:image (resources/get-mock-image :user-picture-male4)}]
:content {:text (:content-text @state)
:info (:content-info @state)
:mentions {:name "Alisher"
:image (resources/get-mock-image :user-picture-male5)}}}))
(defn preview []
(let [state (reagent/atom {:type :deleted
:pinned-by "Steve"
:content-text "Hello! This is an example of a pinned message!"
:content-info "3 photos"
:timestamp-str "09:41"})]
(fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150}
[preview/customizer state descriptor]
[rn/view {:padding-vertical 60
:align-items :center}
[system-message/system-message (finalize-state state)]]]])))
(defn preview-system-message []
[rn/view {:background-color (colors/theme-colors colors/white colors/neutral-90)
:flex 1}
[rn/flat-list {:flex 1
:header [preview]
:key-fn str
:keyboardShouldPersistTaps :always}]])

View File

@ -55,13 +55,16 @@
:podcasts (js/require "../resources/images/ui/podcasts.png")})
(def mock-images
{:photo1 (js/require "../resources/images/mock/photo1.png")
:photo2 (js/require "../resources/images/mock/photo2.png")
:photo3 (js/require "../resources/images/mock/photo3.png")
:community-banner (js/require "../resources/images/mock/community-banner.png")
:community-logo (js/require "../resources/images/mock/community-logo.png")
:gif (js/require "../resources/images/mock/gif.png")
:sticker (js/require "../resources/images/mock/sticker.png")})
{:photo1 (js/require "../resources/images/mock/photo1.png")
:photo2 (js/require "../resources/images/mock/photo2.png")
:photo3 (js/require "../resources/images/mock/photo3.png")
:community-banner (js/require "../resources/images/mock/community-banner.png")
:community-logo (js/require "../resources/images/mock/community-logo.png")
:gif (js/require "../resources/images/mock/gif.png")
:sticker (js/require "../resources/images/mock/sticker.png")
:user-picture-female2 (js/require "../resources/images/mock/user_picture_female2.png")
:user-picture-male4 (js/require "../resources/images/mock/user_picture_male4.png")
:user-picture-male5 (js/require "../resources/images/mock/user_picture_male5.png")})
(defn get-theme-image [k]
(get ui (when (colors/dark?) (keyword (str (name k) "-dark"))) (get ui k)))

View File

@ -20,6 +20,7 @@
"active-online": "Online",
"active-unknown": "Unknown",
"add": "Add",
"added": "added",
"add-a-watch-account": "Add a watch-only address",
"add-account": "Add an account",
"add-account-description": "You can import any type of Ethereum account to add it to your Status wallet",
@ -856,6 +857,8 @@
"members-active-none": "no members",
"members-title": "Members",
"message": "Message",
"message-deleted": "Message deleted",
"message-deleted-for-you": "Message deleted for you",
"message-not-sent": "Message not sent",
"message-options-cancel": "Cancel",
"message-reply": "Reply",
@ -1302,6 +1305,7 @@
"last-backup-performed": "Last backup performed:",
"unable-to-read-this-code": "Unable to read this code",
"unblock-contact": "Unblock this user",
"undo": "Undo",
"unknown-status-go-error": "Unknown status-go error",
"unlock": "Unlock",
"unpair-card": "Unpair card",
@ -1653,6 +1657,7 @@
"accept-and-continue": "Accept and continue",
"empty-activity-center": "Your chat notifications\nwill appear here",
"pinned-messages": "Pinned messages",
"pinned-a-message": "pinned a message",
"pin": "Pin",
"unpin": "Unpin",
"no-pinned-messages": "No pinned messages",