Improve home animations (#15247)

This commit is contained in:
flexsurfer 2023-03-13 19:47:04 +01:00 committed by GitHub
parent 4810e1d7bf
commit 0fe6fea7e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 493 additions and 434 deletions

View File

@ -0,0 +1,7 @@
import {useAnimatedScrollHandler} from "react-native-reanimated";
export function useAnimatedScrollHandlerWorklet(scrollY) {
return useAnimatedScrollHandler((event) => {
scrollY.value = event.contentOffset.y;
})
}

View File

@ -355,11 +355,6 @@ globalThis.__STATUS_MOBILE_JS_IDENTITY_PROXY__ = new Proxy({}, {get() { return (
(def worklet-factory
#js {:applyAnimationsToStyle (fn [])})
(def shell-worklets #js {})
(def bottom-sheet #js {})
(def record-audio-worklets #js {})
;; Update i18n_resources.cljs
(defn mock
[module]
@ -407,10 +402,11 @@ 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
"../src/js/worklet_factory.js" worklet-factory
"../src/js/shell_worklets.js" shell-worklets
"../src/js/bottom_sheet.js" bottom-sheet
"../src/js/record_audio_worklets.js" record-audio-worklets
"../src/js/worklets/core.js" worklet-factory
"../src/js/worklets/shell.js" #js {}
"../src/js/worklets/bottom_sheet.js" #js {}
"../src/js/worklets/record_audio.js" #js {}
"../src/js/worklets/scroll_view.js" #js {}
"./fleets.js" default-fleets
"@walletconnect/client" wallet-connect-client
"../translations/ar.json" (js/JSON.parse (slurp "./translations/ar.json"))

View File

@ -78,42 +78,42 @@
[props
{:keys [name
muted?
unread-messages?
unread-mentions-count
unviewed-messages-count
unviewed-mentions-count
status
community-icon
images
tokens
locked?]}]
locked?
style]}]
[rn/touchable-highlight
(merge {:underlay-color (colors/theme-colors
colors/neutral-5
colors/neutral-95)
:style {:border-radius 12}}
props)
[rn/view {:flex 1}
[rn/view (style/membership-info-container)
[community-icon/community-icon
{:images community-icon} 32]
[rn/view
{:flex 1
:margin-left 12
:justify-content :center}
[text/text
{:accessibility-label :chat-name-text
:number-of-lines 1
:ellipsize-mode :tail
:weight :semi-bold
:size :paragraph-1}
name]]
[rn/view (merge (style/membership-info-container) style)
[community-icon/community-icon
{:images images} 32]
[rn/view
{:flex 1
:margin-left 12
:justify-content :center}
[text/text
{:accessibility-label :chat-name-text
:number-of-lines 1
:ellipsize-mode :tail
:weight :semi-bold
:size :paragraph-1}
name]]
[rn/view
{:justify-content :center
:margin-right 16}
(if (= status :gated)
[community-view/permission-tag-container
{:locked? locked?
:tokens tokens}]
[notification-view
{:muted? muted?
:unread-mentions-count unread-mentions-count
:unread-messages? unread-messages?}])]]]])
[rn/view
{:justify-content :center
:margin-right 16}
(if (= status :gated)
[community-view/permission-tag-container
{:locked? locked?
:tokens tokens}]
[notification-view
{:muted? muted?
:unread-mentions-count unviewed-mentions-count
:unread-messages? (pos? unviewed-messages-count)}])]]])

View File

@ -92,6 +92,7 @@
colors/neutral-90)}
{:flex-direction :row
:margin-horizontal 20
:margin-vertical 8
:height 56
:padding-right 12})
[card-title-and-description title description]

View File

@ -15,9 +15,9 @@
:shadow-radius radius
:shadow-opacity 1
:shadow-color colors/shadow
:elevation 1
:border-radius radius
:justify-content :space-between
:elevation 2
:background-color (colors/theme-colors
colors/white
colors/neutral-90)})

View File

