From 63d0aaca2a5c94bee71dcd7b6a84444bbc0af37d Mon Sep 17 00:00:00 2001 From: Ulises Manuel <90291778+ulisesmac@users.noreply.github.com> Date: Wed, 2 Oct 2024 14:35:23 -0600 Subject: [PATCH] feat(chats): Implement a simpler chat screen (#21313) * Change `defonce ^:const` -> `def ^:const` in `status-im.contexts.chat.messenger.messages.list.view` to be more REPL friendly * Remove animations from `status-im.contexts.chat.messenger.messages.pin.banner.style` * Simplify placeholder for messages * Replace shared-value with a ratom usage since no animations were performed. * Fix the style for the new designs and remove now unnecessary animations * Improve chat component implementation The previous implementation has two main problems: 1. It is creating atoms and ratoms in non-form-2-components. 2. Conditionally uses a hook: `rn/use-mount` in `lazy-chat-screen`. The new implementation fixes the previous problems, improves the readability and passes only the props needed to its children. * Remove action buttons from the chat screen * Remove now unused code * Replace reanimated/view -> rn/view where no animations are made --- src/js/worklets/chat/messenger/navigation.js | 47 --- src/js/worklets/chat/messenger/placeholder.js | 15 - .../messenger/composer/mentions/view.cljs | 2 +- .../chat/messenger/composer/view.cljs | 4 +- .../chat/messenger/messages/constants.cljs | 11 - .../chat/messenger/messages/list/view.cljs | 283 +++--------------- .../messenger/messages/navigation/style.cljs | 53 ++-- .../messenger/messages/navigation/view.cljs | 163 ++++------ .../messenger/messages/pin/banner/style.cljs | 9 +- .../messenger/messages/pin/banner/view.cljs | 36 +-- .../messages/scroll_to_bottom/view.cljs | 2 +- .../chat/messenger/messages/view.cljs | 77 +++-- .../chat/messenger/placeholder/style.cljs | 23 +- .../chat/messenger/placeholder/view.cljs | 14 +- .../worklets/chat/messenger/messages.cljs | 5 - .../worklets/chat/messenger/navigation.cljs | 27 -- .../worklets/chat/messenger/placeholder.cljs | 11 - 17 files changed, 183 insertions(+), 599 deletions(-) delete mode 100644 src/js/worklets/chat/messenger/navigation.js delete mode 100644 src/js/worklets/chat/messenger/placeholder.js delete mode 100644 src/utils/worklets/chat/messenger/navigation.cljs delete mode 100644 src/utils/worklets/chat/messenger/placeholder.cljs diff --git a/src/js/worklets/chat/messenger/navigation.js b/src/js/worklets/chat/messenger/navigation.js deleted file mode 100644 index 715213216c..0000000000 --- a/src/js/worklets/chat/messenger/navigation.js +++ /dev/null @@ -1,47 +0,0 @@ -import { useDerivedValue, withTiming, interpolate } from 'react-native-reanimated'; - -export function navigationHeaderOpacity(distanceFromListTop, isAllLoaded, isCalculationsComplete, startPosition) { - return useDerivedValue(function () { - 'worklet'; - const isCalculationsCompleteValue = isCalculationsComplete.value; - if (distanceFromListTop.value < startPosition && isAllLoaded.value) { - return isCalculationsCompleteValue ? withTiming(0) : 0; - } else { - return isCalculationsCompleteValue ? withTiming(1) : 1; - } - }); -} - -export function navigationHeaderPosition(distanceFromListTop, isAllLoaded, topBarHeight, startPosition) { - return useDerivedValue(function () { - 'worklet'; - return distanceFromListTop.value < startPosition && isAllLoaded.value ? withTiming(topBarHeight) : withTiming(0); - }); -} - -export function navigationButtonsCompleteOpacity(isCalculationComplete) { - return useDerivedValue(function () { - 'worklet'; - return isCalculationComplete.value ? withTiming(1) : 0; - }); -} - -export function interpolateNavigationViewOpacity(props) { - return useDerivedValue(function () { - 'worklet'; - const { - 'all-loaded?': isAllLoaded, - 'end-position': endPosition, - 'start-position': startPosition, - 'distance-from-list-top': distanceFromListTop, - } = props; - if (isAllLoaded.value) { - return interpolate(distanceFromListTop.value, [startPosition, endPosition], [0, 1], { - extrapolateLeft: 'clamp', - extrapolateRight: 'clamp', - }); - } else { - return 1; - } - }); -} diff --git a/src/js/worklets/chat/messenger/placeholder.js b/src/js/worklets/chat/messenger/placeholder.js deleted file mode 100644 index 281bddcc29..0000000000 --- a/src/js/worklets/chat/messenger/placeholder.js +++ /dev/null @@ -1,15 +0,0 @@ -import { useDerivedValue } from 'react-native-reanimated'; - -export function placeholderOpacity(isCalculationsComplete) { - return useDerivedValue(function () { - 'worklet'; - return isCalculationsComplete.value ? 0 : 1; - }); -} - -export function placeholderZIndex(isCalculationsComplete) { - return useDerivedValue(function () { - 'worklet'; - return isCalculationsComplete.value ? 0 : 2; - }); -} diff --git a/src/status_im/contexts/chat/messenger/composer/mentions/view.cljs b/src/status_im/contexts/chat/messenger/composer/mentions/view.cljs index 22c6e23ea6..1321209916 100644 --- a/src/status_im/contexts/chat/messenger/composer/mentions/view.cljs +++ b/src/status_im/contexts/chat/messenger/composer/mentions/view.cljs @@ -17,7 +17,7 @@ user]) (defn view - [{:keys [layout-height]}] + [layout-height] (let [suggestions (rf/sub [:chat/mention-suggestions]) suggestions? (seq suggestions) theme (quo.theme/use-theme) diff --git a/src/status_im/contexts/chat/messenger/composer/view.cljs b/src/status_im/contexts/chat/messenger/composer/view.cljs index bf5abc032f..3eb08a5995 100644 --- a/src/status_im/contexts/chat/messenger/composer/view.cljs +++ b/src/status_im/contexts/chat/messenger/composer/view.cljs @@ -35,7 +35,7 @@ :default-value default-value}]))) (defn view - [props] + [layout-height] (let [theme (quo.theme/use-theme) bottom (safe-area/get-bottom) input-ref (rn/use-ref-atom nil) @@ -43,7 +43,7 @@ (rf/dispatch [:chat/set-input-ref value]) (reset! input-ref value)))] [rn/view {:style {:margin-bottom bottom}} - [mentions/view props] + [mentions/view layout-height] [quo/separator] [rn/view {:style {:padding-horizontal 20 :padding-top 20}} [:<> diff --git a/src/status_im/contexts/chat/messenger/messages/constants.cljs b/src/status_im/contexts/chat/messenger/messages/constants.cljs index 9b8080292c..ffcc6d4604 100644 --- a/src/status_im/contexts/chat/messenger/messages/constants.cljs +++ b/src/status_im/contexts/chat/messenger/messages/constants.cljs @@ -3,15 +3,4 @@ ;;;; Navigation (def ^:const top-bar-height 56) (def ^:const pinned-banner-height 40) -(def ^:const header-container-top-margin 48) (def ^:const header-container-radius 20) -(def ^:const header-animation-distance 20) -(def ^:const content-animation-start-position-android 130) -(def ^:const content-animation-start-position-ios 124) -;; Note - We should also consider height of bio for banner animation starting position -;; Todo - Should be updated once New-profile implemation is complete -(def ^:const pinned-banner-animation-start-position 148) - -(def ^:const default-extrapolation-option - {:extrapolateLeft "clamp" - :extrapolateRight "clamp"}) diff --git a/src/status_im/contexts/chat/messenger/messages/list/view.cljs b/src/status_im/contexts/chat/messenger/messages/list/view.cljs index e26cdf467d..9923d959e4 100644 --- a/src/status_im/contexts/chat/messenger/messages/list/view.cljs +++ b/src/status_im/contexts/chat/messenger/messages/list/view.cljs @@ -1,6 +1,5 @@ (ns status-im.contexts.chat.messenger.messages.list.view (:require - [clojure.string :as string] [legacy.status-im.ui.screens.chat.group :as chat.group] [oops.core :as oops] [quo.core :as quo] @@ -25,8 +24,8 @@ [utils.re-frame :as rf] [utils.worklets.chat.messenger.messages :as worklets])) -(defonce ^:const distance-from-last-message 4) -(defonce ^:const loading-indicator-page-loading-height 100) +(def ^:const distance-from-last-message 4) +(def ^:const loading-indicator-page-loading-height 100) (defn list-key-fn [{:keys [message-id value]}] (or message-id value)) (defn list-ref [ref] (reset! state/messages-list-ref ref)) @@ -60,44 +59,17 @@ on-loaded]) (if platform/low-device? 700 100))))) -(defn- contact-icon - [{:keys [ens-verified added?]} theme] - (when (or ens-verified added?) - [rn/view - {:style {:margin-left 4}} - (if ens-verified - [quo/icon :i/verified - {:no-color true - :size 20 - :color (colors/theme-colors - (colors/custom-color :success 50) - (colors/custom-color :success 60) - theme)}] - (when added? - [quo/icon :i/contact - {:no-color true - :size 20 - :color (colors/theme-colors colors/primary-50 colors/primary-60 theme)}]))])) - -(defn- skeleton-list-props - [content parent-height animated?] - {:content content - :parent-height parent-height - :animated? animated?}) - (defn loading-view - [chat-id {:keys [window-height]}] + [{:keys [chat-id window-height]}] (let [messages (rf/sub [:chats/raw-chat-messages-stream chat-id]) loading-first-page? (= (count messages) 0) - top-spacing (if loading-first-page? - 0 - (+ messages.constants/top-bar-height (safe-area/get-top))) parent-height (if loading-first-page? window-height loading-indicator-page-loading-height)] - [rn/view {:padding-top top-spacing} - ;; Don't use animated loading skeleton https://github.com/status-im/status-mobile/issues/17426 - [quo/skeleton-list (skeleton-list-props :messages parent-height false)]])) + [quo/skeleton-list + {:content :messages + :parent-height parent-height + :animated? false}])) (defn header-height [{:keys [insets able-to-send-message? images reply edit link-previews? input-content-height]}] @@ -125,84 +97,6 @@ (+ (:bottom insets))) (- 70 (:bottom insets)))) -(defn list-header - [insets able-to-send-message?] - (let [header-data {:insets insets - :able-to-send-message? able-to-send-message? - :input-content-height (:input-content-height (rf/sub [:chats/current-chat-input])) - :images (rf/sub [:chats/sending-image]) - :reply (rf/sub [:chats/reply-message]) - :edit (rf/sub [:chats/edit-message]) - :link-previews? (or (rf/sub [:chats/link-previews?]) - (rf/sub [:chats/status-link-previews?]))}] - [rn/view {:style {:height (header-height header-data)}}])) - -(defn list-footer-avatar - [{:keys [distance-from-list-top display-name online? profile-picture theme group-chat color - emoji chat-type chat-name empty-chat?]}] - (let [scale (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [1 0.4] - messages.constants/default-extrapolation-option) - top (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [-44 -12] - messages.constants/default-extrapolation-option) - left (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [16 -8] - messages.constants/default-extrapolation-option) - community-channel? (= chat-type constants/community-chat-type)] - [reanimated/view - {:style (style/header-image scale top left theme)} - (cond - community-channel? - [quo/channel-avatar - {:size :size-80 - :full-name chat-name - :customization-color color - :emoji (when-not (string/blank? emoji) - (string/trim emoji))}] - group-chat - [quo/group-avatar - {:customization-color color - :size :size-80 - :picture profile-picture - :chat-name chat-name}] - :else - [quo/user-avatar - {:full-name display-name - :online? online? - :profile-picture profile-picture - :size :big}])])) - -(defn chat-display-name - [{:keys [distance-from-list-top display-name contact theme empty-chat?]}] - (let [top (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [0 -35] - messages.constants/default-extrapolation-option) - left (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [0 40] - messages.constants/default-extrapolation-option)] - [reanimated/view - {:style (style/user-name-container top left)} - [rn/view - {:style style/user-name} - [quo/text - {:weight :semi-bold - :size :heading-1 - :style {:flex-shrink 1} - :number-of-lines 1} - display-name] - [contact-icon contact theme]]])) - (defn actions [chat-id cover-bg-color] (let [latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id]) @@ -236,101 +130,12 @@ chat-type muted?)))}]}])) -(defn bio-and-actions - [{:keys [distance-from-list-top bio chat-id customization-color empty-chat? description]}] - (let [has-bio (seq (or bio description)) - top (reanimated/interpolate - distance-from-list-top - [0 (if empty-chat? 0 messages.constants/header-container-top-margin)] - [(if has-bio 8 16) (if has-bio -28 -20)] - messages.constants/default-extrapolation-option)] - [reanimated/view - {:style (style/bio-and-actions top)} - (when has-bio - [quo/text (or bio description)]) - [actions chat-id customization-color]])) - -(defn footer-component - [{:keys [chat distance-from-list-top customization-color]}] - (let [theme (quo.theme/use-theme) - {:keys [chat-id chat-name emoji chat-type - group-chat color description - empty-chat?]} chat - display-name (cond - (= chat-type constants/one-to-one-chat-type) - (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) - (= chat-type constants/community-chat-type) - (str "# " chat-name) - :else (str emoji chat-name)) - {:keys [bio]} (rf/sub [:contacts/contact-by-identity chat-id]) - online? (rf/sub [:visibility-status-updates/online? chat-id]) - contact (when-not group-chat - (rf/sub [:contacts/contact-by-address chat-id])) - photo-path (if group-chat - (rf/sub [:chats/group-chat-image chat-id]) - (rf/sub [:chats/photo-path chat-id])) - top-margin (+ (safe-area/get-top) - messages.constants/top-bar-height - messages.constants/header-container-top-margin - 32) - background-color (colors/theme-colors - (colors/resolve-color customization-color theme 20) - (colors/resolve-color customization-color theme 40) - theme) - bottom (reanimated/interpolate - distance-from-list-top - [0 messages.constants/header-container-top-margin] - [32 -4] - messages.constants/default-extrapolation-option) - background-opacity (reanimated/interpolate - distance-from-list-top - [messages.constants/header-container-top-margin - (+ messages.constants/header-animation-distance - messages.constants/header-container-top-margin)] - [1 0] - messages.constants/default-extrapolation-option)] - [:<> - [reanimated/view - {:style (style/background-container background-color background-opacity top-margin)}] - [reanimated/view {:style (style/header-bottom-container bottom top-margin)} - [rn/view {:style (style/header-bottom-shadow theme)}] - [rn/view {:style (style/header-bottom-part theme)} - [list-footer-avatar - {:distance-from-list-top distance-from-list-top - :display-name display-name - :online? online? - :theme theme - :profile-picture photo-path - :group-chat group-chat - :color color - :emoji emoji - :chat-type chat-type - :chat-name chat-name - :empty-chat? empty-chat?}] - [chat-display-name - {:distance-from-list-top distance-from-list-top - :display-name display-name - :theme theme - :contact contact - :group-chat group-chat - :empty-chat? empty-chat?}] - [bio-and-actions - {:distance-from-list-top distance-from-list-top - :bio bio - :chat-id chat-id - :customization-color customization-color - :description description - :empty-chat? empty-chat?}]]]])) - -(defn list-footer - [props] - (let [chat-id (get-in props [:chat :chat-id]) - loading-messages? (rf/sub [:chats/loading-messages? chat-id]) +(defn more-messages-loader + [{:keys [chat-id] :as props}] + (let [loading-messages? (rf/sub [:chats/loading-messages? chat-id]) all-loaded? (rf/sub [:chats/all-loaded? chat-id])] - [:<> - (if (or loading-messages? (not all-loaded?)) - [loading-view chat-id props] - [footer-component props])])) + (when (or loading-messages? (not all-loaded?)) + [loading-view props]))) (defn list-group-chat-header [{:keys [chat-id invitation-admin]}] @@ -359,8 +164,7 @@ (reset! content-height content-height-new))))) (defn on-layout - [{:keys [event layout-height distance-atom distance-from-list-top - chat-screen-layout-calculations-complete?]}] + [{:keys [event layout-height distance-atom distance-from-list-top on-layout-done?]}] (let [layout-height-new (oops/oget event "nativeEvent.layout.height") change (- layout-height-new @layout-height) new-distance (- @distance-atom change)] @@ -368,8 +172,7 @@ (reanimated/set-shared-value distance-from-list-top new-distance) (reset! distance-atom new-distance) (reset! layout-height layout-height-new)) - (when-not (reanimated/get-shared-value chat-screen-layout-calculations-complete?) - (reanimated/set-shared-value chat-screen-layout-calculations-complete? true)))) + (reset! on-layout-done? true))) (defn on-scroll-fn [distance-atom layout-height-atom] @@ -379,28 +182,21 @@ (reset! distance-atom new-distance))) (defn messages-list-content - [{:keys [insets distance-from-list-top content-height layout-height distance-atom - chat-screen-layout-calculations-complete? chat-list-scroll-y]}] - (let [theme (quo.theme/use-theme) - {:keys [chat-type chat-id] :as chat} (rf/sub [:chats/current-chat-chat-view]) - one-to-one-chat? (= chat-type constants/one-to-one-chat-type) - community-channel? (= constants/community-chat-type chat-type) - {contact-customization-color - :customization-color} (when one-to-one-chat? - (rf/sub [:contacts/contact-by-identity chat-id])) - customization-color (cond community-channel? - (or (:color chat) - (rf/sub [:communities/community-color - (:community-id chat)])) - one-to-one-chat? contact-customization-color - :else (or (:color chat) :turquoise)) - {:keys [keyboard-shown]} (hooks/use-keyboard) - {window-height :height} (rn/get-window) - context (rf/sub [:chats/current-chat-message-list-view-context]) - able-to-send-message? (:able-to-send-message? context) - messages (rf/sub [:chats/raw-chat-messages-stream chat-id]) - margin-bottom? (and community-channel? (not able-to-send-message?)) - recording? (rf/sub [:chats/recording?])] + [{:keys [insets distance-from-list-top layout-height chat-list-scroll-y on-layout-done?]}] + (let [content-height (rn/use-ref-atom 0) + distance-atom (rn/use-ref-atom 0) + theme (quo.theme/use-theme) + {:keys [keyboard-shown]} (hooks/use-keyboard) + {:keys [chat-type chat-id] + :as chat} (rf/sub [:chats/current-chat-chat-view]) + community-channel? (= constants/community-chat-type chat-type) + {window-height :height} (rn/get-window) + context (rf/sub [:chats/current-chat-message-list-view-context]) + able-to-send-message? (:able-to-send-message? context) + messages (rf/sub [:chats/raw-chat-messages-stream chat-id]) + margin-bottom? (and community-channel? (not able-to-send-message?)) + recording? (rf/sub [:chats/recording?]) + top-margin (+ (safe-area/get-top) messages.constants/top-bar-height)] [rn/view {:style (style/permission-context-sheet margin-bottom?)} [rn/view {:style {:flex-shrink 1}} ;; Keeps flat list on top [reanimated/flat-list @@ -409,12 +205,9 @@ :bounces false :header (when (= (:chat-type chat) constants/private-group-chat-type) [list-group-chat-header chat]) - :footer [list-footer - {:theme theme - :chat chat - :window-height window-height - :distance-from-list-top distance-from-list-top - :customization-color customization-color}] + :footer [more-messages-loader + {:chat-id chat-id + :window-height window-height}] :data messages :render-data {:theme theme :context context @@ -444,15 +237,15 @@ :style {:background-color (colors/theme-colors colors/white colors/neutral-95 theme)} - :content-container-style {:padding-top distance-from-last-message} + :content-container-style {:padding-top distance-from-last-message + :padding-bottom top-margin} :inverted true :on-layout #(on-layout - {:event % - :layout-height layout-height - :distance-atom distance-atom + {:event % + :layout-height layout-height + :distance-atom distance-atom :distance-from-list-top distance-from-list-top - :chat-screen-layout-calculations-complete? - chat-screen-layout-calculations-complete?}) + :on-layout-done? on-layout-done?}) :scroll-enabled (not recording?) :content-inset-adjustment-behavior :never :scroll-indicator-insets {:right 1}}]]])) diff --git a/src/status_im/contexts/chat/messenger/messages/navigation/style.cljs b/src/status_im/contexts/chat/messenger/messages/navigation/style.cljs index 71e2a26f77..359e65e01e 100644 --- a/src/status_im/contexts/chat/messenger/messages/navigation/style.cljs +++ b/src/status_im/contexts/chat/messenger/messages/navigation/style.cljs @@ -1,56 +1,43 @@ (ns status-im.contexts.chat.messenger.messages.navigation.style - (:require - [quo.foundations.colors :as colors] - [react-native.reanimated :as reanimated])) + (:require [quo.foundations.colors :as colors] + [status-im.contexts.chat.messenger.messages.constants :as messages.constants])) (defn navigation-view - [navigation-view-height pinned-banner-height] + [navigation-view-height] {:top 0 :left 0 :right 0 :position :absolute :pointer-events :box-none - :height (+ navigation-view-height pinned-banner-height) + :height (+ navigation-view-height messages.constants/pinned-banner-height) :z-index 1}) -(defn animated-background-view - [background-opacity navigation-view-height] - (reanimated/apply-animations-to-style - {:opacity background-opacity} - {:height navigation-view-height - :top 0 - :left 0 - :right 0 - :overflow :hidden - :position :absolute})) +(defn background + [navigation-view-height] + {:height navigation-view-height + :top 0 + :left 0 + :right 0 + :overflow :hidden + :position :absolute}) (defn header-container - [top-insets top-bar-height] + [top-insets] {:margin-top top-insets :flex-direction :row :padding-horizontal 20 :overflow :hidden - :height top-bar-height + :height messages.constants/top-bar-height :align-items :center}) -(defn button-animation-container - [opacity-value] - (reanimated/apply-animations-to-style - {:opacity opacity-value} - {})) - ;;;; Content -(defn header-content-container - [header-opacity header-position] - (reanimated/apply-animations-to-style - {:transform [{:translate-y header-position}] - :opacity header-opacity} - {:flex-direction :row - :align-items :center - :flex 1 - :margin-horizontal 12 - :height 40})) +(def header-content-container + {:flex-direction :row + :align-items :center + :flex 1 + :margin-horizontal 12 + :height 40}) (def header-text-container {:margin-left 8}) diff --git a/src/status_im/contexts/chat/messenger/messages/navigation/view.cljs b/src/status_im/contexts/chat/messenger/messages/navigation/view.cljs index b63d547b4f..29c35775dc 100644 --- a/src/status_im/contexts/chat/messenger/messages/navigation/view.cljs +++ b/src/status_im/contexts/chat/messenger/messages/navigation/view.cljs @@ -7,7 +7,6 @@ [re-frame.db] [react-native.core :as rn] [react-native.platform :as platform] - [react-native.reanimated :as reanimated] [react-native.safe-area :as safe-area] [status-im.common.home.actions.view :as actions] [status-im.constants :as constants] @@ -15,44 +14,26 @@ [status-im.contexts.chat.messenger.messages.navigation.style :as style] [status-im.contexts.chat.messenger.messages.pin.banner.view :as pin.banner] [utils.i18n :as i18n] - [utils.re-frame :as rf] - [utils.worklets.chat.messenger.messages :as messages.worklets] - [utils.worklets.chat.messenger.navigation :as worklets])) + [utils.re-frame :as rf])) (defn header-content-container - [{:keys [chat distance-from-list-top all-loaded? chat-screen-layout-calculations-complete?]}] - (let [theme (quo.theme/use-theme) - {:keys [chat-id group-chat chat-type chat-name - emoji color]} chat - display-name (cond - (= chat-type constants/one-to-one-chat-type) - (first (rf/sub - [:contacts/contact-two-names-by-identity - chat-id])) - (= chat-type constants/community-chat-type) - (str "# " chat-name) - :else (str emoji chat-name)) - online? (when-not group-chat (rf/sub [:visibility-status-updates/online? chat-id])) - photo-path (if group-chat - (rf/sub [:chats/group-chat-image chat-id]) - (rf/sub [:chats/photo-path chat-id])) - header-opacity (worklets/navigation-header-opacity - distance-from-list-top - all-loaded? - chat-screen-layout-calculations-complete? - (if platform/ios? - messages.constants/content-animation-start-position-ios - messages.constants/content-animation-start-position-android)) - header-position (worklets/navigation-header-position - distance-from-list-top - all-loaded? - messages.constants/top-bar-height - (if platform/ios? - messages.constants/content-animation-start-position-ios - messages.constants/content-animation-start-position-android)) - community-channel? (= chat-type constants/community-chat-type)] - [reanimated/view - {:style (style/header-content-container header-opacity header-position)} + [{:keys [chat-id group-chat chat-type chat-name emoji color] :as _chat}] + (let [theme (quo.theme/use-theme) + display-name (cond + (= chat-type constants/one-to-one-chat-type) + (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) + + (= chat-type constants/community-chat-type) + (str "# " chat-name) + + :else + (str emoji chat-name)) + online? (when-not group-chat (rf/sub [:visibility-status-updates/online? chat-id])) + photo-path (if group-chat + (rf/sub [:chats/group-chat-image chat-id]) + (rf/sub [:chats/photo-path chat-id])) + community-channel? (= chat-type constants/community-chat-type)] + [rn/view {:style style/header-content-container} (cond community-channel? [quo/channel-avatar @@ -90,30 +71,11 @@ (i18n/label (if online? :t/online :t/offline))])]])) -(defn animated-background-and-pinned-banner - [{:keys [chat-id navigation-view-height distance-from-list-top all-loaded?]}] - (let [theme (quo.theme/use-theme) - animation-distance messages.constants/header-animation-distance - props {:distance-from-list-top distance-from-list-top - :all-loaded? all-loaded?} - background-opacity (worklets/interpolate-navigation-view-opacity - (assoc props - :start-position - messages.constants/header-container-top-margin - :end-position - (+ animation-distance - messages.constants/header-container-top-margin))) - banner-opacity (worklets/interpolate-navigation-view-opacity - (assoc props - :start-position - (+ navigation-view-height - messages.constants/pinned-banner-animation-start-position) - :end-position - (+ animation-distance - navigation-view-height - messages.constants/pinned-banner-animation-start-position)))] +(defn header-background + [{:keys [chat-id navigation-view-height]}] + (let [theme (quo.theme/use-theme)] [:<> - [reanimated/view {:style (style/animated-background-view background-opacity navigation-view-height)} + [rn/view {:style (style/background navigation-view-height)} [quo/blur {:style {:flex 1} :blur-amount 20 @@ -121,58 +83,37 @@ :overlay-color (colors/theme-colors colors/white-70-blur colors/neutral-95-opa-70-blur theme) :blur-radius (if platform/ios? 20 10)}]] [pin.banner/banner - {:chat-id chat-id - :banner-opacity banner-opacity - :top-offset navigation-view-height}]])) + {:chat-id chat-id + :top-offset navigation-view-height}]])) (defn view - [{:keys [distance-from-list-top chat-screen-layout-calculations-complete?]}] + [] (let [{:keys [chat-id chat-type] - :as chat} (rf/sub [:chats/current-chat-chat-view]) - all-loaded? (reanimated/use-shared-value false) - all-loaded-sub (rf/sub [:chats/all-loaded? chat-id]) - top-insets (safe-area/get-top) - top-bar-height messages.constants/top-bar-height - navigation-view-height (+ top-bar-height top-insets) - navigation-buttons-opacity (worklets/navigation-buttons-complete-opacity - chat-screen-layout-calculations-complete?) - reached-threshold? (messages.worklets/use-messages-scrolled-to-threshold - distance-from-list-top - top-bar-height) - button-background (if reached-threshold? :photo :blur)] - (rn/use-effect (fn [] (reanimated/set-shared-value all-loaded? all-loaded-sub)) - [all-loaded-sub]) - [rn/view - {:style (style/navigation-view navigation-view-height messages.constants/pinned-banner-height)} - [animated-background-and-pinned-banner + :as chat} (rf/sub [:chats/current-chat-chat-view]) + top-insets (safe-area/get-top) + navigation-view-height (+ top-insets messages.constants/top-bar-height)] + [rn/view {:style (style/navigation-view navigation-view-height)} + [header-background {:chat-id chat-id - :navigation-view-height navigation-view-height - :distance-from-list-top distance-from-list-top - :all-loaded? all-loaded?}] - [rn/view {:style (style/header-container top-insets top-bar-height)} - [reanimated/view {:style (style/button-animation-container navigation-buttons-opacity)} - [quo/button - {:icon-only? true - :type :grey - :background button-background - :size 32 - :accessibility-label :back-button - :on-press #(rf/dispatch [:navigate-back])} - (if (= chat-type constants/community-chat-type) :i/arrow-left :i/close)]] - [header-content-container - {:chat chat - :distance-from-list-top distance-from-list-top - :all-loaded? all-loaded? - :chat-screen-layout-calculations-complete? chat-screen-layout-calculations-complete?}] - [reanimated/view {:style (style/button-animation-container navigation-buttons-opacity)} - [quo/button - {:icon-only? true - :type :grey - :background button-background - :size 32 - :accessibility-label :options-button - :on-press (fn [] - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:show-bottom-sheet - {:content (fn [] [actions/chat-actions chat true])}]))} - :i/options]]]])) + :navigation-view-height navigation-view-height}] + [rn/view {:style (style/header-container top-insets)} + [quo/button + {:icon-only? true + :type :grey + :background :blur + :size 32 + :accessibility-label :back-button + :on-press #(rf/dispatch [:navigate-back])} + (if (= chat-type constants/community-chat-type) :i/arrow-left :i/close)] + [header-content-container chat] + [quo/button + {:icon-only? true + :type :grey + :background :blur + :size 32 + :accessibility-label :options-button + :on-press (fn [] + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch [:show-bottom-sheet + {:content (fn [] [actions/chat-actions chat true])}]))} + :i/options]]])) diff --git a/src/status_im/contexts/chat/messenger/messages/pin/banner/style.cljs b/src/status_im/contexts/chat/messenger/messages/pin/banner/style.cljs index 259d89851e..9c561c74f5 100644 --- a/src/status_im/contexts/chat/messenger/messages/pin/banner/style.cljs +++ b/src/status_im/contexts/chat/messenger/messages/pin/banner/style.cljs @@ -1,6 +1,5 @@ (ns status-im.contexts.chat.messenger.messages.pin.banner.style (:require - [react-native.reanimated :as reanimated] [status-im.contexts.chat.messenger.messages.constants :as messages.constants])) (def container @@ -10,8 +9,6 @@ :right 0 :height messages.constants/pinned-banner-height}) -(defn container-animated-style - [top-offset banner-opacity] - (reanimated/apply-animations-to-style - {:opacity banner-opacity} - (assoc container :top top-offset))) +(defn container-with-top-offset + [top-offset] + (assoc container :top top-offset)) diff --git a/src/status_im/contexts/chat/messenger/messages/pin/banner/view.cljs b/src/status_im/contexts/chat/messenger/messages/pin/banner/view.cljs index 5d19fefc80..6649008821 100644 --- a/src/status_im/contexts/chat/messenger/messages/pin/banner/view.cljs +++ b/src/status_im/contexts/chat/messenger/messages/pin/banner/view.cljs @@ -2,30 +2,26 @@ (:require [quo.core :as quo] [quo.theme] + [react-native.core :as rn] [react-native.platform :as platform] - [react-native.reanimated :as reanimated] [status-im.contexts.chat.messenger.messages.pin.banner.style :as style] [utils.re-frame :as rf])) -(defn f-banner - [{:keys [chat-id banner-opacity top-offset]} latest-pin-text pins-count] - (let [theme (quo.theme/use-theme)] - [reanimated/view {:style (style/container-animated-style top-offset banner-opacity)} - [quo/blur - {:style style/container - :blur-radius (if platform/ios? 20 10) - :blur-type theme - :blur-amount 20}] - [quo/banner - {:latest-pin-text latest-pin-text - :pins-count pins-count - :on-press (fn [] - (rf/dispatch [:dismiss-keyboard]) - (rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}]])) - (defn banner - [{:keys [chat-id] :as props}] - (let [latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id]) + [{:keys [chat-id top-offset]}] + (let [theme (quo.theme/use-theme) + latest-pin-text (rf/sub [:chats/last-pinned-message-text chat-id]) pins-count (rf/sub [:chats/pin-messages-count chat-id])] (when (> pins-count 0) - [:f> f-banner props latest-pin-text pins-count]))) + [rn/view {:style (style/container-with-top-offset top-offset)} + [quo/blur + {:style style/container + :blur-radius (if platform/ios? 20 10) + :blur-type theme + :blur-amount 20}] + [quo/banner + {:latest-pin-text latest-pin-text + :pins-count pins-count + :on-press (fn [] + (rf/dispatch [:dismiss-keyboard]) + (rf/dispatch [:pin-message/show-pins-bottom-sheet chat-id]))}]]))) diff --git a/src/status_im/contexts/chat/messenger/messages/scroll_to_bottom/view.cljs b/src/status_im/contexts/chat/messenger/messages/scroll_to_bottom/view.cljs index 9117322765..5fbaab1e21 100644 --- a/src/status_im/contexts/chat/messenger/messages/scroll_to_bottom/view.cljs +++ b/src/status_im/contexts/chat/messenger/messages/scroll_to_bottom/view.cljs @@ -7,7 +7,7 @@ [utils.worklets.chat.messenger.composer :as worklets])) (defn button - [{:keys [chat-list-scroll-y]}] + [chat-list-scroll-y] (let [{window-height :height} (rn/get-window) scroll-down-button-opacity (worklets/scroll-down-button-opacity chat-list-scroll-y diff --git a/src/status_im/contexts/chat/messenger/messages/view.cljs b/src/status_im/contexts/chat/messenger/messages/view.cljs index f28d9dabeb..c3ff279b4c 100644 --- a/src/status_im/contexts/chat/messenger/messages/view.cljs +++ b/src/status_im/contexts/chat/messenger/messages/view.cljs @@ -19,57 +19,50 @@ [utils.re-frame :as rf])) (defn- footer - [props] + [layout-height] (let [current-chat-id (rf/sub [:chats/current-chat-id]) able-to-send-message? (rf/sub [:chats/able-to-send-message?])] (when-not (string/blank? current-chat-id) (if able-to-send-message? - [composer/view props] + [composer/view layout-height] [contact-requests.bottom-drawer/view {:contact-id current-chat-id}])))) (defn- chat-screen - [{:keys [insets] :as props}] + [on-layout-done?] (let [theme (quo.theme/use-theme) + layout-height (rn/use-ref-atom 0) + distance-from-list-top (reanimated/use-shared-value 0) + chat-list-scroll-y (reanimated/use-shared-value 0) alert-banners-top-margin (rf/sub [:alert-banners/top-margin]) - chat-exist? (rf/sub [:chats/current-chat-exist?])] - (when chat-exist? - [rn/keyboard-avoiding-view - {:style (style/keyboard-avoiding-container theme) - :keyboard-vertical-offset (- (if platform/ios? alert-banners-top-margin 0) (:bottom insets))} - [:<> - [list.view/messages-list-content props] - [scroll-to-bottom/button props]] - [messages.navigation/view props] - [footer props]]))) - -(defn lazy-chat-screen - [chat-screen-layout-calculations-complete? *screen-loaded?*] - (let [screen-loaded? (rf/sub [:shell/chat-screen-loaded?]) - distance-from-list-top (reanimated/use-shared-value 0) - chat-list-scroll-y (reanimated/use-shared-value 0) - props {:insets (safe-area/get-insets) - :content-height (atom 0) - :layout-height (atom 0) - :distance-atom (atom 0) - :distance-from-list-top distance-from-list-top - :chat-list-scroll-y chat-list-scroll-y - :chat-screen-layout-calculations-complete? - chat-screen-layout-calculations-complete?}] - (when *screen-loaded?* - (rn/use-mount #(reset! *screen-loaded?* true))) - (when-not (if *screen-loaded?* @*screen-loaded?* screen-loaded?) - (reanimated/set-shared-value chat-screen-layout-calculations-complete? false) - (reanimated/set-shared-value distance-from-list-top 0) - (reanimated/set-shared-value chat-list-scroll-y 0)) - (when (if *screen-loaded?* @*screen-loaded?* screen-loaded?) - [chat-screen props]))) + insets (safe-area/get-insets)] + [rn/keyboard-avoiding-view + {:style (style/keyboard-avoiding-container theme) + :keyboard-vertical-offset (- (if platform/ios? alert-banners-top-margin 0) + (:bottom insets))} + [:<> + [list.view/messages-list-content + {:insets insets + :distance-from-list-top distance-from-list-top + :chat-list-scroll-y chat-list-scroll-y + :layout-height layout-height + :on-layout-done? on-layout-done?}] + [scroll-to-bottom/button chat-list-scroll-y]] + [messages.navigation/view] + [footer layout-height]])) (defn chat [] - (let [chat-screen-layout-calculations-complete? (reanimated/use-shared-value false) - jump-to-enabled? (ff/enabled? ::ff/shell.jump-to) - *screen-loaded?* (when-not jump-to-enabled? - (reagent/atom false))] - [:<> - [lazy-chat-screen chat-screen-layout-calculations-complete? *screen-loaded?*] - [placeholder.view/view chat-screen-layout-calculations-complete?]])) + (let [on-layout-done? (reagent/atom false) + first-render-done? (reagent/atom false)] + (fn [] + (let [chat-exists? (rf/sub [:chats/current-chat-exist?]) + jump-to-enabled? (ff/enabled? ::ff/shell.jump-to) + screen-loaded-for-jump-to? (rf/sub [:shell/chat-screen-loaded?]) + screen-loaded? (if jump-to-enabled? + screen-loaded-for-jump-to? + @first-render-done?)] + (rn/use-mount #(reset! first-render-done? true)) + [:<> + (when (and chat-exists? screen-loaded?) + [chat-screen on-layout-done?]) + [placeholder.view/view on-layout-done?]])))) diff --git a/src/status_im/contexts/chat/messenger/placeholder/style.cljs b/src/status_im/contexts/chat/messenger/placeholder/style.cljs index b58677d420..c9a5006791 100644 --- a/src/status_im/contexts/chat/messenger/placeholder/style.cljs +++ b/src/status_im/contexts/chat/messenger/placeholder/style.cljs @@ -1,16 +1,15 @@ (ns status-im.contexts.chat.messenger.placeholder.style (:require [quo.foundations.colors :as colors] - [react-native.reanimated :as reanimated])) + [react-native.safe-area :as safe-area])) (defn container - [top opacity z-index theme] - (reanimated/apply-animations-to-style - {:opacity opacity - :z-index z-index} - {:position :absolute - :padding-top top - :top 0 - :left 0 - :right 0 - :bottom 0 - :background-color (colors/theme-colors colors/white colors/neutral-95 theme)})) + [theme on-layout-done?] + {:position :absolute + :padding-top (safe-area/get-top) + :top 0 + :left 0 + :right 0 + :bottom 0 + :background-color (colors/theme-colors colors/white colors/neutral-95 theme) + :opacity (if on-layout-done? 0 1) + :z-index (if on-layout-done? 0 2)}) diff --git a/src/status_im/contexts/chat/messenger/placeholder/view.cljs b/src/status_im/contexts/chat/messenger/placeholder/view.cljs index a17d2a99eb..8373b51d39 100644 --- a/src/status_im/contexts/chat/messenger/placeholder/view.cljs +++ b/src/status_im/contexts/chat/messenger/placeholder/view.cljs @@ -3,11 +3,8 @@ [quo.core :as quo] [quo.theme] [react-native.core :as rn] - [react-native.reanimated :as reanimated] - [react-native.safe-area :as safe-area] [status-im.contexts.chat.messenger.placeholder.style :as style] - [utils.re-frame :as rf] - [utils.worklets.chat.messenger.placeholder :as worklets])) + [utils.re-frame :as rf])) (defn- loading-skeleton [] @@ -17,13 +14,10 @@ :animated? false}]) (defn view - [chat-screen-layout-calculations-complete?] + [on-layout-done?] (let [theme (quo.theme/use-theme) - top (safe-area/get-top) - chat-exist? (rf/sub [:chats/current-chat-exist?]) - opacity (worklets/placeholder-opacity chat-screen-layout-calculations-complete?) - z-index (worklets/placeholder-z-index chat-screen-layout-calculations-complete?)] - [reanimated/view {:style (style/container top opacity z-index theme)} + chat-exist? (rf/sub [:chats/current-chat-exist?])] + [rn/view {:style (style/container theme @on-layout-done?)} (when-not chat-exist? [quo/page-nav {:icon-name :i/arrow-left diff --git a/src/utils/worklets/chat/messenger/messages.cljs b/src/utils/worklets/chat/messenger/messages.cljs index 6b91c55402..adfaf17a8e 100644 --- a/src/utils/worklets/chat/messenger/messages.cljs +++ b/src/utils/worklets/chat/messenger/messages.cljs @@ -6,8 +6,3 @@ [distance-from-list-top chat-list-scroll-y callback] (.messagesListOnScroll ^js worklets distance-from-list-top chat-list-scroll-y callback)) -(defn use-messages-scrolled-to-threshold - [distance-from-list-top threshold] - (.useMessagesScrolledToThreshold ^js worklets - distance-from-list-top - threshold)) diff --git a/src/utils/worklets/chat/messenger/navigation.cljs b/src/utils/worklets/chat/messenger/navigation.cljs deleted file mode 100644 index 7fcf4f97bd..0000000000 --- a/src/utils/worklets/chat/messenger/navigation.cljs +++ /dev/null @@ -1,27 +0,0 @@ -(ns utils.worklets.chat.messenger.navigation) - -(def ^:private worklets (js/require "../src/js/worklets/chat/messenger/navigation.js")) - -(defn navigation-header-opacity - [distance-from-list-top all-loaded? chat-screen-layout-calculations-complete? start-position] - (.navigationHeaderOpacity ^js worklets - distance-from-list-top - all-loaded? - chat-screen-layout-calculations-complete? - start-position)) - -(defn navigation-header-position - [distance-from-list-top all-loaded? top-bar-height start-position] - (.navigationHeaderPosition ^js worklets - distance-from-list-top - all-loaded? - top-bar-height - start-position)) - -(defn navigation-buttons-complete-opacity - [chat-screen-layout-calculations-complete?] - (.navigationButtonsCompleteOpacity ^js worklets chat-screen-layout-calculations-complete?)) - -(defn interpolate-navigation-view-opacity - [props] - (.interpolateNavigationViewOpacity ^js worklets (clj->js props))) diff --git a/src/utils/worklets/chat/messenger/placeholder.cljs b/src/utils/worklets/chat/messenger/placeholder.cljs deleted file mode 100644 index ed7ff5ec45..0000000000 --- a/src/utils/worklets/chat/messenger/placeholder.cljs +++ /dev/null @@ -1,11 +0,0 @@ -(ns utils.worklets.chat.messenger.placeholder) - -(def ^:private worklets (js/require "../src/js/worklets/chat/messenger/placeholder.js")) - -(defn placeholder-opacity - [chat-screen-layout-calculations-complete?] - (.placeholderOpacity ^js worklets chat-screen-layout-calculations-complete?)) - -(defn placeholder-z-index - [chat-screen-layout-calculations-complete?] - (.placeholderZIndex ^js worklets chat-screen-layout-calculations-complete?))