Show collapsed header in communities

Fixes: #16123

This commit changes the behavior when joining communities:

1) If the user hasn't joined a community, they will see the
   non-collapsed header.
2) If the user has already joined the community, they will see a
   collapsed version of the header, in order to have quicker access to
   the chats of the community without having to scroll a lot.

One edge case that is taken care of is the following:
1) User visits a community that has not joined, requests to join.
2) The user is on the community page when the state changes from
   not-joined -> joined.

In this case the user won't see the collapsed header until they leave
the community view (go back to home say and back to communities).

This is done in order to avoid some janky transition between the non
collapsed & collapsed version of the header.

This is slightly different from as mentioned in the issue "visiting the
page for the 2nd time", as that will require larger changes but it
should be an acceptable behavior, since most of the times they will have
to visit the overview to request access.
This commit is contained in:
Andrea Maria Piana 2023-08-15 14:35:06 +01:00
parent 8c02291c0b
commit 70d8a90152
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
18 changed files with 273 additions and 204 deletions

View File

@ -0,0 +1,19 @@
(ns quo2.components.text-combinations.style)
(defn container
[container-style]
(merge
{:flex 1
:margin-horizontal 20}
container-style))
(def title-container
{:flex 1
:flex-direction :row
:align-items :center})
(def avatar-container
{:margin-right 9})
(def description-description-text
{:margin-top 8})

View File

@ -1,17 +0,0 @@
(ns quo2.components.text-combinations.title.style
(:require
[quo2.foundations.colors :as colors]))
(defn title-container
[container-style]
(merge
{:justify-content :center
:padding-horizontal 20}
container-style))
(def title-text
{:color colors/white})
(def subtitle-text
{:color colors/white
:margin-top 8})

View File

@ -1,26 +0,0 @@
(ns quo2.components.text-combinations.title.view
(:require
[quo2.components.markdown.text :as text]
[quo2.components.text-combinations.title.style :as style]
[react-native.core :as rn]))
(defn title
[{:keys [container-style
title
title-accessibility-label
subtitle
subtitle-accessibility-label]}]
[rn/view {:style (style/title-container container-style)}
[text/text
{:accessibility-label title-accessibility-label
:weight :semi-bold
:size :heading-1
:style style/title-text}
title]
(when subtitle
[text/text
{:accessibility-label subtitle-accessibility-label
:weight :regular
:size :paragraph-1
:style style/subtitle-text}
subtitle])])

View File

@ -0,0 +1,51 @@
(ns quo2.components.text-combinations.view
(:require
[quo2.theme :as theme]
[quo2.components.markdown.text :as text]
[quo2.components.text-combinations.style :as style]
[react-native.core :as rn]))
(defn icon
[source size]
[rn/image
{:source (if (string? source)
{:uri source}
source)
:style {:border-radius 50
:border-width 0
:border-color :transparent
:width size
:height size}}])
(defn view-internal
[{:keys [container-style
title
avatar
title-accessibility-label
description
description-props
description-accessibility-label]}]
[rn/view {:style (style/container container-style)}
[rn/view {:style style/title-container}
(when avatar
[rn/view {:style style/avatar-container}
[icon avatar 32]])
[text/text
{:accessibility-label title-accessibility-label
:weight :semi-bold
:ellipsize-mode :tail
:number-of-lines 1
:size :heading-1}
title]]
(case description
:description
[text/text
{:accessibility-label description-accessibility-label
:weight :regular
:size :paragraph-1
:style style/description-description-text}
description-props]
nil)])
(def view (theme/with-theme view-internal))

View File

@ -113,9 +113,9 @@
quo2.components.tags.tag
quo2.components.tags.tags
quo2.components.tags.token-tag
quo2.components.text-combinations.title.view
quo2.components.wallet.account-card.view
quo2.components.text-combinations.view
quo2.components.wallet.account-overview.view
quo2.components.wallet.account-card.view
quo2.components.wallet.keypair.view
quo2.components.wallet.network-amount.view
quo2.components.wallet.network-bridge.view
@ -319,8 +319,8 @@
(def context-tag quo2.components.tags.context-tag.view/view)
(def number-tag quo2.components.tags.number-tag.view/view)
;;;; Title
(def title quo2.components.text-combinations.title.view/title)
;;;; Text combinations
(def text-combinations quo2.components.text-combinations.view/view)
;;;; Wallet
(def account-card quo2.components.wallet.account-card.view/view)