@ -8,7 +8,8 @@
[taoensso.timbre :as log]
[cljs-bean.core :as bean]
[reagent.core :as reagent]
[quo2.components.record-audio.record-audio.helpers :as helpers]))
[quo2.components.record-audio.record-audio.helpers :as helpers]
[utils.worklets.record-audio :as worklets.record-audio]))
(def ^:private scale-to-each 1.8)
(def ^:private scale-to-total 2.6)
@ -18,14 +19,6 @@
(def ^:private signal-anim-duration 3900)
(def ^:private signal-anim-duration-2 1950)
(def ^:private record-audio-worklets (js/require "../src/js/record_audio_worklets.js"))
(defn- ring-scale
[scale substract]
(.ringScale ^js record-audio-worklets
scale
substract))
(def ^:private animated-ring
(reagent/adapt-react-class
(rn/memo
@ -45,7 +38,9 @@
opacity-from (if @ready-to-lock? opacity-from-lock opacity-from-default)
animations (map
(fn [index]
(let [ring-scale (ring-scale scale (* scale-padding index))]
(let [ring-scale (worklets.record-audio/ring-scale scale
(* scale-padding
index))]
{:scale ring-scale
:opacity (reanimated/interpolate ring-scale
[1 scale-to-each]

View File

@ -98,6 +98,10 @@
(def use-ref react/useRef)
(defn current-ref
[ref]
(oops/oget ref "current"))
(defn use-effect
([effect-fn]
(use-effect effect-fn []))

View File

@ -18,7 +18,8 @@
LinearTransition)]
[reagent.core :as reagent]
[react-native.flat-list :as rn-flat-list]
[utils.collection]))
[utils.collection]
[utils.worklets.core :as worklets.core]))
;; Animations
(def slide-in-up-animation SlideInUp)
@ -29,14 +30,14 @@
(def create-animated-component (comp reagent/adapt-react-class (.-createAnimatedComponent reanimated)))
(def view (reagent/adapt-react-class (.-View reanimated)))
(def scroll-view (reagent/adapt-react-class (.-ScrollView reanimated)))
(def image (reagent/adapt-react-class (.-Image reanimated)))
(def reanimated-flat-list (reagent/adapt-react-class (.-FlatList ^js rn)))
(def reanimated-flat-list (create-animated-component (.-FlatList ^js rn)))
(defn flat-list
[props]
[reanimated-flat-list (rn-flat-list/base-list-props props)])
(def touchable-opacity (create-animated-component (.-TouchableOpacity ^js rn)))
(def linear-gradient (create-animated-component LinearGradient))
(def fast-image (create-animated-component FastImage))
(def blur-view (create-animated-component (.-BlurView blur)))
@ -77,24 +78,20 @@
(when (and anim (some? val))
(set! (.-value anim) val)))
;; Worklets
(def worklet-factory (js/require "../src/js/worklet_factory.js"))
(defn interpolate
([shared-value input-range output-range]
(interpolate shared-value input-range output-range nil))
([shared-value input-range output-range extrapolation]
(.interpolateValue ^js worklet-factory
shared-value
(clj->js input-range)
(clj->js output-range)
(clj->js extrapolation))))
(worklets.core/interpolate-value
shared-value
(clj->js input-range)
(clj->js output-range)
(clj->js extrapolation))))
;;;; Component Animations
(defn apply-animations-to-style
[animations style]
(use-animated-style
(.applyAnimationsToStyle ^js worklet-factory (clj->js animations) (clj->js style))))
(worklets.core/apply-animations-to-style (clj->js animations) (clj->js style))))
;; Animators
(defn animate-shared-value-with-timing

View File

@ -10,9 +10,8 @@
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
[reagent.core :as reagent]))
(def bottom-sheet-js (js/require "../src/js/bottom_sheet.js"))
[reagent.core :as reagent]
[utils.worklets.bottom-sheet :as worklets.bottom-sheet]))
(def animation-delay 450)
@ -129,9 +128,9 @@
bg-height (max (min @content-height bg-height-expanded) 109)
bottom-sheet-dy (reanimated/use-shared-value 0)
pan-y (reanimated/use-shared-value 0)
translate-y (.useTranslateY ^js bottom-sheet-js window-height bottom-sheet-dy pan-y)
translate-y (worklets.bottom-sheet/use-translate-y window-height bottom-sheet-dy pan-y)
bg-opacity
(.useBackgroundOpacity ^js bottom-sheet-js translate-y bg-height window-height)
(worklets.bottom-sheet/use-background-opacity translate-y bg-height window-height)
on-content-layout (fn [evt]
(let [height (oget evt "nativeEvent" "layout" "height")]
(reset! content-height height)))

View File

