[13939] Implement system message into quo2 components (#14061)
After Width: | Height: | Size: 667 B |
After Width: | Height: | Size: 940 B |
After Width: | Height: | Size: 441 B |
After Width: | Height: | Size: 585 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 440 B |
After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 15 KiB |
After Width: | Height: | Size: 9.7 KiB |
|
@ -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}]]))
|
||||
|
|
|
@ -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?)]]))
|
||||
|
|
|
@ -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]]))])
|
|
@ -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
|
||||
|
|
|
@ -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"}]}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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}]])
|
|
@ -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)))
|
||||
|
|
|
@ -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",
|
||||
|
|