[#17986] feat: implement new settings ui, header section (#17991)

This commit is contained in:
Mohsen 2023-11-29 20:54:11 +03:00 committed by GitHub
parent 589a581298
commit 6b721265af
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 416 additions and 7 deletions

View File

@ -0,0 +1,22 @@
(ns quo.components.overlay.style
(:require [quo.foundations.colors :as colors]))
(defn overlay-background
[type]
(let [background-color (case type
:shell colors/neutral-80-opa-80-blur
:drawer colors/neutral-100-opa-70-blur
nil)]
{:position :absolute
:top 0
:left 0
:right 0
:bottom 0
:background-color background-color}))
(def container
{:flex 1})
(def blur-container
{:flex 1
:background-color :transparent})

View File

@ -0,0 +1,20 @@
(ns quo.components.overlay.view
(:require
[quo.components.overlay.style :as style]
[react-native.blur :as blur]
[react-native.core :as rn]))
(defn view
[{:keys [type]} & children]
[rn/view {:style (style/overlay-background type)}
(if (= type :shell)
[blur/view
{:blur-amount 20
:blur-radius 25
:blur-type :transparent
:overlay-color :transparent
:style style/container}
[rn/view {:style style/blur-container}
children]]
[rn/view {:style style/container}
children])])

View File

@ -9,3 +9,8 @@
(def description-description-text
{:margin-top 8})
(def emoji-hash
{:margin-top 8
:letter-spacing 0.5
:line-height 20.5})

View File

@ -27,7 +27,8 @@
description-accessibility-label
button-icon
button-on-press
customization-color]}]
customization-color
emoji-hash]}]
[rn/view {:style container-style}
[rn/view
{:style {:flex-direction :row
@ -55,6 +56,11 @@
:weight :regular
:size :paragraph-1
:style style/description-description-text}
description])])
description])
(when emoji-hash
[text/text
{:number-of-lines 1
:style style/emoji-hash}
emoji-hash])])
(def view (theme/with-theme view-internal))

View File

@ -101,6 +101,7 @@
quo.components.numbered-keyboard.keyboard-key.view
quo.components.numbered-keyboard.numbered-keyboard.view
quo.components.onboarding.small-option-card.view
quo.components.overlay.view
quo.components.password.tips.view
quo.components.profile.collectible.view
quo.components.profile.profile-card.view
@ -316,6 +317,9 @@
(def notification quo.components.notifications.notification.view/notification)
(def toast quo.components.notifications.toast.view/toast)
;;;; Overlay
(def overlay quo.components.overlay.view/view)
;;;; Password
(def tips quo.components.password.tips.view/view)

View File

@ -148,7 +148,9 @@
(def black-opa-30 (alpha black 0.3))
(def black-opa-60 (alpha black 0.6))
(def onboarding-header-black "#000716")
(def border-avatar-light
"Simulates a blurred, transparent border for avatars in light mode"
"#475060")
;;;;Primary
;;Solid

View File

@ -0,0 +1,43 @@
(ns status-im2.contexts.profile.settings.header.avatar
(:require [quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.reanimated :as reanimated]
[status-im2.contexts.profile.settings.header.style :as style]))
(def scroll-animation-input-range [0 50])
(def header-extrapolation-option
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
(defn f-avatar
[{:keys [scroll-y full-name online? profile-picture customization-color]}]
(let [image-scale-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[1 0.5]
header-extrapolation-option)
image-top-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 20]
header-extrapolation-option)
image-side-margin-animation (reanimated/interpolate scroll-y
scroll-animation-input-range
[0 -20]
header-extrapolation-option)
theme (quo.theme/get-theme)]
[reanimated/view
{:style (style/avatar-container theme
image-scale-animation
image-top-margin-animation
image-side-margin-animation)}
[quo/user-avatar
{:full-name full-name
:online? online?
:profile-picture profile-picture
:status-indicator? true
:ring? true
:customization-color customization-color
:size :big}]]))
(defn view
[props]
[:f> f-avatar props])