@ -46,7 +46,7 @@
:style override-style
:avatar user-avatar}
"
[{:keys [type style avatar hide-search]}]
[{:keys [type style avatar search?] :or {type :default}}]
(let [button-common-props (get-button-common-props type)
notif-count (rf/sub [:activity-center/unread-count])
new-notifications? (pos? notif-count)
@ -71,7 +71,7 @@
:right 20
:top 12
:flex-direction :row}}
(when-not hide-search
(when search?
[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]

View File

@ -11,9 +11,7 @@
(defn icon-color
[]
(colors/theme-colors
colors/white-opa-40
colors/neutral-80-opa-40))
(colors/theme-colors colors/white-opa-40 colors/neutral-80-opa-40))
(def negative-scroll-position-0 (if platform/ios? -44 0))
(def scroll-position-0 (if platform/ios? 44 0))
@ -27,15 +25,7 @@
(min maximum)))
(defn scroll-page-header
[scroll-height
height
name
page-nav
logo
sticky-header
top-nav
title-colum
navigate-back?]
[scroll-height height name page-nav 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])
y (reanimated/use-shared-value scroll-height)
@ -120,19 +110,10 @@
(defn scroll-page
[_ _ _]
(let [scroll-height (reagent/atom negative-scroll-position-0)]
(fn
[{:keys [cover-image
logo
page-nav-right-section-buttons
name
on-scroll
height
top-nav
title-colum
background-color
navigate-back?]}
sticky-header
children]
(fn [{:keys [name cover-image logo page-nav-right-section-buttons on-scroll
height top-nav title-colum background-color navigate-back?]}
sticky-header
children]
[:<>
[:f> scroll-page-header @scroll-height height name page-nav-right-section-buttons
logo sticky-header top-nav title-colum navigate-back?]

View File

@ -0,0 +1,100 @@
(ns status-im2.common.sticky-scroll-view.view
(:require [react-native.reanimated :as reanimated]
[react-native.core :as rn]
[react-native.platform :as platform]
[utils.worklets.scroll-view :as worklets.scroll-view]
[quo2.foundations.colors :as colors]))
(defn sticky-item
[{:keys [height translation-y background-color]} content]
[:f>
(fn []
[rn/view (merge {:height height} (when platform/ios? {:z-index 1}))
[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY translation-y}]}
{:position :absolute
:z-index (when platform/android? 1)
:top 0
:left 0
:right 0
:height height
:background-color background-color})}
content]])])
(defn scroll-view
[{:keys [ref scroll-y blur]} & content]
[:f>
(fn []
(let [scroll-handler (worklets.scroll-view/use-animated-scroll-handler scroll-y)
opacity (when blur
(reanimated/interpolate scroll-y
[0 (:delta blur)]
[0 1]
{:extrapolateLeft "clamp"
:extrapolateRight "extend"}))]
(into [reanimated/scroll-view
{:ref ref
:scroll-event-throttle 1
:shows-vertical-scroll-indicator false
:contentInsetAdjustmentBehavior :never
:on-scroll scroll-handler}]
(concat
(when blur
;bug on Android
;https://github.com/Kureev/react-native-blur/issues/520}
[[reanimated/view
{:style (reanimated/apply-animations-to-style
{:transform [{:translateY scroll-y}]
:opacity opacity}
{:overflow (if platform/ios? :visible :hidden)
:position :absolute
:z-index 1
:top 0
:height (:height blur)
:right 0
:left 0})}
[reanimated/blur-view
{:blur-amount 10
:blur-type (if (colors/dark?) :dark :xlight)
:style {:position :absolute
:top 0
:height (:height blur)
:right 0
:left 0}}]]])
content))))])
(defn flat-list
[{:keys [scroll-y blur header render-fn data]}]
[:f>
(fn []
(let [scroll-handler (worklets.scroll-view/use-animated-scroll-handler scroll-y)
opacity (when blur
(reanimated/interpolate scroll-y
[0 (:delta blur)]
[0 1]
{:extrapolateLeft "clamp"
:extrapolateRight "extend"}))]
[reanimated/flat-list
{:scroll-event-throttle 1
:shows-vertical-scroll-indicator false
:contentInsetAdjustmentBehavior :never
:data data
:render-fn render-fn
:header (if blur
[:<>
[reanimated/blur-view
{:blur-amount 10
:blur-type :xlight
:style (reanimated/apply-animations-to-style
{:transform [{:translateY scroll-y}]
:opacity opacity}
{:z-index 1
:position :absolute
:top 0
:height (:height blur)
:right 0
:left 0})}]
header]
header)
:on-scroll scroll-handler}]))])

View File

@ -0,0 +1,24 @@
(ns status-im2.contexts.chat.home.style
(:require [react-native.platform :as platform]))
(def tabs
{:padding-horizontal 20
:padding-top 16
:padding-bottom 12})
(def blur
{:position :absolute
:top 0
:right 0
:left 0
:bottom 0})
(defn blur-container
[top]
{:overflow (if platform/ios? :visible :hidden)
:position :absolute
:z-index 1
:top 0
:right 0
:left 0
:padding-top top})

View File

