Compare commits

...
Author SHA1 Message Date
Omar Basem dd7c8b9363 update blur 2023-03-06 14:11:38 +04:00
Omar Basem 1942a320fa fix prop name 2023-03-06 13:59:23 +04:00
Omar Basem cd8622a7f6 lint 2023-03-06 13:59:23 +04:00
Omar Basem c5aa75c925 feat: activity centre animations
updates

updates

updates

updates

updates

updates

updates

updates
2023-03-06 13:59:23 +04:00
Parvesh Monu f314806b83 Improve profile card (#15264) 2023-03-06 14:24:34 +05:30
13 changed files with 254 additions and 120 deletions
@@ -28,4 +28,12 @@
<item name="android:textColorPrimary">@color/alert_text</item>
<item name="android:background">@color/alert_background</item>
</style>
<style name="Theme.FullScreenDialog">
<item name="android:windowNoTitle">true</item>
<item name="android:windowIsFloating">false</item>
<item name="android:windowBackground">@android:color/transparent</item>
<item name="android:statusBarColor">@android:color/transparent</item>
<item name="android:navigationBarColor">@android:color/transparent</item>
</style>
</resources>
+1
View File
@@ -60,6 +60,7 @@
"react-native-linear-gradient": "^2.5.6",
"react-native-lottie-splash-screen": "^1.0.1",
"react-native-mail": "^6.1.1",
"react-native-modal": "^13.0.1",
"react-native-navigation": "^7.27.1",
"react-native-orientation-locker": "^1.5.0",
"react-native-permissions": "^2.1.5",
+4
View File
@@ -338,6 +338,9 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
(clj->js {:default #js {}
:useDeviceOrientationChange #js {}}))
(def react-native-modal
(clj->js {:default #js {}}))
(def wallet-connect-client
#js
{:default #js {}
@@ -404,6 +407,7 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
"@react-native-async-storage/async-storage" async-storage
"react-native-svg" react-native-svg
"react-native-orientation-locker" react-native-orientation-locker
"react-native-modal" react-native-modal
"../src/js/worklet_factory.js" worklet-factory
"../src/js/shell_worklets.js" shell-worklets
"../src/js/bottom_sheet.js" bottom-sheet
@@ -2,12 +2,14 @@
(:require [quo2.foundations.colors :as colors]))
(defn card-container
[customization-color]
{:flex-direction :column
:padding 12
:flex 1
:border-radius 16
:background-color (colors/custom-color customization-color 50 40)})
[customization-color padding-bottom]
{:flex-direction :column
:padding-horizontal 12
:padding-top 12
:padding-bottom padding-bottom
:flex 1
:border-radius 16
:background-color (colors/custom-color customization-color 50 40)})
(def card-header
{:flex-direction :row
@@ -16,25 +18,23 @@
(def name-container
{:flex-direction :row
:margin-top 8
:margin-bottom 2
:align-items :center
:padding-right 12})
(def user-name
{:margin-right 4
:color colors/white})
{:color colors/white})
(def emoji-hash
{:margin-top 10})
{:margin-top 12})
(def user-hash
{:color colors/white-opa-60})
(def sign-button
{:margin-top 14})
{:margin-top 2
:color colors/white-opa-60})
(def keycard-icon
{:color colors/white-opa-40})
{:margin-left 4
:color colors/white-opa-40})
(def option-button
{:background-color colors/white-opa-5})
{:background-color colors/white-opa-5
:margin-left 8})
@@ -1,63 +1,80 @@
(ns quo2.components.profile.profile-card.view
(:require
[quo2.components.profile.profile-card.style :as style]
[quo2.foundations.colors :as colors]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.icon :as icon]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[react-native.core :as rn]))
(:require [utils.i18n :as i18n]
[react-native.core :as rn]
[quo2.components.icon :as icon]
[quo2.components.tags.tag :as tag]
[quo2.foundations.colors :as colors]
[quo2.components.markdown.text :as text]
[quo2.components.buttons.button :as button]
[quo2.components.avatars.user-avatar :as user-avatar]
[quo2.components.profile.profile-card.style :as style]))
(defn profile-card
[{:keys [show-sign-profile? key-card? profile-picture name hash customization-color sign-label
emoji-hash on-press-dots on-press-sign show-emoji-hash?]
:or {show-sign-profile? false
show-emoji-hash? false
customization-color :turquoise
key-card? false}}]
[rn/view
{:style (style/card-container customization-color)}
[{:keys [key-card? profile-picture name hash customization-color
emoji-hash on-options-press show-emoji-hash? padding-bottom
show-options-button? show-user-hash? show-logged-in? on-card-press]
:or {show-emoji-hash? false
show-user-hash? false
customization-color :turquoise
show-options-button? false
show-logged-in? false
key-card? false}}]
[rn/touchable-without-feedback
{:on-press on-card-press
:flex 1
:accessibility-label :profile-card}
[rn/view
{:style style/card-header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
:override-theme :dark
:size :medium
:status-indicator? false}]
[button/button
{:size 32
:type :blur-bg
:icon true
:override-theme :dark
:style style/option-button
:on-press on-press-dots}
:i/options]]
[rn/view
{:style style/name-container}
[text/text
{:size :heading-2
:weight :semi-bold
:number-of-lines 1
:style style/user-name} name]
(when key-card?
(icon/icon
:i/keycard
style/keycard-icon))]
[text/text
{:weight :monospace
:number-of-lines 1
:style style/user-hash} hash]
(when (and show-emoji-hash? emoji-hash)
(style/card-container
customization-color
(or padding-bottom (if show-emoji-hash? 12 10)))
[rn/view
{:style style/card-header}
[user-avatar/user-avatar
{:full-name name
:profile-picture profile-picture
:override-theme :dark
:size :medium
:status-indicator? false}]
[rn/view {:flex-direction :row}
(when show-logged-in?
[tag/tag
{:type :icon
:size 32
:blurred? true
:labelled? true
:resource :main-icons2/check
:accessibility-label :logged-in-tag
:icon-color colors/success-50
:override-theme :dark
:label (i18n/label :t/logged-in)}])
(when show-options-button?
[button/button
{:size 32
:type :blur-bg
:icon true
:override-theme :dark
:style style/option-button
:on-press on-options-press
:accessibility-label :profile-card-options}
:i/options])]]
[rn/view
{:style style/name-container}
[text/text
{:weight :monospace
{:size :heading-2
:weight :semi-bold
:number-of-lines 1
:style style/emoji-hash} emoji-hash])
(when show-sign-profile?
[button/button
{:on-press on-press-sign
:type :community
:community-color (colors/custom-color customization-color 60)
:community-text-color colors/white
:style style/sign-button} sign-label])])
:style style/user-name} name]
(when key-card?
(icon/icon
:i/keycard
style/keycard-icon))]
(when show-user-hash?
[text/text
{:weight :monospace
:number-of-lines 1
:style style/user-hash} hash])
(when (and show-emoji-hash? emoji-hash)
[text/text
{:weight :monospace
:number-of-lines 1
:style style/emoji-hash} emoji-hash])]])
+2 -2
View File
@@ -83,13 +83,13 @@
- `labelled` boolean: is true if tag has label else false"
[_ _]
(fn [{:keys [id on-press disabled? size resource active accessibility-label
label type labelled? blurred? icon-color]
label type labelled? blurred? icon-color override-theme]
:or {size 32}}]
(let [state (cond disabled? :disabled
active :active
:else :default)
{:keys [border-color blurred-border-color text-color]}
(get-in themes [(theme/get-theme) state])]
(get-in themes [(or override-theme (theme/get-theme)) state])]
[rn/view {:style {:align-items :center}}
[base-tag/base-tag
{:id id
+3 -1
View File
@@ -1,6 +1,7 @@
(ns react-native.core
(:require ["react" :as react]
["react-native" :as react-native]
["react-native-modal" :default Modal]
[cljs-bean.core :as bean]
[oops.core :as oops]
[react-native.flat-list :as flat-list]
@@ -31,7 +32,8 @@
(def activity-indicator (reagent/adapt-react-class (.-ActivityIndicator ^js react-native)))
(def modal (reagent/adapt-react-class (.-Modal ^js react-native)))
;; "react-native-modal" is a superset to the Modal component from RN, no need to define it separately
(def modal (reagent/adapt-react-class Modal))
(def keyboard ^js (.-Keyboard ^js react-native))
+40 -4
View File
@@ -3,8 +3,12 @@
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.hole-view :as hole-view]
[react-native.navigation :as navigation]
[reagent.core :as reagent]
[status-im2.common.home.style :as style]
[status-im2.common.plus-button.view :as components.plus-button]
[status-im2.contexts.activity-center.view :as ac]
[status-im2.contexts.shell.animation :as shell]
[utils.re-frame :as rf]))
(defn title-column
@@ -39,6 +43,29 @@
button-common-props)
icon])
(defn ac-modal
[visible? view-id]
(let [status-bar-style (if (or (colors/dark?)
(not (shell/home-stack-open?)))
:light
:dark)
close-modal (fn []
(reset! visible? false)
(navigation/merge-options (clj->js view-id)
(clj->js {:statusBar {:style status-bar-style}})))]
[rn/modal
{:visible @visible?
:cover-screen true
:transparent true
:status-bar-translucent true
:hardware-accelerated true
:animation-type :slide
:style {:margin 0
:width "100%"}
:on-back-button-press close-modal}
[ac/view close-modal]]))
(defn top-nav
"[top-nav opts]
opts
@@ -51,8 +78,18 @@
notif-count (rf/sub [:activity-center/unread-count])
new-notifications? (pos? notif-count)
notification-indicator :unread-dot
counter-label "0"]
counter-label "0"
visible? (reagent/atom false)
view-id (rf/sub [:view-id])
open-ac (fn []
;; delaying status-bar style update looks nicer
(js/setTimeout
#(navigation/merge-options (clj->js view-id)
(clj->js {:statusBar {:style :light}}))
20)
(reset! visible? (not @visible?)))]
[rn/view {:style (assoc style :height 56)}
[ac-modal visible? view-id]
;; Left Section
[rn/touchable-without-feedback {:on-press #(rf/dispatch [:navigate-to :my-profile])}
[rn/view
@@ -75,7 +112,7 @@
[base-button :i/search #() :open-search-button button-common-props])
[base-button :i/scan #() :open-scanner-button button-common-props]
[base-button :i/qr-code #() :show-qr-button button-common-props]
[rn/view ;; Keep view instead of "[:<>" to make sure relative
[rn/view ;; Keep view instead of "[:<>" to make sure relative
;; position is calculated from this view instead of its parent
[hole-view/hole-view
{:key new-notifications? ;; Key is required to force removal of holes
@@ -88,8 +125,7 @@
:else
[{:x 33 :y -7 :width 18 :height 18 :borderRadius 7}])}
[base-button :i/activity-center #(rf/dispatch [:activity-center/open])
:open-activity-center-button button-common-props]]
[base-button :i/activity-center open-ac :open-activity-center-button button-common-props]]
(when new-notifications?
(if (= notification-indicator :counter)
[quo/counter
@@ -1,5 +1,6 @@
(ns status-im2.contexts.activity-center.style
(:require [quo2.foundations.colors :as colors]))
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(def screen-padding 20)
@@ -60,3 +61,25 @@
:height 120
:background-color colors/danger-50
:margin-bottom 20})
(def blur-background
{:position :absolute
:background-color colors/neutral-80-opa-80
:top 0
:bottom 0
:left 0
:right 0})
(defn options-content-container
[bottom-inset]
{:background-color colors/neutral-100
:padding-bottom (if platform/ios? bottom-inset 20)
:padding-top 20
:border-top-left-radius 20
:border-top-right-radius 20})
(def options-modal-container
{:justify-content :flex-end
:margin 0
:width "100%"
:align-self :center})
@@ -4,6 +4,7 @@
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.contexts.activity-center.notification-types :as types]
[status-im2.contexts.activity-center.notification.admin.view :as admin]
[status-im2.contexts.activity-center.notification.contact-requests.view :as contact-requests]
@@ -14,6 +15,7 @@
[status-im2.contexts.activity-center.notification.reply.view :as reply]
[status-im2.contexts.activity-center.style :as style]
[utils.i18n :as i18n]
[react-native.blur :as blur]
[utils.re-frame :as rf]))
(defn filter-selector-read-toggle
@@ -28,27 +30,44 @@
:all
:unread)}])}]))
(defn options-bottom-sheet-content
[]
(defn options-content
[bottom-inset]
(let [unread-count (rf/sub [:activity-center/unread-count])]
[quo/action-drawer
[[{:icon :i/check
:override-theme :dark
:label (i18n/label :t/mark-all-notifications-as-read)
:on-press (fn []
(if (pos? unread-count)
(rf/dispatch [:activity-center.notifications/mark-all-as-read-locally
(fn []
{:icon :up-to-date
:icon-color colors/success-50
:text (i18n/label :t/notifications-marked-as-read
{:count unread-count})
:override-theme :dark})])
;; Need design improvements if there is NO unread
;; notifications to mark as read
;; https://github.com/status-im/status-mobile/issues/14983
(js/alert "No unread notifications to mark as read"))
(rf/dispatch [:bottom-sheet/hide]))}]]]))
[rn/view
{:style (style/options-content-container bottom-inset)}
[quo/action-drawer
[[{:icon :i/check
:override-theme :dark
:label (i18n/label :t/mark-all-notifications-as-read)
:on-press (fn []
(if (pos? unread-count)
(rf/dispatch [:activity-center.notifications/mark-all-as-read-locally
(fn []
{:icon :up-to-date
:icon-color colors/success-50
:text (i18n/label :t/notifications-marked-as-read
{:count unread-count})
:override-theme :dark})])
;; Need design improvements if there is NO unread
;; notifications to mark as read
;; https://github.com/status-im/status-mobile/issues/14983
(js/alert "No unread notifications to mark as read"))
(rf/dispatch [:bottom-sheet/hide]))}]]]]))
(defn options-bottom-sheet
[visible? bottom-inset]
;; not using the `bottom-sheet` component as it renders behind the full screen `Modal` component on
;; Android
[rn/modal
{:is-visible @visible?
:use-native-driver true
:use-native-driver-for-backdrop true
:hide-modal-content-while-animating true
:backdrop-opacity 0.5
:on-backdrop-press #(reset! visible? false)
:style style/options-modal-container}
[options-content bottom-inset]])
(defn empty-tab
[]
@@ -134,7 +153,7 @@
(contains? types-with-unread types/system))}]}]))
(defn header
[request-close]
[request-close open-options]
[rn/view
[rn/view {:style style/header-container}
[quo/button
@@ -151,9 +170,7 @@
:size 32
:accessibility-label :activity-center-open-more
:override-theme :dark
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content options-bottom-sheet-content
:override-theme :dark}])}
:on-press open-options}
:i/options]]
[quo/text
{:size :heading-1
@@ -203,7 +220,8 @@
(defn view
[request-close]
(let [active-swipeable (atom nil)]
(let [active-swipeable (atom nil)
visible? (reagent/atom false)]
[:f>
(fn []
(rn/use-effect-once #(rf/dispatch [:activity-center.notifications/fetch-first-page]))
@@ -212,7 +230,11 @@
(let [notifications (rf/sub [:activity-center/notifications])
window-width (rf/sub [:dimensions/window-width])]
[rn/view {:style (style/screen-container window-width top bottom)}
[header request-close]
[blur/view
{:blurAmount 5
:style style/blur-background}]
[options-bottom-sheet visible? bottom]
[header request-close #(reset! visible? true)]
[rn/flat-list
{:data notifications
:render-data active-swipeable
@@ -7,15 +7,21 @@
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Show: Sign in to this profile?"
:key :show-sign-profile?
:type :boolean}
{:label "Show: Is from key card?"
[{:label "Show: Is from key card?"
:key :key-card?
:type :boolean}
{:label "Show: Emoji hash?"
:key :show-emoji-hash?
:type :boolean}
{:label "Show: User hash?"
:key :show-user-hash?
:type :boolean}
{:label "Show: Options Button?"
:key :show-options-button?
:type :boolean}
{:label "Show: Logged In?"
:key :show-logged-in?
:type :boolean}
{:label "Customization Color"
:key :customization-color
:type :select
@@ -51,22 +57,21 @@
:type :text}
{:label "Emoji hash"
:key :emoji-hash
:type :text}
{:label "Sign button label"
:key :sign-label
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom {:show-sign-profile? true
:key-card? true
(let [state (reagent/atom {:key-card? false
:name "Matt Grote"
:sign-label "Sign in to this profile"
:on-press-dots nil
:on-options-press nil
:on-card-press nil
:show-options-button? true
:show-logged-in? true
:show-user-hash? false
:on-press-sign nil
:customization-color :turquoise
:profile-picture (resources/get-mock-image :user-picture-male5)
:show-emoji-hash? true
:show-emoji-hash? false
:hash "zQ3k83euenmcikw7474hfu73t5N"
:emoji-hash "😄😂🫣🍑😇🤢😻🥷🏻🦸🏻‍♀️🦸🏻🦸🏻‍♂️🦹🏻‍♀️🧑🏻‍🎄🎅🏻"})]
(fn []
+2 -1
View File
@@ -1975,5 +1975,6 @@
"strength-divider-weak-label": "Weak",
"strength-divider-okay-label": "Okay",
"strength-divider-strong-label": "Strong",
"strength-divider-very-strong-label": "Very strong"
"strength-divider-very-strong-label": "Very strong",
"logged-in": "Logged in"
}
+15
View File
@@ -9330,6 +9330,13 @@ react-lifecycles-compat@2.0.0:
resolved "https://registry.yarnpkg.com/react-lifecycles-compat/-/react-lifecycles-compat-2.0.0.tgz#71d9c4cde47114c4102454f76da055c2bc48c948"
integrity sha512-txfpPCQYiazVdcbMRhatqWKcAxJweUu2wDXvts5/7Wyp6+Y9cHojqXHsLPEckzutfHlxZhG8Oiundbmp8Fd6eQ==
react-native-animatable@1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/react-native-animatable/-/react-native-animatable-1.3.3.tgz#a13a4af8258e3bb14d0a9d839917e9bb9274ec8a"
integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==
dependencies:
prop-types "^15.7.2"
react-native-background-timer@^2.1.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/react-native-background-timer/-/react-native-background-timer-2.2.0.tgz#ff82d30899209b924983cc00e6ce174b8de5054a"
@@ -9458,6 +9465,14 @@ react-native-mail@^6.1.1:
resolved "https://registry.yarnpkg.com/react-native-mail/-/react-native-mail-6.1.1.tgz#f1b1f8034c84d2510a93e4a2a795f0db5a13595e"
integrity sha512-pTs180wwyh7hN/iyTC9SfOX579U4YhDlHOLxi47IGvhPJENqO/QFdBq+wWKxyhNqdQuVSy+LoeIxLreWnIeYmg==
react-native-modal@^13.0.1:
version "13.0.1"
resolved "https://registry.yarnpkg.com/react-native-modal/-/react-native-modal-13.0.1.tgz#691f1e646abb96fa82c1788bf18a16d585da37cd"
integrity sha512-UB+mjmUtf+miaG/sDhOikRfBOv0gJdBU2ZE1HtFWp6UixW9jCk/bhGdHUgmZljbPpp0RaO/6YiMmQSSK3kkMaw==
dependencies:
prop-types "^15.6.2"
react-native-animatable "1.3.3"
react-native-navigation@^7.27.1:
version "7.27.1"
resolved "https://registry.yarnpkg.com/react-native-navigation/-/react-native-navigation-7.27.1.tgz#90bfac2a400109cc036394b4ee807a997da6a7b4"