View File

@ -0,0 +1,36 @@
(ns status-im2.contexts.profile.settings.header.header-shape
(:require [quo.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.svg :as svg]
[status-im2.contexts.profile.settings.header.style :as style]))
(defn left-radius
[background-color]
[svg/svg {:width "20" :height "20" :viewBox "0 0 20 20" :fill "none"}
[svg/path
{:d "M20 0C7 2 0 10 0 20V0H15Z"
:fill background-color}]])
(defn right-radius
[background-color]
[svg/svg {:width "20" :height "21" :viewBox "0 0 20 21" :fill "none"}
[svg/path
{:d "M20 20V0H0C11 0 20 9 20 20Z"
:fill background-color}]])
(defn f-view
[{:keys [scroll-y customization-color theme]}]
(let [background-color (colors/resolve-color customization-color theme 40)
opacity-animation (reanimated/interpolate scroll-y
[0 45 50]
[1 1 0])]
[:<>
[rn/view {:style (style/header-middle-shape background-color)}]
[reanimated/view {:style (style/radius-container opacity-animation)}
[left-radius background-color]
[right-radius background-color]]]))
(defn view
[props]
[:f> f-view props])

View File

@ -0,0 +1,48 @@
(ns status-im2.contexts.profile.settings.header.style
(:require [quo.foundations.colors :as colors]
[react-native.reanimated :as reanimated]))
(defn header-view
[customization-color theme]
{:background-color (colors/resolve-color customization-color theme 40)
:min-height 100
:flex 1})
(def avatar-row-wrapper
{:display :flex
:padding-left 16
:padding-right 12
:margin-top -60
:margin-bottom -4
:align-items :flex-end
:justify-content :space-between
:flex-direction :row})
(def title-container
{:padding-horizontal 20
:padding-vertical 12})
(defn header-middle-shape
[background-color]
{:background-color background-color
:height 48
:flex-grow 1})
(defn radius-container
[opacity-animation]
(reanimated/apply-animations-to-style
{:opacity opacity-animation}
{:flex-direction :row
:justify-content :space-between}))
(defn avatar-container
[theme scale-animation top-margin-animation side-margin-animation]
(reanimated/apply-animations-to-style
{:transform [{:scale scale-animation}]
:margin-top top-margin-animation
:margin-left side-margin-animation
:margin-bottom side-margin-animation}
{:align-items :flex-start
:border-width 4
:border-color (colors/theme-colors colors/border-avatar-light colors/neutral-80-opa-80 theme)
:border-radius 100}))

View File

@ -0,0 +1,49 @@
(ns status-im2.contexts.profile.settings.header.view
(:require [clojure.string :as string]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.header.avatar :as header.avatar]
[status-im2.contexts.profile.settings.header.header-shape :as header.shape]
[status-im2.contexts.profile.settings.header.style :as style]
[status-im2.contexts.profile.utils :as profile.utils]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- f-view
[{:keys [theme scroll-y]}]
(let [{:keys [public-key emoji-hash] :as profile} (rf/sub [:profile/profile-with-image])
online? (rf/sub [:visibility-status-updates/online?
public-key])
customization-color (rf/sub [:profile/customization-color])
full-name (profile.utils/displayed-name profile)
profile-picture (profile.utils/photo profile)
emoji-string (string/join emoji-hash)]
[:<>
[header.shape/view
{:scroll-y scroll-y
:customization-color customization-color
:theme theme}]
[rn/view {:style style/avatar-row-wrapper}
[header.avatar/view
{:scroll-y scroll-y
:display-name full-name
:online? online?
:customization-color customization-color
:profile-picture profile-picture}]
[rn/view {:style {:margin-bottom 4}}
[quo/dropdown
{:background :blur
:size :size-32
:type :outline
:icon? true
:icon-name :i/online
:on-press not-implemented/alert}
(i18n/label :t/online)]]]
[quo/text-combinations
{:container-style style/title-container
:emoji-hash emoji-string
:title full-name}]]))
(def view (quo.theme/with-theme f-view))