@ -10,11 +10,16 @@
[status-im2.contexts.chat.home.contact-request.view :as contact-request]
[utils.re-frame :as rf]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im2.common.home.actions.view :as actions]))
[status-im2.common.home.actions.view :as actions]
[react-native.safe-area :as safe-area]
[quo2.foundations.colors :as colors]
[react-native.blur :as blur]
[status-im2.contexts.chat.home.style :as style]
[react-native.platform :as platform]))
(defn get-item-layout
[_ index]
#js {:length 64 :offset (* 64 index) :index index})
#js {:length 56 :offset (* 56 index) :index index})
(defn filter-items-by-tab
[tab items]
@ -30,20 +35,21 @@
[quo/text (i18n/label :t/blank-messages-text)]])
(defn chats
[selected-tab]
[selected-tab top]
(let [{:keys [items search-filter]} (rf/sub [:home-items])
items (filter-items-by-tab selected-tab items)]
(if (and (empty? items)
(empty? search-filter))
[welcome-blank-chats]
[rn/flat-list
{:key-fn #(or (:chat-id %) (:public-key %) (:id %))
:get-item-layout get-item-layout
:on-end-reached #(re-frame/dispatch [:chat/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn chat-list-item/chat-list-item
:content-container-style {:padding-bottom 30}}])))
{:key-fn #(or (:chat-id %) (:public-key %) (:id %))
:content-inset-adjustment-behavior :never
:header [rn/view {:height (+ 245 top)}]
:get-item-layout get-item-layout
:on-end-reached #(re-frame/dispatch [:chat/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn chat-list-item/chat-list-item}])))
(defn welcome-blank-contacts
[]
@ -65,63 +71,63 @@
:on-press show-profile-actions}})
item]))
(defn contacts-section-list
[sections]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections sections
:render-section-header-fn contact-list/contacts-section-header
:content-container-style {:padding-bottom 20}
:render-fn contact-item-render}])
(defn contacts
[pending-contact-requests]
[pending-contact-requests top]
(let [items (rf/sub [:contacts/active-sections])]
(if (and (empty? items) (empty? pending-contact-requests))
[welcome-blank-contacts]
[:<>
(when (seq pending-contact-requests)
[contact-request/contact-requests pending-contact-requests])
(when (seq items)
[contacts-section-list items])])))
[rn/section-list
{:key-fn :public-key
:get-item-layout get-item-layout
:content-inset-adjustment-behavior :never
:header [:<>
[rn/view {:height (+ 245 top)}]
(when (seq pending-contact-requests)
[contact-request/contact-requests
pending-contact-requests])]
:sections items
:sticky-section-headers-enabled false
:render-section-header-fn contact-list/contacts-section-header
:render-fn contact-item-render}])))
(defn tabs
(defn get-tabs-data
[dot?]
[{:id :recent :label (i18n/label :t/recent) :accessibility-label :tab-recent}
{:id :groups :label (i18n/label :t/groups) :accessibility-label :tab-groups}
{:id :contacts
:label (i18n/label :t/contacts)
:accessibility-label :tab-contacts
:notification-dot? dot?}])
(defn home
[]
(let [selected-tab (reagent/atom :recent)]
(fn []
(let [pending-contact-requests (rf/sub [:activity-center/pending-contact-requests])]
[:<>
[quo/discover-card
{:title (i18n/label :t/invite-friends-to-status)
:description (i18n/label :t/share-invite-link)}]
[quo/tabs
{:style {:margin-left 20
:margin-bottom 20
:margin-top 24}
:size 32
:on-change #(reset! selected-tab %)
:default-active @selected-tab
:data [{:id :recent
:label (i18n/label :t/recent)
:accessibility-label :tab-recent}
{:id :groups
:label (i18n/label :t/groups)
:accessibility-label :tab-groups}
{:id :contacts
:label (i18n/label :t/contacts)
:accessibility-label :tab-contacts
:notification-dot? (pos? (count pending-contact-requests))}]}]
(if (= @selected-tab :contacts)
[contacts pending-contact-requests]
[chats @selected-tab])]))))
(defn home
[]
[:<>
[common.home/top-nav {:type :default :hide-search true}]
[common.home/title-column
{:label (i18n/label :t/messages)
:handler #(rf/dispatch [:bottom-sheet/show-sheet :new-chat-bottom-sheet {}])
:accessibility-label :new-chat-button}]
[tabs]])
[safe-area/consumer
(fn [{:keys [top]}]
[:<>
(if (= @selected-tab :contacts)
[contacts pending-contact-requests top]
[chats @selected-tab top])
[rn/view
{:style (style/blur-container top)}
[blur/view
{:blur-amount (if platform/ios? 20 10)
:blur-type (if (colors/dark?) :dark (if platform/ios? :light :xlight))
:style style/blur}]
[common.home/top-nav]
[common.home/title-column
{:label (i18n/label :t/messages)
:handler #(rf/dispatch [:bottom-sheet/show-sheet :new-chat-bottom-sheet
{}])
:accessibility-label :new-chat-button}]
[quo/discover-card
{:title (i18n/label :t/invite-friends-to-status)
:description (i18n/label :t/share-invite-link)}]
[quo/tabs
{:style style/tabs
:size 32
:on-change #(reset! selected-tab %)
:default-active @selected-tab
:data (get-tabs-data (pos? (count pending-contact-requests)))}]]])]))))

View File

