diff --git a/package.json b/package.json index 811fdcab47..cba2b25842 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "react-native-image-resizer": "^1.2.3", "react-native-keychain": "git+https://github.com/status-im/react-native-keychain.git#v.3.0.0-5-status", "react-native-languages": "^3.0.2", + "react-native-linear-gradient": "^2.5.6", "react-native-mail": "git+https://github.com/status-im/react-native-mail.git#v4.0.0-status", "react-native-navigation-bar-color": "^2.0.1", "react-native-permissions": "^2.1.5", diff --git a/src/mocks/js_dependencies.cljs b/src/mocks/js_dependencies.cljs index 22cf279737..f8b57679e6 100644 --- a/src/mocks/js_dependencies.cljs +++ b/src/mocks/js_dependencies.cljs @@ -190,6 +190,8 @@ #js {:localNotification identity :requestPermission identity}) +(def react-native-gradien #js {:default #js {}}) + (def push-notification-ios #js {}) ;; Update i18n_resources.cljs (defn mock [module] @@ -220,6 +222,7 @@ "react-native-haptic-feedback" react-native-haptic-feedback "react-native-device-info" react-native-device-info "react-native-push-notification" react-native-push-notification + "react-native-linear-gradient" react-native-gradien "@react-native-community/push-notification-ios" push-notification-ios "./fleets.js" default-fleets "./chats.js" default-chats diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 45bb8e96e2..cec965a248 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -2,7 +2,6 @@ (:require [re-frame.core :as re-frame] [status-im.chat.models :as chat-model] [status-im.chat.models.loading :as chat-loading] - [status-im.chat.models.message-content :as message-content] [status-im.chat.models.message-list :as message-list] [status-im.constants :as constants] [status-im.data-store.messages :as data-store.messages] @@ -14,16 +13,10 @@ [taoensso.timbre :as log])) (defn- prepare-message - [{:keys [content content-type] :as message} current-chat?] + [message current-chat?] (cond-> message current-chat? - (assoc :seen true) - - (and (= constants/content-type-text content-type) - (message-content/should-collapse? - (:text content) - (:line-count content))) - (assoc :should-collapse? true))) + (assoc :seen true))) (fx/defn rebuild-message-list [{:keys [db]} chat-id] diff --git a/src/status_im/chat/models/message_content.cljs b/src/status_im/chat/models/message_content.cljs index 7c5817ad69..d978b131d7 100644 --- a/src/status_im/chat/models/message_content.cljs +++ b/src/status_im/chat/models/message_content.cljs @@ -5,10 +5,6 @@ [:italic constants/regx-italic] [:backquote constants/regx-backquote]]) -(defn should-collapse? [text line-count] - (or (<= constants/chars-collapse-threshold (count text)) - (<= constants/lines-collapse-threshold (inc line-count)))) - (defn emoji-only-content? "Determines if text is just an emoji" [{:keys [text response-to]}] diff --git a/src/status_im/ui/components/react.cljs b/src/status_im/ui/components/react.cljs index 7b828d873c..e2d0c58788 100644 --- a/src/status_im/ui/components/react.cljs +++ b/src/status_im/ui/components/react.cljs @@ -9,7 +9,8 @@ ["react-native-image-crop-picker" :default image-picker] ["react-native-safe-area-context" :as safe-area-context :refer (SafeAreaProvider SafeAreaInsetsContext)] - ["@react-native-community/clipboard" :default Clipboard]) + ["@react-native-community/clipboard" :default Clipboard] + ["react-native-linear-gradient" :default LinearGradient]) (:require-macros [status-im.utils.views :as views])) (def native-modules (.-NativeModules react-native)) @@ -32,6 +33,8 @@ (defn image-get-size [uri callback] (.getSize (.-Image react-native) uri callback)) +(def linear-gradient (reagent/adapt-react-class LinearGradient)) + (defn valid-source? [source] (or (not (map? source)) (not (contains? source :uri)) diff --git a/src/status_im/ui/screens/chat/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs index 2cf5e4fa37..f13d2c9f42 100644 --- a/src/status_im/ui/screens/chat/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -236,28 +236,72 @@ [react/view [render-parsed-text message (:parsed-text content)]]]]]) +(def message-height-px 200) +(def max-message-height-px 150) + +(defn on-long-press-fn [on-long-press message content] + (on-long-press + [{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message]) + :label (i18n/label :t/message-reply)} + {:on-press #(react/copy-to-clipboard + (components.reply/get-quoted-text-with-mentions + (get content :parsed-text))) + :label (i18n/label :t/sharing-copy-to-clipboard)}])) + +(defn collapsible-text-message [_ _] + (let [collapsed? (reagent/atom false) + collapsible? (reagent/atom false)] + (fn [{:keys [content outgoing current-public-key public?] :as message} on-long-press modal] + [react/touchable-highlight + (when-not modal + {:on-press (fn [_] + (react/dismiss-keyboard!)) + :on-long-press (fn [] + (if @collapsed? + (do (reset! collapsed? false) + (js/setTimeout #(on-long-press-fn on-long-press message content) 200)) + (on-long-press-fn on-long-press message content)))}) + [react/view (assoc (style/message-view message) + :remove-clipped-subviews (not outgoing) + :max-height (when-not (or outgoing modal) + (if @collapsible? + (if @collapsed? message-height-px nil) + message-height-px))) + (let [response-to (:response-to content)] + [react/view {:on-layout + #(when (and (> (.-nativeEvent.layout.height ^js %) max-message-height-px) + (not @collapsible?) + (not outgoing) + (not modal)) + (reset! collapsed? true) + (reset! collapsible? true))} + (when (and (seq response-to) (:quoted-message message)) + [quoted-message response-to (:quoted-message message) outgoing current-public-key public?]) + [render-parsed-text-with-timestamp message (:parsed-text content)]]) + (when-not @collapsed? + [message-timestamp message true]) + (when (and @collapsible? (not modal)) + (if @collapsed? + [react/touchable-highlight + {:on-press #(swap! collapsed? not) + :style {:position :absolute :bottom 0 :left 0 :right 0 :height 72}} + [react/linear-gradient {:colors [(str colors/blue-light "00") colors/blue-light] + :start {:x 0 :y 0} :end {:x 0 :y 0.9}} + [react/view {:height 72 :align-self :center :justify-content :flex-end + :padding-bottom 10} + [react/view (style/collapse-button) + [vector-icons/icon :main-icons/dropdown + {:color colors/white}]]]]] + [react/touchable-highlight {:on-press #(swap! collapsed? not) + :style {:align-self :center :margin 5}} + [react/view (style/collapse-button) + [vector-icons/icon :main-icons/dropdown-up + {:color colors/white}]]]))]]))) + (defmethod ->message constants/content-type-text - [{:keys [content outgoing current-public-key public?] :as message} {:keys [on-long-press modal] - :as reaction-picker}] + [message {:keys [on-long-press modal] :as reaction-picker}] [message-content-wrapper message - [react/touchable-highlight (when-not modal - {:on-press (fn [_] - (react/dismiss-keyboard!)) - :on-long-press (fn [] - (on-long-press - [{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message]) - :label (i18n/label :t/message-reply)} - {:on-press #(react/copy-to-clipboard - (components.reply/get-quoted-text-with-mentions - (get content :parsed-text))) - :label (i18n/label :t/sharing-copy-to-clipboard)}]))}) - [react/view (style/message-view message) - (let [response-to (:response-to content)] - [react/view - (when (and (seq response-to) (:quoted-message message)) - [quoted-message response-to (:quoted-message message) outgoing current-public-key public?]) - [render-parsed-text-with-timestamp message (:parsed-text content)]]) - [message-timestamp message true]]] + [collapsible-text-message message on-long-press modal] reaction-picker]) (defmethod ->message constants/content-type-status diff --git a/src/status_im/ui/screens/chat/styles/message/message.cljs b/src/status_im/ui/screens/chat/styles/message/message.cljs index 96f453be0b..04d9cfe985 100644 --- a/src/status_im/ui/screens/chat/styles/message/message.cljs +++ b/src/status_im/ui/screens/chat/styles/message/message.cljs @@ -3,7 +3,8 @@ [status-im.ui.components.colors :as colors] [status-im.ui.components.react :as react] [status-im.ui.screens.chat.styles.photos :as photos] - [status-im.ui.components.typography :as typography])) + [status-im.ui.components.typography :as typography] + [quo.design-system.colors :as quo.colors])) (defn style-message-text [outgoing] @@ -109,10 +110,20 @@ :margin-right 12 :margin-top (if incoming-group 4 0)}) +(defn collapse-button [] + {:height 24 :width 24 :background-color colors/blue + :border-radius 12 :align-items :center :justify-content :center + :elevation 4 + :shadow-opacity 1 + :shadow-radius 16 + :shadow-color (:shadow-01 @quo.colors/theme) + :shadow-offset {:width 0 :height 4}}) + (defn message-view [{:keys [content-type outgoing group-chat last-in-group?]}] (merge - {:border-top-left-radius 16 + {:overflow :hidden + :border-top-left-radius 16 :border-top-right-radius 16 :border-bottom-right-radius 16 :border-bottom-left-radius 16 diff --git a/yarn.lock b/yarn.lock index 061bc4f0b8..bed54d8479 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6604,6 +6604,11 @@ react-native-languages@^3.0.2: resolved "https://registry.yarnpkg.com/react-native-languages/-/react-native-languages-3.0.2.tgz#c2c4c5050974fe4b50f7372051ca1f9824c1c778" integrity sha512-LGsTfixFM6hXDhcFJI6mrtrNBsGPSvXT9RtZQ0tlqmGFKmMyZW6eQgJ7kLw8lISD2FIGl4jJwY06EAJpbMsNxg== +react-native-linear-gradient@^2.5.6: + version "2.5.6" + resolved "https://registry.yarnpkg.com/react-native-linear-gradient/-/react-native-linear-gradient-2.5.6.tgz#96215cbc5ec7a01247a20890888aa75b834d44a0" + integrity sha512-HDwEaXcQIuXXCV70O+bK1rizFong3wj+5Q/jSyifKFLg0VWF95xh8XQgfzXwtq0NggL9vNjPKXa016KuFu+VFg== + "react-native-mail@git+https://github.com/status-im/react-native-mail.git#v4.0.0-status": version "4.0.0" resolved "git+https://github.com/status-im/react-native-mail.git#a5ff17c3e394b5545549fed33883afe4496f127a"