View File

@ -0,0 +1,83 @@
(ns status-im2.contexts.profile.settings.list-items
(:require [status-im2.common.not-implemented :as not-implemented]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(def items
[[{:title (i18n/label :t/edit-profile)
:on-press not-implemented/alert
:image-props :i/edit
:image :icon
:action :arrow}
{:title (i18n/label :t/password)
:on-press not-implemented/alert
:image-props :i/password
:image :icon
:action :arrow}]
[{:title (i18n/label :t/messages)
:on-press not-implemented/alert
:image-props :i/messages
:image :icon
:action :arrow}
{:title (i18n/label :t/wallet)
:on-press not-implemented/alert
:image-props :i/wallet
:image :icon
:action :arrow}
{:title (i18n/label :t/dapps)
:on-press not-implemented/alert
:image-props :i/placeholder
:image :icon
:action :arrow}
{:title "Browser"
:on-press not-implemented/alert
:image-props :i/browser
:image :icon
:action :arrow}
{:title (i18n/label :t/keycard)
:on-press not-implemented/alert
:image-props :i/keycard
:image :icon
:action :arrow}]
[{:title (i18n/label :t/syncing)
:on-press not-implemented/alert
:image-props :i/syncing
:image :icon
:action :arrow}
{:title (i18n/label :t/notifications)
:on-press not-implemented/alert
:image-props :i/notifications
:image :icon
:action :arrow}
{:title (i18n/label :t/appearance)
:on-press not-implemented/alert
:image-props :i/light
:image :icon
:action :arrow}
{:title (i18n/label :t/language-and-currency)
:on-press not-implemented/alert
:image-props :i/globe
:image :icon
:action :arrow}]
[{:title (i18n/label :t/data-usage)
:on-press not-implemented/alert
:image-props :i/mobile
:image :icon
:action :arrow}
{:title (i18n/label :t/advanced)
:on-press not-implemented/alert
:image-props :i/settings
:image :icon
:action :arrow}]
;; temporary link to legacy settings
[{:title "Legacy settings"
:on-press #(rf/dispatch [:navigate-to :my-profile])
:action :arrow
:image :icon
:image-props :i/toggle}]
[{:title (i18n/label :t/about)
:on-press not-implemented/alert
:action :arrow}
{:title (i18n/label :t/status-help)
:on-press not-implemented/alert
:action :arrow}]])

View File

@ -0,0 +1,11 @@
(ns status-im2.contexts.profile.settings.style
(:require [quo.foundations.colors :as colors]))
(defn navigation-wrapper
[{:keys [customization-color inset theme]}]
{:padding-top inset
:background-color (colors/resolve-color customization-color theme 40)})
(def footer-container
{:padding-horizontal 20
:padding-vertical 12})

View File

@ -0,0 +1,71 @@
(ns status-im2.contexts.profile.settings.view
(:require [oops.core :as oops]
[quo.core :as quo]
[quo.theme :as quo.theme]
[react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[status-im2.common.not-implemented :as not-implemented]
[status-im2.contexts.profile.settings.header.view :as settings.header]
[status-im2.contexts.profile.settings.list-items :as settings.items]
[status-im2.contexts.profile.settings.style :as style]
[utils.debounce :as debounce]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
(defn- settings-item-view
[data]
[quo/category
{:list-type :settings
:blur? true
:data data}])
(defn scroll-handler
[event scroll-y]
(let [current-y (oops/oget event "nativeEvent.contentOffset.y")]
(reanimated/set-shared-value scroll-y current-y)))
(defn- footer
[logout-press]
[rn/view {:style style/footer-container}
[quo/button
{:on-press logout-press
:type :danger
:icon-left :i/log-out}
(i18n/label :t/logout)]])
(defn- settings-view
[theme]
(let [insets (safe-area/get-insets)
customization-color (rf/sub [:profile/customization-color])
scroll-y (reanimated/use-shared-value 0)
logout-press #(rf/dispatch [:multiaccounts.logout.ui/logout-pressed])]
[quo/overlay {:type :shell}
[rn/view
{:style (style/navigation-wrapper {:customization-color customization-color
:inset (:top insets)
:theme theme})}
[quo/page-nav
{:background :blur
:icon-name :i/close
:on-press #(rf/dispatch [:navigate-back])
:right-side [{:icon-name :i/multi-profile :on-press #(rf/dispatch [:open-modal :sign-in])}
{:icon-name :i/qr-code :on-press not-implemented/alert}
{:icon-name :i/share
:on-press #(debounce/dispatch-and-chill [:open-modal :share-shell] 1000)}]}]]
[rn/flat-list
{:header [settings.header/view {:scroll-y scroll-y}]
:data settings.items/items
:key-fn :title
:shows-vertical-scroll-indicator false
:render-fn settings-item-view
:footer [footer logout-press]
:scroll-event-throttle 16
:on-scroll #(scroll-handler % scroll-y)
:bounces false}]]))
(defn- internal-view
[props]
[:f> settings-view props])
(def view (quo.theme/with-theme internal-view))

View File

@ -8,8 +8,8 @@
(def descriptor
[{:key :title :type :text}
{:key :avatar :type :boolean}
{:key :description
:type :text}])
{:key :description :type :text}
{:key :emoji-hash :type :text}])
(defn state->text-combinations-props
[state]
@ -22,7 +22,8 @@
(let [state (reagent/atom {:title "Title"
:title-accessibility-label :title
:description ""
:description-accessibility-label :subtitle})]
:description-accessibility-label :subtitle
:emoji-hash "🐲🍀🎭🌟🚀🐠🌈🏰🔮🦉🐼🍉🎨🚲🌙🍔🌵"})]
(fn []
[preview/preview-container
{:state state

View File

@ -27,6 +27,7 @@
[status-im2.contexts.onboarding.syncing.results.view :as syncing-results]
[status-im2.contexts.onboarding.welcome.view :as welcome]
[status-im2.contexts.profile.profiles.view :as profiles]
[status-im2.contexts.profile.settings.view :as settings]
[status-im2.contexts.quo-preview.component-preview.view :as component-preview]
[status-im2.contexts.quo-preview.main :as quo.preview]
[status-im2.contexts.shell.activity-center.view :as activity-center]
@ -118,6 +119,10 @@
{:name :community-overview
:component communities.overview/overview}
{:name :settings
:options options/transparent-screen-options
:component settings/view}
{:name :settings-syncing
:options (merge options/dark-screen {:insets {:top? true}})
:component settings-syncing/view}

View File

@ -480,7 +480,7 @@
"done": "Done",
"edit": "Edit",
"edit-group": "Edit group",
"edit-profile": "Edit profile",
"edit-profile": "Edit Profile",
"emojihash": "Emojihash",
"emojihash-description": "A visual representation of your chat key. It will help other users recognize your profile.",
"emojis": "Emojis",
@ -1005,6 +1005,8 @@
"buy-crypto": "Buy crypto",
"buy-crypto-choose-a-service": "Choose a service you'd like to use to buy crypto",
"buy-crypto-leaving": "You are leaving Status and entering a third party website to complete your purchase",
"data-usage": "Data usage",
"language-and-currency": "Language and currency",
"opening-buy-crypto": "Opening {{site}}...",
"network": "Network",
"network-chain": "Network chain",
@ -1313,6 +1315,7 @@
"status-pending": "Pending",
"status-tx-not-found": "TX not found",
"status-sent": "Sent",
"status-help": "Status Help",
"status-not-sent-tap": "Not confirmed. Tap for options",
"status-not-sent-click": "Not confirmed. Click for options",
"step-i-of-n": "Step {{step}} of {{number}}",