@ -153,31 +153,24 @@
(get mock-community-item-data :data))])]))
(if communities communities communities-ids))])
(defn communities-lists
[selected-tab view-type]
(let [ids-by-user-involvement (rf/sub [:communities/community-ids-by-user-involvement])
all-communities (rf/sub [:communities/sorted-communities])
tab @selected-tab]
[rn/view {:style {:flex 1}}
(case tab
:all
(other-communities-list {:communities all-communities
:view-type view-type})
[rn/view {:style {:flex 1}}
(case @selected-tab
:all
(other-communities-list {:communities (rf/sub [:communities/sorted-communities])
:view-type view-type})
:open
(other-communities-list {:communities-ids (:open ids-by-user-involvement)
:view-type view-type})
:open
[:<>]
:gated
(other-communities-list {:communities-ids (:gated ids-by-user-involvement)
:view-type view-type})
[quo/information-box
{:type :error
:icon :i/info}
(i18n/label :t/error)])]))
:gated
[:<>]
[quo/information-box
{:type :error
:icon :i/info}
(i18n/label :t/error)])])
(defn render-communities
[selected-tab

View File

@ -1,38 +1,25 @@
(ns status-im2.contexts.communities.home.style
(:require [react-native.platform :as platform]))
(defn community-segments
[padding-top]
{:padding-bottom 12
:padding-top padding-top
:padding-horizontal 20
:background-color :transparent})
(def tabs
{:padding-horizontal 20
:padding-top 16
:padding-bottom 12})
(def communities-header-style
{:padding-vertical 8
:margin-top (if platform/ios? 208 112)})
(def blur
{:position :absolute
:top 0
:right 0
:left 0
:bottom 0})
(def render-segments-container
{:flex 1
:padding-horizontal 20
:padding-vertical 12})
(defn blur-container
[top]
{:overflow (if platform/ios? :visible :hidden)
:position :absolute
:z-index 1
:top 0
:right 0
:left 0
:padding-top top})
(defn home-communities-container
[background-color]
{:flex 1
:background-color background-color
:position :absolute
:top (if platform/ios? -44 0)
:bottom 0
:left 0
:right 0})
(def blur-tabs-header
{:flex 1
:position :absolute
:top (if platform/ios? 156 112)
:height 52
:left 0
:right 0
:justify-content :center
:background-color :transparent})

View File

@ -1,136 +1,74 @@
(ns status-im2.contexts.communities.home.view
(:require [utils.i18n :as i18n]
[quo2.core :as quo]
[quo2.foundations.colors :as colors]
[reagent.core :as reagent]
[react-native.core :as rn]
[status-im2.common.home.view :as common.home]
[status-im2.common.scroll-page.view :as scroll-page]
[status-im2.contexts.communities.menus.community-options.view :as options]
[utils.re-frame :as rf]
[react-native.safe-area :as safe-area]
[react-native.blur :as blur]
[quo2.foundations.colors :as colors]
[status-im2.contexts.communities.home.style :as style]
[utils.re-frame :as rf]))
[react-native.platform :as platform]))
(defn community-segments
[selected-tab padding-top]
[rn/view
{:style (style/community-segments padding-top)}
[quo/tabs
{:size 32
:on-change #(reset! selected-tab %)
:default-active :joined
:data [{:id :joined :label (i18n/label :chats/joined) :accessibility-label :joined-tab}
{:id :pending :label (i18n/label :t/pending) :accessibility-label :pending-tab}
{:id :opened :label (i18n/label :t/opened) :accessibility-label :opened-tab}]}]])
(defn item-render
[{:keys [id] :as item}]
(let [unviewed-counts (rf/sub [:communities/unviewed-counts id])
item (merge item unviewed-counts)]
[quo/communities-membership-list-item
{:style {:padding-horizontal 18}
:on-press #(rf/dispatch [:navigate-to-nav2 :community-overview id])
:on-long-press #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
[options/community-options-bottom-sheet id])
:selected-item (fn []
[quo/communities-membership-list-item {} item])}])}
item]))
(defn communities-list
[communities-ids]
[rn/view
(map-indexed
(fn [index id]
(let [community (rf/sub [:communities/home-item id])]
^{:key index}
[quo/communities-membership-list-item
{:on-press #(rf/dispatch [:navigate-to-nav2 :community-overview id])
:on-long-press #(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn []
[options/community-options-bottom-sheet id])
:selected-item (fn []
[quo/communities-membership-list-item {} community])}])}
community]))
communities-ids)])
(defn render-communities-segments
[selected-tab]
(let [ids-by-user-involvement (rf/sub [:communities/community-ids-by-user-involvement])
tab @selected-tab]
[rn/view
{:style style/render-segments-container}
(case tab
:joined
[communities-list (:joined ids-by-user-involvement)]
:pending
[communities-list (:pending ids-by-user-involvement)]
:opened
[communities-list (:opened ids-by-user-involvement)]
[quo/information-box
{:type :error
:icon :i/info}
(i18n/label :t/error)])]))
(defn communities-header
[selected-tab padding-top]
[:<>
[rn/view
{:style style/communities-header-style}
[quo/discover-card
{:on-press #(rf/dispatch [:navigate-to :discover-communities])
:title (i18n/label :t/discover)
:description (i18n/label :t/whats-trending)
:accessibility-label :communities-home-discover-card}]]
[community-segments selected-tab padding-top]])
(defn home-page-comunity-lists
[{:keys [selected-tab padding-top]}]
[rn/view {:style {:flex 1}}
[communities-header selected-tab padding-top]
[render-communities-segments selected-tab]])
(defn home-sticky-header
[{:keys [selected-tab scroll-height padding-top]}]
(when (> @scroll-height 80)
[rn/view
{:style style/blur-tabs-header}
[community-segments selected-tab padding-top]]))
(defn home-nav
[]
[common.home/top-nav
{:type :default
:hide-search true
:style {:background-color :transparent}}])
(defn title-column
[]
[common.home/title-column
{:label (i18n/label :t/communities)
:handler #(rf/dispatch [:bottom-sheet/show-sheet :add-new {}])
:accessibility-label :new-chat-button}])
(defn communities-screen-content
[]
(let [scroll-height (reagent/atom 0)
selected-tab (reagent/atom :joined)]
(fn []
[scroll-page/scroll-page
{:name (i18n/label :t/communities)
:on-scroll #(reset! scroll-height %)
:top-nav [home-nav]
:title-colum [title-column]
:background-color (colors/theme-colors
colors/white
colors/neutral-95)
:navigate-back? :false
:height (if (> @scroll-height 80)
208
156)}
[home-sticky-header
{:selected-tab selected-tab
:scroll-height scroll-height
:padding-top 8}]
[home-page-comunity-lists
{:selected-tab selected-tab
:padding-top 16
:height 60}]])))
(def tabs-data
[{:id :joined :label (i18n/label :chats/joined) :accessibility-label :joined-tab}
{:id :pending :label (i18n/label :t/pending) :accessibility-label :pending-tab}
{:id :opened :label (i18n/label :t/opened) :accessibility-label :opened-tab}])
(defn home
[]
[rn/view
{:style (style/home-communities-container (colors/theme-colors
colors/white
colors/neutral-95))}
[communities-screen-content]])
(let [selected-tab (reagent/atom :joined)]
(fn []
(let [{:keys [joined pending opened]} (rf/sub [:communities/grouped-by-status])
selected-items (case @selected-tab
:joined joined
:pending pending
:opened opened)]
[safe-area/consumer
(fn [{:keys [top]}]
[:<>
[rn/flat-list
{:key-fn :id
:content-inset-adjustment-behavior :never
:header [rn/view {:height (+ 245 top)}]
:render-fn item-render
:data selected-items}]
[rn/view
{:style (style/blur-container top)}
[blur/view
{:blur-amount (if platform/ios? 20 10)
:blur-type (if (colors/dark?) :dark (if platform/ios? :light :xlight))
:style style/blur}]
[common.home/top-nav]
[common.home/title-column
{:label (i18n/label :t/communities)
:handler #(rf/dispatch [:bottom-sheet/show-sheet :add-new {}])
:accessibility-label :new-chat-button}]
[quo/discover-card
{:on-press #(rf/dispatch [:navigate-to :discover-communities])
:title (i18n/label :t/discover)
:description (i18n/label :t/whats-trending)
:accessibility-label :communities-home-discover-card}]
[quo/tabs
{:size 32
:style style/tabs
:on-change #(reset! selected-tab %)
:default-active @selected-tab
:data tabs-data}]]])]))))