View File

@ -5,7 +5,7 @@
(defn image-slider
[size]
{:top (if platform/ios? 0 -64)
{:top -64
:height size
:width size
:z-index 4

View File

@ -2,14 +2,13 @@
(:require [oops.core :as oops]
[quo2.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.common.scroll-page.style :as style]
[utils.re-frame :as rf]
[react-native.reanimated :as reanimated]))
(def negative-scroll-position-0 (if platform/ios? -44 0))
(def scroll-position-0 (if platform/ios? 44 0))
(def negative-scroll-position-0 0)
(def scroll-position-0 0)
(defn diff-with-max-min
[value maximum minimum]
@ -19,10 +18,15 @@
(max minimum)
(min maximum)))
(defn page-header-threshold
[collapsed?]
(if collapsed? 50 170))
(defn f-scroll-page-header
[scroll-height height name page-nav-right-side logo sticky-header top-nav title-colum navigate-back?]
(let [input-range (if platform/ios? [-47 10] [0 10])
output-range (if platform/ios? [-208 0] [-208 -45])
[scroll-height height name page-nav-right-side logo sticky-header top-nav title-colum navigate-back?
collapsed?]
(let [input-range [0 10]
output-range [-208 -45]
y (reanimated/use-shared-value scroll-height)
translate-animation (reanimated/interpolate y
input-range
@ -30,13 +34,13 @@
{:extrapolateLeft "clamp"
:extrapolateRight "clamp"})
opacity-animation (reanimated/use-shared-value 0)
threshold (if platform/ios? 30 170)]
threshold (page-header-threshold collapsed?)]
(rn/use-effect
#(do
(reanimated/set-shared-value y scroll-height)
(reanimated/set-shared-value opacity-animation
(reanimated/with-timing (if (>= scroll-height threshold) 1 0)
(clj->js {:duration 300}))))
(fn []
(reanimated/set-shared-value y scroll-height)
(reanimated/set-shared-value opacity-animation
(reanimated/with-timing (if (>= scroll-height threshold) 1 0)
(clj->js {:duration 300}))))
[scroll-height])
[:<>
[reanimated/blur-view
@ -62,7 +66,7 @@
:style {:line-height 21}}
name]])
(if top-nav
[rn/view {:style {:margin-top (if platform/ios? 44 0)}}
[rn/view {:style {:margin-top 0}}
top-nav]
[quo/page-nav
(cond-> {:margin-top 44
@ -80,7 +84,7 @@
(defn f-display-picture
[scroll-height cover]
(let [input-range (if platform/ios? [-67 10] [0 150])
(let [input-range [0 150]
y (reanimated/use-shared-value scroll-height)
animation (reanimated/interpolate y
input-range
@ -101,25 +105,27 @@
[_ _ _]
(let [scroll-height (reagent/atom negative-scroll-position-0)]
(fn [{:keys [name cover-image logo page-nav-right-section-buttons on-scroll
collapsed?
height top-nav title-colum background-color navigate-back?]}
sticky-header
children]
[:<>
[:f> f-scroll-page-header @scroll-height height name page-nav-right-section-buttons
logo sticky-header top-nav title-colum navigate-back?]
logo sticky-header top-nav title-colum navigate-back? collapsed?]
[rn/scroll-view
{:content-container-style {:flex-grow 1}
:shows-vertical-scroll-indicator false
:scroll-event-throttle 16
:on-scroll (fn [^js event]
(reset! scroll-height (int
(oops/oget
event
"nativeEvent.contentOffset.y")))
(when on-scroll
(on-scroll @scroll-height)))}
{:content-container-style {:flex-grow 1}
:content-inset-adjustment-behavior :never
:shows-vertical-scroll-indicator false
:scroll-event-throttle 16
:on-scroll (fn [^js event]
(reset! scroll-height (int
(oops/oget
event
"nativeEvent.contentOffset.y")))
(when on-scroll
(on-scroll @scroll-height)))}
(when cover-image
[rn/view {:style {:height 151}}
[rn/view {:style {:height (if collapsed? 110 151)}}
[rn/image
{:source cover-image
;; Using negative margin-bottom as a workaround because on Android,
@ -131,6 +137,6 @@
[rn/view
{:style (style/children-container {:border-radius (diff-with-max-min @scroll-height 16 0)
:background-color background-color})}
(when cover-image
(when (and (not collapsed?) cover-image)
[:f> f-display-picture @scroll-height logo])
children])]])))

View File

@ -4,7 +4,6 @@
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.contexts.communities.actions.community-options.view :as options]
[status-im.ui.components.react :as react]
@ -212,13 +211,9 @@
colors/white
colors/neutral-95)
:navigate-back? :true
:height (if platform/ios?
(if (> @scroll-height 360)
156
100)
(if (> @scroll-height 360)
208
148))}
:height (if (> @scroll-height 360)
208
148)}
[render-sticky-header
{:selected-tab selected-tab
:scroll-height scroll-height}]

View File

@ -4,7 +4,6 @@
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[react-native.core :as rn]
[react-native.platform :as platform]
[reagent.core :as reagent]
[status-im2.common.home.actions.view :as actions]
[status-im2.common.password-authentication.view :as password-authentication]
@ -69,15 +68,13 @@
channels-list]
[rn/view
{:on-layout #(on-first-channel-height-changed
(+ (if platform/ios? 0 38)
(int (Math/ceil (layout-y %))))
(+ 38 (int (Math/ceil (layout-y %))))
(into #{} (map (comp :name second) channels-list)))
:style {:margin-top 20 :flex 1}}
:style {:margin-top 8 :flex 1}}
(doall
(for [[category-id {:keys [chats name collapsed?]}] channels-list]
[rn/view
{:style {:flex 1}
:key category-id
{:key category-id
;; on-layout fires only when the component re-renders, so
;; in case the category hasn't changed, it will not be fired
:on-layout #(on-category-layout name (int (layout-y %)))}
@ -235,18 +232,22 @@
[category (update v :chats add-on-press)])
categorized-chats)))
(defn community-header
[name]
[quo/text
{:accessibility-label :chat-name-text
:number-of-lines 1
:ellipsize-mode :tail
:weight :semi-bold
:size :heading-1
:style {:margin-top (+ scroll-page.style/picture-radius
scroll-page.style/picture-border-width
12)}}
name])
[title logo]
[quo/text-combinations
{:container-style
{:margin-horizontal 0
:padding-right 20
:margin-top
(if logo
12
(+ scroll-page.style/picture-radius
scroll-page.style/picture-border-width
12))}
:avatar logo
:title title
:title-accessibility-label :chat-name-text}])
(defn community-description
[description]
@ -260,20 +261,25 @@
description])
(defn community-content
[{:keys [name description joined tags color id]
[{:keys [name description joined images tags color id]
:as community}
pending?
{:keys [on-category-layout on-first-channel-height-changed]}]
{:keys [on-category-layout
collapsed?
on-first-channel-height-changed]}]
(let [chats-by-category (rf/sub [:communities/categorized-channels id])]
[:<>
[rn/view {:style style/community-content-container}
[status-tag pending? joined]
[community-header name]
[community-description description]
[quo/community-tags
{:tags tags
:last-item-style style/last-community-tag
:container-style style/community-tag-container}]
(when-not collapsed?
[status-tag pending? joined])
[community-header name (when collapsed? (get-in images [:thumbnail :uri]))]
(when-not collapsed?
[community-description description])
(when-not collapsed?
[quo/community-tags
{:tags tags
:last-item-style style/last-community-tag
:container-style style/community-tag-container}])
[join-community community pending?]]
[channel-list-component
{:on-category-layout on-category-layout
@ -311,37 +317,41 @@
(and (>= scroll-height (+ height first-channel-height))
category)))))
(defn community-card-page-view
[]
(let [categories-heights (reagent/atom {})
(defn community-scroll-page
[{:keys [joined]}]
(let [scroll-height (reagent/atom 0)
categories-heights (reagent/atom {})
first-channel-height (reagent/atom 0)
scroll-height (reagent/atom 0)]
(fn [id]
(let [{:keys [name images id]
:as community} (rf/sub [:communities/community id])
pending? (rf/sub [:communities/my-pending-request-to-join id])
cover {:uri (get-in images [:banner :uri])}
logo {:uri (get-in images [:thumbnail :uri])}]
;; We track the initial value of joined
;; as we open the page to avoid switching
;; from not collapsed to collapsed if the
;; user is on this page
initial-joined? joined]
(fn [{:keys [id name images] :as community} pending?]
(let [cover {:uri (get-in images [:banner :uri])}
logo {:uri (get-in images [:thumbnail :uri])}
collapsed? (and initial-joined? (:joined community))]
[scroll-page/scroll-page
{:cover-image cover
:collapsed? collapsed?
:logo logo
:page-nav-right-section-buttons (page-nav-right-section-buttons id)
:name name
:on-scroll #(reset! scroll-height %)
:navigate-back? true
:background-color (colors/theme-colors colors/white colors/neutral-95)
:height (if platform/ios? 100 148)}
:height 148}
[sticky-category-header
{:enabled (> @scroll-height @first-channel-height)
:label (pick-first-category-by-height
@scroll-height
@first-channel-height
@categories-heights)}]
[community-content
community
pending?
{:on-category-layout (partial add-category-height categories-heights)
:collapsed? collapsed?
:on-first-channel-height-changed
;; Here we set the height of the component and we filter out the
;; categories, as some might have been removed
@ -349,6 +359,13 @@
(swap! categories-heights select-keys categories)
(reset! first-channel-height height))}]]))))
(defn community-card-page-view
[id]
(let [{:keys [id]
:as community} (rf/sub [:communities/community id])
pending? (rf/sub [:communities/my-pending-request-to-join id])]
[community-scroll-page community pending?]))
(defn overview
[id]
(let [id (or id (rf/sub [:get-screen-params :community-overview]))

View File

@ -12,12 +12,13 @@
(defn page-title
[]
[quo/title
{:container-style {:margin-top 12}
:title (i18n/label :t/enable-biometrics)
:title-accessibility-label :enable-biometrics-title
:subtitle (i18n/label :t/use-biometrics)
:subtitle-accessibility-label :enable-biometrics-sub-title}])
[quo/text-combinations
{:container-style {:margin-top 12}
:title (i18n/label :t/enable-biometrics)
:title-accessibility-label :enable-biometrics-title
:description :description
:description-props (i18n/label :t/use-biometrics)
:description-accessibility-label :enable-biometrics-sub-title}])
(defn enable-biometrics-buttons
[insets]

View File

@ -11,12 +11,13 @@
(defn page-title
[]
[quo/title
{:container-style {:margin-top 12}
:title (i18n/label :t/intro-wizard-title6)
:title-accessibility-label :notifications-title
:subtitle (i18n/label :t/enable-notifications-sub-title)
:subtitle-accessibility-label :notifications-sub-title}])
[quo/text-combinations
{:container-style {:margin-top 12}
:title (i18n/label :t/intro-wizard-title6)
:title-accessibility-label :notifications-title
:description :description
:description-props (i18n/label :t/enable-notifications-sub-title)
:description-accessibility-label :notifications-sub-title}])
(defn enable-notification-buttons
[{:keys [insets]}]

View File

@ -11,17 +11,17 @@
(defn generate-keys-title
[]
[quo/title
[quo/text-combinations
{:title (i18n/label :t/generating-keys)}])
(defn saving-keys-title
[]
[quo/title
[quo/text-combinations
{:title (i18n/label :t/saving-keys-to-device)}])
(defn keys-saved-title
[]
[quo/title
[quo/text-combinations
{:title (i18n/label :t/keys-saved)}])
(def first-transition-delay-ms 2000)

View File

@ -12,16 +12,17 @@
(defn page-title
[pairing-progress?]
[quo/title
{:container-style {:margin-top 56}
:title (i18n/label (if pairing-progress?
:t/sync-devices-title
:t/sync-devices-error-title))
:subtitle (i18n/label (if pairing-progress?
:t/sync-devices-sub-title
:t/sync-devices-error-sub-title))
:title-accessibility-label :progress-screen-title
:subtitle-accessibility-label :progress-screen-sub-title}])
[quo/text-combinations
{:container-style {:margin-top 56}
:title (i18n/label (if pairing-progress?
:t/sync-devices-title
:t/sync-devices-error-title))
:description :description
:description-props (i18n/label (if pairing-progress?
:t/sync-devices-sub-title
:t/sync-devices-error-sub-title))
:title-accessibility-label :progress-screen-title
:description-accessibility-label :progress-screen-sub-title}])
(defn try-again-button
[profile-color in-onboarding?]

View File

@ -13,11 +13,12 @@
(defn page-title
[]
[quo/title
{:title (i18n/label :t/sync-devices-complete-title)
:title-accessibility-label :sync-devices-title
:subtitle (i18n/label :t/sync-devices-complete-sub-title)
:subtitle-accessibility-label :sync-devices-complete-sub-title}])
[quo/text-combinations
{:title (i18n/label :t/sync-devices-complete-title)
:title-accessibility-label :sync-devices-title
:description :description
:description-props (i18n/label :t/sync-devices-complete-sub-title)
:description-accessibility-label :sync-devices-complete-sub-title}])
(defn current-device
[installation]

View File

@ -11,14 +11,15 @@
(defn page-title
[]
(let [new-account? (rf/sub [:onboarding-2/new-account?])]
[quo/title
{:container-style {:margin-top 12}
:title (i18n/label (if new-account?
:t/welcome-to-web3
:t/welcome-back))
:title-accessibility-label :welcome-title
:subtitle (i18n/label :t/welcome-to-web3-sub-title)
:subtitle-accessibility-label :welcome-sub-title}]))
[quo/text-combinations
{:container-style {:margin-top 12}
:title (i18n/label (if new-account?
:t/welcome-to-web3
:t/welcome-back))
:title-accessibility-label :welcome-title
:description :description
:description-props (i18n/label :t/welcome-to-web3-sub-title)
:description-accessibility-label :welcome-sub-title}]))
(defn dispatch-visibility-status-update
[status-type]

View File

@ -109,7 +109,7 @@
[status-im2.contexts.quo-preview.tags.status-tags :as status-tags]
[status-im2.contexts.quo-preview.tags.tags :as tags]
[status-im2.contexts.quo-preview.tags.token-tag :as token-tag]
[status-im2.contexts.quo-preview.title.title :as title]
[status-im2.contexts.quo-preview.text-combinations.preview :as text-combinations]
[status-im2.contexts.quo-preview.keycard.keycard :as keycard]
[status-im2.contexts.quo-preview.loaders.skeleton-list :as skeleton-list]
[status-im2.contexts.quo-preview.community.channel-actions :as channel-actions]
@ -348,8 +348,8 @@
:component status-tags/preview-status-tags}
{:name :token-tag
:component token-tag/preview-token-tag}]
:text-combinations [{:name :title
:component title/preview-title}]
:text-combinations [{:name :text-combinations
:component text-combinations/preview}]
:wallet [{:name :account-card
:component account-card/preview-account-card}
{:name :account-overview

View File

@ -0,0 +1,61 @@
(ns status-im2.contexts.quo-preview.text-combinations.preview
(:require [quo2.components.text-combinations.view :as quo2]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.common.resources :as resources]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Title"
:key :title
:type :text}
{:label :avatar
:key :avatar
:type :boolean}
{:label "Description type:"
:key :description
:type :select
:options [{:key :none
:value nil}
{:key :description
:value :description}]}
{:label "Description text"
:key :description-props
:type :text}])
(defn state->text-combinations-props
[state]
(if (:avatar state)
(assoc state :avatar (resources/get-mock-image :user-picture-male4))
state))
(defn cool-preview
[]
(let [state (reagent/atom {:title "Title"
:title-accessibility-label :title
:description nil
:description-props ""
:description-accessibility-label :subtitle})]
(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}
[quo2/view
(state->text-combinations-props @state)]]]])))
(defn preview
[]
[rn/view
{:background-color (colors/theme-colors colors/white colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
:flex-grow 1
:nested-scroll-enabled true
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])

View File

@ -1,42 +0,0 @@
(ns status-im2.contexts.quo-preview.title.title
(:require [quo2.components.text-combinations.title.view :as quo2]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor
[{:label "Title"
:key :title
:type :text}
{:label "Subtitle"
:key :subtitle
:type :text}])
(defn cool-preview
[]
(let [state (reagent/atom {:title "Title"
:title-accessibility-label :title
:subtitle ""
:subtitle-accessibility-label :subtitle})]
(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}
[quo2/title @state]]]])))
(defn preview-title
[]
[rn/view
{:background-color (colors/theme-colors colors/white colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
:flex-grow 1
:nested-scroll-enabled true
:keyboard-should-persist-taps :always
:header [cool-preview]
:key-fn str}]])