View File

@ -4,7 +4,8 @@
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im.async-storage.core :as async-storage] ;;TODO remove when not used anymore
[status-im2.contexts.shell.constants :as shell.constants]))
[status-im2.contexts.shell.constants :as shell.constants]
[utils.worklets.shell :as worklets.shell]))
;; Atoms
(def selected-stack-id (atom nil))
@ -66,8 +67,6 @@
:top (+ top-empty-space (shell.constants/bottom-tabs-container-height))
:scale minimize-scale}))
(def shell-worklets (js/require "../src/js/shell_worklets.js"))
;; Shared Values
(defn calculate-shared-values
[]
@ -87,18 +86,11 @@
(assoc
acc
stack-opacity-keyword
(.stackOpacity
^js shell-worklets
(name id)
selected-stack-id-sv)
(worklets.shell/stack-opacity (name id) selected-stack-id-sv)
stack-pointer-keyword
(.stackPointer
^js shell-worklets
(name id)
selected-stack-id-sv)
(worklets.shell/stack-pointer (name id) selected-stack-id-sv)
tabs-icon-color-keyword
(.bottomTabIconColor
^js shell-worklets
(worklets.shell/bottom-tab-icon-color
(name id)
selected-stack-id-sv
home-stack-state-sv
@ -110,28 +102,19 @@
:pass-through? pass-through-sv
:home-stack-state home-stack-state-sv
:animate-home-stack-left animate-home-stack-left
:home-stack-left (.homeStackLeft
^js shell-worklets
:home-stack-left (worklets.shell/home-stack-left
selected-stack-id-sv
animate-home-stack-left
home-stack-state-sv
(clj->js (:left home-stack-position)))
:home-stack-top (.homeStackTop
^js shell-worklets
:home-stack-top (worklets.shell/home-stack-top
home-stack-state-sv
(:top home-stack-position))
:home-stack-opacity (.homeStackOpacity
^js shell-worklets
home-stack-state-sv)
:home-stack-pointer (.homeStackPointer
^js shell-worklets
home-stack-state-sv)
:home-stack-scale (.homeStackScale
^js shell-worklets
home-stack-state-sv
(:scale home-stack-position))
:bottom-tabs-height (.bottomTabsHeight
^js shell-worklets
:home-stack-opacity (worklets.shell/home-stack-opacity home-stack-state-sv)
:home-stack-pointer (worklets.shell/home-stack-pointer home-stack-state-sv)
:home-stack-scale (worklets.shell/home-stack-scale home-stack-state-sv
(:scale home-stack-position))
:bottom-tabs-height (worklets.shell/bottom-tabs-height
home-stack-state-sv
(shell.constants/bottom-tabs-container-height)
(shell.constants/bottom-tabs-extended-container-height))}

View File

@ -1,9 +1,7 @@
(ns status-im2.contexts.shell.home-stack
(:require [react-native.core :as rn]
[react-native.reanimated :as reanimated]
[react-native.safe-area :as safe-area]
(:require [react-native.reanimated :as reanimated]
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
[status-im2.contexts.chat.home.view :as chat] ;; TODO move to status-im2
[status-im2.contexts.chat.home.view :as chat]
[status-im2.contexts.communities.home.view :as communities]
[status-im2.contexts.shell.animation :as animation]
[status-im2.contexts.shell.constants :as shell.constants]
@ -43,22 +41,19 @@
(defn home-stack
[]
[safe-area/consumer
(fn [insets]
[:f>
(fn []
(let [shared-values @animation/shared-values-atom
home-stack-original-style (styles/home-stack @animation/screen-height)
home-stack-animated-style (reanimated/apply-animations-to-style
{:top (:home-stack-top shared-values)
:left (:home-stack-left shared-values)
:opacity (:home-stack-opacity shared-values)
:pointer-events (:home-stack-pointer shared-values)
:transform [{:scale (:home-stack-scale shared-values)}]}
home-stack-original-style)]
[reanimated/view {:style home-stack-animated-style}
[rn/view {:margin-top (:top insets) :flex 1}
[stack-view :communities-stack shared-values]
[stack-view :chats-stack shared-values]
[stack-view :browser-stack shared-values]
[stack-view :wallet-stack shared-values]]]))])])
[:f>
(fn []
(let [shared-values @animation/shared-values-atom
home-stack-original-style (styles/home-stack @animation/screen-height)
home-stack-animated-style (reanimated/apply-animations-to-style
{:top (:home-stack-top shared-values)
:left (:home-stack-left shared-values)
:opacity (:home-stack-opacity shared-values)
:pointer-events (:home-stack-pointer shared-values)
:transform [{:scale (:home-stack-scale shared-values)}]}
home-stack-original-style)]
[reanimated/view {:style home-stack-animated-style}
[stack-view :communities-stack shared-values]
[stack-view :chats-stack shared-values]
[stack-view :browser-stack shared-values]
[stack-view :wallet-stack shared-values]]))])

View File

@ -40,7 +40,7 @@
height (or screen-height height)]
{:border-bottom-left-radius 20
:border-bottom-right-radius 20
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)
:background-color (colors/theme-colors colors/white colors/neutral-95)
:overflow :hidden
:position :absolute
:width width

View File

@ -109,10 +109,9 @@
[jump-to-list switcher-cards shell-margin]
[top-nav-blur-overlay (:top insets)]
[common.home/top-nav
{:type :shell
:hide-search true
:style {:margin-top (:top insets)
:z-index 2}}]])]))
{:type :shell
:style {:margin-top (:top insets)
:z-index 2}}]])]))
(defn on-layout
[evt]

View File

@ -121,21 +121,16 @@
(map :id communities)))
(re-frame/reg-sub
:communities/community-ids-by-user-involvement
:communities/grouped-by-status
:<- [:communities/communities]
;; Return communities splitted by level of user participation. Some communities user
;; already joined, to some of them join request sent and others were opened one day
;; and their data remained in app-db.
;; Result map has form: {:joined [id1, id2] :pending [id3, id5] :opened [id4]}"
(fn [communities]
(reduce (fn [acc community]
(let [joined? (:joined community)
requested? (pos? (:requested-to-join-at community))
id (:id community)]
requested? (pos? (:requested-to-join-at community))] ;; this looks suspicious
(cond
joined? (update acc :joined conj id)
requested? (update acc :pending conj id)
:else (update acc :opened conj id))))
joined? (update acc :joined conj community)
requested? (update acc :pending conj community)
:else (update acc :opened conj community))))
{:joined [] :pending [] :opened []}
communities)))

View File

@ -81,42 +81,6 @@
:unviewed-mentions-count 0}
(rf/sub [sub-name community-id])))))
(h/deftest-sub :communities/community-ids-by-user-involvement
[sub-name]
(testing "Empty communities list"
(swap! rf-db/app-db assoc
:communities
{})
(is (= {:joined [] :pending [] :opened []}
(rf/sub [sub-name]))))
(testing "Only opened communities"
(swap! rf-db/app-db assoc
:communities/enabled? true
:communities
{"0x1" {:id "0x1" :name "civilized monkeys"}
"0x2" {:id "0x2" :name "Civilized rats"}
"0x3" {:id "0x3" :name "Civilized dolphins"}})
(is (= {:joined [] :pending [] :opened ["0x1" "0x2" "0x3"]}
(rf/sub [sub-name]))))
(testing "One joined community and two opened ones"
(swap! rf-db/app-db assoc
:communities/enabled? true
:communities
{"0x1" {:id "0x1" :name "civilized monkeys" :joined true}
"0x2" {:id "0x2" :name "Civilized rats"}
"0x3" {:id "0x3" :name "Civilized dolphins"}})
(is (= {:joined ["0x1"] :pending [] :opened ["0x2" "0x3"]}
(rf/sub [sub-name]))))
(testing "One joined community, one open and one pending"
(swap! rf-db/app-db assoc
:communities/enabled? true
:communities
{"0x1" {:id "0x1" :name "civilized monkeys" :joined true}
"0x2" {:id "0x2" :name "Civilized rats" :requested-to-join-at 1000}
"0x3" {:id "0x3" :name "Civilized dolphins"}})
(is (= {:joined ["0x1"] :pending ["0x2"] :opened ["0x3"]}
(rf/sub [sub-name])))))
(h/deftest-sub :communities/sorted-communities
[sub-name]
(testing "Empty communities list"

View File

@ -0,0 +1,11 @@
(ns utils.worklets.bottom-sheet)
(def bottom-sheet-js (js/require "../src/js/worklets/bottom_sheet.js"))
(defn use-translate-y
[window-height bottom-sheet-dy pan-y]
(.useTranslateY ^js bottom-sheet-js window-height bottom-sheet-dy pan-y))
(defn use-background-opacity
[translate-y bg-height window-height]
(.useBackgroundOpacity ^js bottom-sheet-js translate-y bg-height window-height))

View File

@ -0,0 +1,18 @@
(ns utils.worklets.core)
(def core-js (js/require "../src/js/worklets/core.js"))
(defn interpolate-value
[shared-value
input-range
output-range
extrapolation]
(.interpolateValue ^js core-js
shared-value
(clj->js input-range)
(clj->js output-range)
(clj->js extrapolation)))
(defn apply-animations-to-style
[animations style]
(.applyAnimationsToStyle ^js core-js (clj->js animations) (clj->js style)))

View File

@ -0,0 +1,7 @@
(ns utils.worklets.record-audio)
(def ^:private record-audio-worklets (js/require "../src/js/worklets/record_audio.js"))
(defn ring-scale
[scale substract]
(.ringScale ^js record-audio-worklets scale substract))

View File

@ -0,0 +1,7 @@
(ns utils.worklets.scroll-view)
(def scroll-worklet-js (js/require "../src/js/worklets/scroll_view.js"))
(defn use-animated-scroll-handler
[scroll-y]
(.useAnimatedScrollHandlerWorklet ^js scroll-worklet-js scroll-y))

View File

@ -0,0 +1,52 @@
(ns utils.worklets.shell)
(def shell-worklets (js/require "../src/js/worklets/shell.js"))
(defn stack-opacity
[id selected-stack-id]
(.stackOpacity ^js shell-worklets id selected-stack-id))
(defn stack-pointer
[id selected-stack-id]
(.stackPointer ^js shell-worklets id selected-stack-id))
(defn bottom-tabs-height
[home-stack-state-sv container-height extended-container-height]
(.bottomTabsHeight ^js shell-worklets home-stack-state-sv container-height extended-container-height))
(defn bottom-tab-icon-color
[id selected-stack-id-sv home-stack-state-sv pass-through-sv selected-tab-color default-color
pass-through-color]
(.bottomTabIconColor ^js shell-worklets
id
selected-stack-id-sv
home-stack-state-sv
pass-through-sv
selected-tab-color
default-color
pass-through-color))
(defn home-stack-opacity
[home-stack-state-sv]
(.homeStackOpacity ^js shell-worklets home-stack-state-sv))
(defn home-stack-pointer
[home-stack-state-sv]
(.homeStackPointer ^js shell-worklets home-stack-state-sv))
(defn home-stack-scale
[home-stack-state-sv scale]
(.homeStackScale ^js shell-worklets home-stack-state-sv scale))
(defn home-stack-left
[selected-stack-id-sv animate-home-stack-left home-stack-state-sv left-home-stack-position]
(.homeStackLeft
^js shell-worklets
selected-stack-id-sv
animate-home-stack-left
home-stack-state-sv
left-home-stack-position))
(defn home-stack-top
[home-stack-state-sv top-home-stack-position]
(.homeStackTop ^js shell-worklets home-stack-state-sv top-home-stack-position))