Base chat dedesign
Signed-off-by: Brian Sztamfater <brian@status.im>
|
@ -2,7 +2,7 @@ PODS:
|
|||
- boost-for-react-native (1.63.0)
|
||||
- BVLinearGradient (2.5.6):
|
||||
- React
|
||||
- CryptoSwift (1.4.3)
|
||||
- CryptoSwift (1.5.1)
|
||||
- DoubleConversion (1.1.6)
|
||||
- FBLazyVector (0.63.4)
|
||||
- FBReactNativeSpec (0.63.4):
|
||||
|
@ -349,7 +349,7 @@ PODS:
|
|||
- React
|
||||
- RNReactNativeHapticFeedback (1.9.0):
|
||||
- React
|
||||
- RNReanimated (2.1.0):
|
||||
- RNReanimated (2.3.3):
|
||||
- DoubleConversion
|
||||
- FBLazyVector
|
||||
- FBReactNativeSpec
|
||||
|
@ -375,7 +375,6 @@ PODS:
|
|||
- React-RCTNetwork
|
||||
- React-RCTSettings
|
||||
- React-RCTText
|
||||
- React-RCTVibration
|
||||
- ReactCommon/turbomodule/core
|
||||
- Yoga
|
||||
- RNShare (7.0.1):
|
||||
|
@ -468,7 +467,7 @@ DEPENDENCIES:
|
|||
- RNSVG (from `../node_modules/react-native-svg`)
|
||||
- secp256k1 (from `https://github.com/status-im/secp256k1.swift.git`)
|
||||
- SQLCipher (~> 3.0)
|
||||
- SSZipArchive
|
||||
- SSZipArchive (= 2.4.3)
|
||||
- TouchID (from `../node_modules/react-native-touch-id`)
|
||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||
|
||||
|
@ -631,14 +630,14 @@ CHECKOUT OPTIONS:
|
|||
SPEC CHECKSUMS:
|
||||
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
|
||||
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
|
||||
CryptoSwift: a0799ee936271bd2253a006f1e4523df21845000
|
||||
CryptoSwift: c4f2debceb38bf44c80659afe009f71e23e4a082
|
||||
DoubleConversion: cde416483dac037923206447da6e1454df403714
|
||||
FBLazyVector: 3bb422f41b18121b71783a905c10e58606f7dc3e
|
||||
FBReactNativeSpec: f2c97f2529dd79c083355182cc158c9f98f4bd6e
|
||||
Folly: b73c3869541e86821df3c387eb0af5f65addfab4
|
||||
glog: 2d7c14bbcd0c3139c6258f813895cb61d7860fcc
|
||||
glog: 502275bc0747df92346edbab1f40dacde2ec86d4
|
||||
HMSegmentedControl: 34c1f54d822d8308e7b24f5d901ec674dfa31352
|
||||
Keycard: 07f1b4d4fadcf1218084cb3e1bb3a8bac3870c5a
|
||||
Keycard: ac6df4d91525c3c82635ac24d4ddd9a80aca5fc8
|
||||
libwebp: 98a37e597e40bfdb4c911fc98f2c53d0b12d05fc
|
||||
Permission-Camera: afad27bf90337684d4a86f3825112d648c8c4d3b
|
||||
Permission-Microphone: 0ffabc3fe1c75cfb260525ee3f529383c9f4368c
|
||||
|
@ -666,7 +665,7 @@ SPEC CHECKSUMS:
|
|||
react-native-shake: de052eaa3eadc4a326b8ddd7ac80c06e8d84528c
|
||||
react-native-slider: 12bd76d3d568c9c5500825db54123d44b48e4ad4
|
||||
react-native-splash-screen: 4312f786b13a81b5169ef346d76d33bc0c6dc457
|
||||
react-native-status: 45dbf1302ce3c258b459dfab137cd1c2c68c295d
|
||||
react-native-status: 21f75d492fd311dc111303da38a7a2b23a8a8466
|
||||
react-native-status-keycard: 961d01ca190889ddf220206822fd752f8f4f3f7a
|
||||
react-native-webview: 28a8636d97ee641f2ee8f20492d7a6c269c1d703
|
||||
React-RCTActionSheet: 89a0ca9f4a06c1f93c26067af074ccdce0f40336
|
||||
|
@ -693,7 +692,7 @@ SPEC CHECKSUMS:
|
|||
RNLanguages: 962e562af0d34ab1958d89bcfdb64fafc37c513e
|
||||
RNPermissions: ad71dd4f767ec254f2cd57592fbee02afee75467
|
||||
RNReactNativeHapticFeedback: 2566b468cc8d0e7bb2f84b23adc0f4614594d071
|
||||
RNReanimated: 70f662b5232dd5d19ccff581e919a54ea73df51c
|
||||
RNReanimated: 69eda0e8790a2ee00de2fff03e89361e9bac749a
|
||||
RNShare: 2dc2fcac3f7321cfd6b60a23ed4bf4d549f86f5f
|
||||
RNSVG: 8ba35cbeb385a52fd960fd28db9d7d18b4c2974f
|
||||
SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d
|
||||
|
@ -705,6 +704,6 @@ SPEC CHECKSUMS:
|
|||
TouchID: ba4c656d849cceabc2e4eef722dea5e55959ecf4
|
||||
Yoga: 4bd86afe9883422a7c4028c00e34790f560923d6
|
||||
|
||||
PODFILE CHECKSUM: 1a5b8878f89edd08eb4d37898a3a8721a7bb3388
|
||||
PODFILE CHECKSUM: a1de9468266e7f0b5273acea713782ab759690f1
|
||||
|
||||
COCOAPODS: 1.11.0
|
||||
COCOAPODS: 1.11.3
|
||||
|
|
After Width: | Height: | Size: 1014 B |
After Width: | Height: | Size: 1.6 KiB |
After Width: | Height: | Size: 498 B |
After Width: | Height: | Size: 659 B |
After Width: | Height: | Size: 569 B |
After Width: | Height: | Size: 819 B |
After Width: | Height: | Size: 463 B |
After Width: | Height: | Size: 605 B |
After Width: | Height: | Size: 773 B |
After Width: | Height: | Size: 1.0 KiB |
After Width: | Height: | Size: 851 B |
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 909 B |
After Width: | Height: | Size: 1.3 KiB |
|
@ -193,5 +193,19 @@
|
|||
(def switcher-background-opa-90 (alpha switcher-background 0.9))
|
||||
(def switcher-background-opa-95 (alpha switcher-background 0.95))
|
||||
|
||||
;;General
|
||||
|
||||
;; background
|
||||
|
||||
(def ui-background-02-light "#F5F9FA")
|
||||
|
||||
;; divider
|
||||
(def divider-light "#EDF2f4")
|
||||
(def divider-dark "#0E1620")
|
||||
|
||||
;; Visibility status
|
||||
|
||||
(def color-online "#26A69A")
|
||||
|
||||
(defn theme-colors [light dark]
|
||||
(if (theme/dark?) dark light))
|
||||
|
|
|
@ -29,4 +29,4 @@
|
|||
|
||||
(def font-bold {:font-family "Inter-Bold"}) ; 700
|
||||
|
||||
(def monospace {:font-family "InterStatus-Regular"})
|
||||
(def monospace {:font-family "InterStatus-Regular"})
|
|
@ -63,6 +63,25 @@
|
|||
[react/view {:style dot-styles
|
||||
:accessibility-label dot-accessibility-label}])]))
|
||||
|
||||
(defn profile-photo-plus-dot-view-old
|
||||
[{:keys [public-key photo-container photo-path community?]}]
|
||||
(let [photo-path (if (nil? photo-path)
|
||||
@(re-frame.core/subscribe [:chats/photo-path public-key])
|
||||
photo-path)
|
||||
photo-container (if (nil? photo-container)
|
||||
styles/container-chat-list photo-container)
|
||||
size (:width photo-container)
|
||||
identicon? (when photo-path (profile.db/base64-png? photo-path))
|
||||
dot-styles (visibility-status-utils/icon-visibility-status-dot-old
|
||||
public-key size identicon?)
|
||||
dot-accessibility-label (:accessibility-label dot-styles)]
|
||||
[react/view {:style photo-container
|
||||
:accessibility-label :profile-photo}
|
||||
[photos/photo photo-path {:size size}]
|
||||
(when-not community?
|
||||
[react/view {:style dot-styles
|
||||
:accessibility-label dot-accessibility-label}])]))
|
||||
|
||||
(defn emoji-chat-icon-view
|
||||
[chat-id group-chat name emoji styles]
|
||||
[react/view (:container styles)
|
||||
|
@ -73,6 +92,16 @@
|
|||
[profile-photo-plus-dot-view {:public-key chat-id
|
||||
:photo-container (:default-chat-icon styles)}])])
|
||||
|
||||
(defn emoji-chat-icon-view-old
|
||||
[chat-id group-chat name emoji styles]
|
||||
[react/view (:container styles)
|
||||
(if group-chat
|
||||
(if (string/blank? emoji)
|
||||
[default-chat-icon name styles]
|
||||
[emoji-chat-icon emoji styles])
|
||||
[profile-photo-plus-dot-view-old {:public-key chat-id
|
||||
:photo-container (:default-chat-icon styles)}])])
|
||||
|
||||
(defn chat-icon-view-toolbar
|
||||
[chat-id group-chat name color emoji]
|
||||
[emoji-chat-icon-view chat-id group-chat name emoji
|
||||
|
@ -163,10 +192,10 @@
|
|||
(styles/emoji-chat-icon-text size))} override-styles)]
|
||||
[react/view (:container styles)
|
||||
(if (and photo-path (seq photo-path))
|
||||
[profile-photo-plus-dot-view {:photo-path photo-path
|
||||
:public-key public-key
|
||||
:photo-container (:container styles)
|
||||
:community? community?}]
|
||||
[profile-photo-plus-dot-view-old {:photo-path photo-path
|
||||
:public-key public-key
|
||||
:photo-container (:container styles)
|
||||
:community? community?}]
|
||||
(if (string/blank? emoji)
|
||||
[default-chat-icon name styles]
|
||||
[emoji-chat-icon emoji styles]))
|
||||
|
|
|
@ -2,9 +2,24 @@
|
|||
(:require [quo.design-system.colors :as colors]
|
||||
[quo.core :as quo]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.icons :as icons]))
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[quo2.components.button :as quo2.button]))
|
||||
|
||||
(def action-button-container
|
||||
{:align-items :center
|
||||
:justify-content :center
|
||||
:height 32
|
||||
:border-radius 16
|
||||
:overflow :hidden})
|
||||
|
||||
(defn action-button []
|
||||
{:width 32
|
||||
:height 32
|
||||
:border-radius 18
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def action-button-container-old
|
||||
{:position :absolute
|
||||
:z-index 2
|
||||
:align-items :center
|
||||
|
@ -14,7 +29,7 @@
|
|||
:bottom 16
|
||||
:height 40})
|
||||
|
||||
(defn action-button []
|
||||
(defn action-button-old []
|
||||
{:width 40
|
||||
:height 40
|
||||
:background-color colors/blue
|
||||
|
@ -31,10 +46,23 @@
|
|||
|
||||
(defn plus-button [{:keys [on-press loading accessibility-label]}]
|
||||
[react/view action-button-container
|
||||
[quo/button {:type :scale
|
||||
:accessibility-label (or accessibility-label :plus-button)
|
||||
:on-press on-press}
|
||||
[quo2.button/button {:type :primary
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label (or accessibility-label :plus-button)
|
||||
:on-press on-press}
|
||||
[react/view (action-button)
|
||||
(if loading
|
||||
[react/activity-indicator {:color colors/white-persist
|
||||
:animating true}]
|
||||
[icons/icon :main-icons/add {:color colors/white-persist}])]]])
|
||||
|
||||
(defn plus-button-old [{:keys [on-press loading accessibility-label]}]
|
||||
[react/view action-button-container-old
|
||||
[quo/button {:type :scale
|
||||
:accessibility-label (or accessibility-label :plus-button)
|
||||
:on-press on-press}
|
||||
[react/view (action-button-old)
|
||||
(if loading
|
||||
[react/activity-indicator {:color colors/white-persist
|
||||
:animating true}]
|
||||
|
|
|
@ -2,9 +2,53 @@
|
|||
(:require [reagent.core :as reagent]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[quo.core :as quo]
|
||||
[quo.design-system.colors :as colors]))
|
||||
[quo.design-system.colors :as colors]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(defn search-input [{:keys [search-active?]}]
|
||||
(let [input-ref (atom nil)
|
||||
search-active? (or search-active? (reagent/atom nil))]
|
||||
(fn [{:keys [on-focus on-change on-blur on-cancel search-filter auto-focus]}]
|
||||
[quo/text-input {:placeholder (i18n/label :t/search)
|
||||
:accessibility-label :search-input
|
||||
:blur-on-submit true
|
||||
:multiline false
|
||||
:get-ref #(reset! input-ref %)
|
||||
:default-value search-filter
|
||||
:auto-focus auto-focus
|
||||
:on-cancel on-cancel
|
||||
:show-cancel true
|
||||
:auto-correct false
|
||||
:auto-capitalize :none
|
||||
:container-style {:border-radius 10
|
||||
:border-width 1
|
||||
:border-color (:ui-01 @colors/theme)
|
||||
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
|
||||
:overflow :hidden}
|
||||
:input-style {:height 32
|
||||
:padding-top 2
|
||||
:padding-bottom 2
|
||||
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}
|
||||
:before {:icon :main-icons/search2
|
||||
:style {:padding-horizontal 8
|
||||
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}
|
||||
:on-press #(some-> ^js @input-ref (.focus))
|
||||
:icon-opts {:color (quo2.colors/theme-colors quo2.colors/neutral-50 quo2.colors/white)}}
|
||||
:on-focus #(do
|
||||
(when on-focus
|
||||
(on-focus search-filter))
|
||||
(reset! search-active? true))
|
||||
:on-blur #(do
|
||||
(when on-blur
|
||||
(on-blur))
|
||||
(reset! search-active? false))
|
||||
:on-change (fn [e]
|
||||
(let [^js native-event (.-nativeEvent ^js e)
|
||||
text (.-text native-event)]
|
||||
(when on-change
|
||||
(on-change text))))}])))
|
||||
|
||||
(defn search-input-old [{:keys [search-active?]}]
|
||||
(let [input-ref (atom nil)
|
||||
search-active? (or search-active? (reagent/atom nil))]
|
||||
(fn [{:keys [on-focus on-change on-blur on-cancel search-filter auto-focus]}]
|
||||
|
@ -38,4 +82,4 @@
|
|||
(let [^js native-event (.-nativeEvent ^js e)
|
||||
text (.-text native-event)]
|
||||
(when on-change
|
||||
(on-change text))))}])))
|
||||
(on-change text))))}])))
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.ui.components.topbar
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[quo.core :as quo]))
|
||||
[quo.core :as quo]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(def default-button-width 48)
|
||||
|
||||
|
@ -20,7 +21,9 @@
|
|||
label
|
||||
(assoc :label label)))
|
||||
|
||||
(defn topbar [{:keys [navigation use-insets right-accessories modal? content]
|
||||
(defn topbar [{:keys [navigation use-insets right-accessories modal? content border-bottom? new-ui?] ;; remove new-ui? key, temp fix
|
||||
:or {border-bottom? true
|
||||
new-ui? false}
|
||||
:as props}]
|
||||
(let [navigation (if (= navigation :none)
|
||||
nil
|
||||
|
@ -31,7 +34,10 @@
|
|||
:title-component content
|
||||
:insets (when use-insets insets)
|
||||
:left-width (when navigation
|
||||
default-button-width)}
|
||||
default-button-width)
|
||||
:border-bottom border-bottom?}
|
||||
props
|
||||
(when (seq right-accessories)
|
||||
{:right-accessories right-accessories}))])]))
|
||||
{:right-accessories right-accessories})
|
||||
(when new-ui?
|
||||
{:background (quo2.colors/theme-colors quo2.colors/white quo2.colors/divider-dark)}))])]))
|
||||
|
|
|
@ -71,5 +71,5 @@
|
|||
:key-fn :browser-id
|
||||
:render-fn list-item}]
|
||||
|
||||
[components.plus-button/plus-button
|
||||
[components.plus-button/plus-button-old
|
||||
{:on-press #(re-frame/dispatch [:browser.ui/open-empty-tab])}]]))
|
|
@ -171,16 +171,16 @@
|
|||
(update-state params))
|
||||
#(update-state (merge params {:error (:message %)}))))))
|
||||
|
||||
(defn- play-pause-button [state-ref outgoing on-press]
|
||||
(let [color (if outgoing colors/blue colors/white-persist)]
|
||||
(defn- play-pause-button [state-ref on-press]
|
||||
(let [color colors/blue]
|
||||
(if (= (:general @state-ref) :preparing)
|
||||
[react/view {:style (style/play-pause-container outgoing true)}
|
||||
[react/view {:style (style/play-pause-container true)}
|
||||
[react/small-loading-indicator color]]
|
||||
[react/touchable-highlight {:on-press on-press}
|
||||
[icons/icon (case (:general @state-ref)
|
||||
:playing :main-icons/pause
|
||||
:main-icons/play)
|
||||
{:container-style (style/play-pause-container outgoing false)
|
||||
{:container-style (style/play-pause-container false)
|
||||
:accessibility-label :play-pause-audio-message-button
|
||||
:color color}]])))
|
||||
|
||||
|
@ -193,7 +193,7 @@
|
|||
:message-id @current-player-message-id}))
|
||||
nil)
|
||||
|
||||
(defview message-content [{:keys [audio audio-duration-ms message-id outgoing]}]
|
||||
(defview message-content [{:keys [audio audio-duration-ms message-id]}]
|
||||
(letsubs [state (reagent/atom nil)
|
||||
progress (reagent/atom 0)
|
||||
progress-anim (anim/create-value 0)
|
||||
|
@ -218,9 +218,9 @@
|
|||
:margin-bottom 16}} (:error-msg @state)]
|
||||
[react/view (style/container width)
|
||||
[react/view style/play-pause-slider-container
|
||||
[play-pause-button state outgoing #(play-pause base-params audio)]
|
||||
[play-pause-button state #(play-pause base-params audio)]
|
||||
[react/view style/slider-container
|
||||
[slider/animated-slider (merge (style/slider outgoing)
|
||||
[slider/animated-slider (merge (style/slider)
|
||||
{:minimum-value 0
|
||||
:maximum-value (:duration @state)
|
||||
:value progress-anim
|
||||
|
@ -229,7 +229,7 @@
|
|||
:on-sliding-complete #(seek (merge base-params {:slider-new-state-seeking? false}) % true nil)})]]]
|
||||
|
||||
[react/view style/times-container
|
||||
[react/text {:style (style/timestamp outgoing)}
|
||||
[react/text {:style (style/timestamp)}
|
||||
(let [time (cond
|
||||
(or (:slider-seeking @state) (> (:seek-to-ms @state) 0)) (:seek-to-ms @state)
|
||||
(#{:playing :paused :seeking} (:general @state)) @progress
|
||||
|
|
|
@ -0,0 +1,238 @@
|
|||
(ns status-im.ui.screens.chat.message.audio-old
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.utils.utils :as utils]
|
||||
[reagent.core :as reagent]
|
||||
[goog.string :as gstring]
|
||||
[status-im.audio.core :as audio]
|
||||
[status-im.utils.fx :as fx]
|
||||
[status-im.ui.screens.chat.styles.message.audio-old :as style]
|
||||
[status-im.ui.components.animation :as anim]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.slider :as slider]
|
||||
["react-native-blob-util" :default ReactNativeBlobUtil]
|
||||
[status-im.utils.platform :as platform]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defonce player-ref (atom nil))
|
||||
(defonce current-player-message-id (atom nil))
|
||||
(defonce current-active-state-ref-ref (atom nil))
|
||||
(defonce progress-timer (atom nil))
|
||||
|
||||
(defn start-stop-progress-timer [{:keys [state-ref progress-ref progress-anim]} start?]
|
||||
(when @progress-timer
|
||||
(utils/clear-interval @progress-timer)
|
||||
(when-not start?
|
||||
(reset! progress-timer nil)))
|
||||
(when start?
|
||||
(when @progress-timer
|
||||
(utils/clear-interval @progress-timer))
|
||||
(reset! progress-timer (utils/set-interval
|
||||
#(when (and @state-ref (not (:slider-seeking @state-ref)))
|
||||
(let [ct (audio/get-player-current-time @player-ref)]
|
||||
(reset! progress-ref ct)
|
||||
(when ct
|
||||
(anim/start (anim/timing progress-anim {:toValue @progress-ref
|
||||
:duration 100
|
||||
:easing (.-linear ^js anim/easing)
|
||||
:useNativeDriver true})))))
|
||||
100))))
|
||||
|
||||
(defn update-state [{:keys [state-ref progress-ref progress-anim message-id seek-to-ms audio-duration-ms slider-new-state-seeking? unloaded? error]}]
|
||||
(let [player-state (audio/get-state @player-ref)
|
||||
slider-seeking (if (some? slider-new-state-seeking?)
|
||||
slider-new-state-seeking?
|
||||
(:slider-seeking @state-ref))
|
||||
general (cond
|
||||
(some? error) :error
|
||||
(or unloaded? (not= message-id @current-player-message-id)) :not-loaded
|
||||
slider-seeking (:general @state-ref) ; persist player state at the time user started sliding
|
||||
(= player-state audio/PLAYING) :playing
|
||||
(= player-state audio/PAUSED) :paused
|
||||
(= player-state audio/SEEKING) :seeking
|
||||
(= player-state audio/PREPARED) :ready-to-play
|
||||
:else :preparing)
|
||||
new-state {:general general
|
||||
:error-msg error
|
||||
:duration (cond (not (#{:preparing :not-loaded :error} general))
|
||||
(audio/get-player-duration @player-ref)
|
||||
|
||||
audio-duration-ms audio-duration-ms
|
||||
|
||||
:else (:duration @state-ref))
|
||||
:progress-ref (or progress-ref (:progress-ref @state-ref))
|
||||
:progress-anim (or progress-anim (:progress-anim @state-ref))
|
||||
:slider-seeking slider-seeking
|
||||
|
||||
; persist seek-to-ms while seeking or audio is not loaded
|
||||
:seek-to-ms (when (or
|
||||
slider-seeking
|
||||
(#{:preparing :not-loaded :error} general))
|
||||
(or seek-to-ms (:seek-to-ms @state-ref)))}]
|
||||
; update state if needed
|
||||
(when (not= @state-ref new-state)
|
||||
(reset! state-ref new-state))
|
||||
|
||||
; update progress UI on slider release
|
||||
(when (and (some? slider-new-state-seeking?) (not slider-new-state-seeking?) (some? seek-to-ms))
|
||||
(reset! (:progress-ref new-state) seek-to-ms))
|
||||
|
||||
; update progres anim value to follow the slider
|
||||
(when (and slider-seeking (some? seek-to-ms))
|
||||
(anim/set-value (:progress-anim new-state) seek-to-ms))
|
||||
|
||||
; on unload, reset values
|
||||
(when unloaded?
|
||||
(reset! (:progress-ref new-state) 0)
|
||||
(anim/set-value (:progress-anim new-state) 0))))
|
||||
|
||||
(defn destroy-player [{:keys [message-id reloading?]}]
|
||||
(when (and @player-ref (or reloading?
|
||||
(= message-id @current-player-message-id)))
|
||||
(audio/destroy-player @player-ref)
|
||||
(reset! player-ref nil)
|
||||
(when @current-active-state-ref-ref
|
||||
(update-state {:state-ref @current-active-state-ref-ref :unloaded? true}))
|
||||
(reset! current-player-message-id nil)
|
||||
(reset! current-active-state-ref-ref nil)))
|
||||
|
||||
(defonce last-seek (atom (js/Date.now)))
|
||||
|
||||
(defn seek [{:keys [message-id] :as params} value immediate? on-success]
|
||||
(when (and @player-ref (= message-id @current-player-message-id))
|
||||
(let [now (js/Date.now)]
|
||||
(when (or immediate? (> (- now @last-seek) 200))
|
||||
(reset! last-seek (js/Date.now))
|
||||
(audio/seek-player
|
||||
@player-ref
|
||||
value
|
||||
#(do
|
||||
(update-state params)
|
||||
(when on-success (on-success)))
|
||||
#(update-state (merge params {:error (:message %)}))))))
|
||||
(update-state (merge params {:seek-to-ms value})))
|
||||
|
||||
(defn download-audio-http [base64-uri on-success]
|
||||
(-> (.config ReactNativeBlobUtil (clj->js {:trusty platform/ios?}))
|
||||
(.fetch "GET" (str base64-uri))
|
||||
(.then #(on-success (.base64 ^js %)))
|
||||
(.catch #(log/error "could not fetch audio"))))
|
||||
|
||||
(defn reload-player [{:keys [message-id state-ref] :as params} audio-url on-success]
|
||||
;; to avoid reloading player while is initializing,
|
||||
;; we go ahead only if there is no player or
|
||||
;; if it is already prepared
|
||||
(when (or (nil? @player-ref) (audio/can-play? @player-ref))
|
||||
(when @player-ref
|
||||
(destroy-player (merge params {:reloading? true})))
|
||||
(download-audio-http
|
||||
audio-url
|
||||
(fn [base64-data]
|
||||
(reset! player-ref (audio/new-player
|
||||
(str "data:audio/acc;base64," base64-data)
|
||||
{:autoDestroy false
|
||||
:continuesToPlayInBackground false}
|
||||
#(seek params 0 true nil)))
|
||||
(audio/prepare-player
|
||||
@player-ref
|
||||
#(when on-success (on-success))
|
||||
#(update-state (merge params {:error (:message %)})))
|
||||
(reset! current-player-message-id message-id)
|
||||
(reset! current-active-state-ref-ref state-ref)
|
||||
(update-state params)))))
|
||||
|
||||
(defn play-pause [{:keys [message-id state-ref] :as params} audio]
|
||||
(if (not= message-id @current-player-message-id)
|
||||
;; player has audio from another message, we need to reload
|
||||
(reload-player params
|
||||
audio
|
||||
;; on-success: audio is loaded, do we have an existing value to seek to?
|
||||
#(if-some [seek-time (:seek-to-ms @state-ref)]
|
||||
;; check seek time against real audio duration and play
|
||||
(let [checked-seek-time (min (audio/get-player-duration @player-ref) seek-time)]
|
||||
(seek params
|
||||
checked-seek-time
|
||||
true
|
||||
(fn [] (play-pause params audio))))
|
||||
|
||||
;; nothing to seek to, play
|
||||
(play-pause params audio)))
|
||||
|
||||
;; loaded audio corresponds to current message we can play
|
||||
(when @player-ref
|
||||
(audio/toggle-playpause-player
|
||||
@player-ref
|
||||
#(do
|
||||
(start-stop-progress-timer params true)
|
||||
(update-state params))
|
||||
#(do
|
||||
(start-stop-progress-timer params false)
|
||||
(update-state params))
|
||||
#(update-state (merge params {:error (:message %)}))))))
|
||||
|
||||
(defn- play-pause-button [state-ref outgoing on-press]
|
||||
(let [color (if outgoing colors/blue colors/white-persist)]
|
||||
(if (= (:general @state-ref) :preparing)
|
||||
[react/view {:style (style/play-pause-container outgoing true)}
|
||||
[react/small-loading-indicator color]]
|
||||
[react/touchable-highlight {:on-press on-press}
|
||||
[icons/icon (case (:general @state-ref)
|
||||
:playing :main-icons/pause
|
||||
:main-icons/play)
|
||||
{:container-style (style/play-pause-container outgoing false)
|
||||
:accessibility-label :play-pause-audio-message-button
|
||||
:color color}]])))
|
||||
|
||||
(fx/defn on-background
|
||||
{:events [:audio-message/on-background]}
|
||||
[_]
|
||||
(when (and @current-active-state-ref-ref
|
||||
@@current-active-state-ref-ref)
|
||||
(update-state {:state-ref @current-active-state-ref-ref
|
||||
:message-id @current-player-message-id}))
|
||||
nil)
|
||||
|
||||
(defview message-content [{:keys [audio audio-duration-ms message-id outgoing]}]
|
||||
(letsubs [state (reagent/atom nil)
|
||||
progress (reagent/atom 0)
|
||||
progress-anim (anim/create-value 0)
|
||||
width [:dimensions/window-width]]
|
||||
{:component-did-mount (fn []
|
||||
(update-state {:state-ref state
|
||||
:audio-duration-ms audio-duration-ms
|
||||
:message-id message-id
|
||||
:unloaded? true
|
||||
:progress-ref progress
|
||||
:progress-anim progress-anim}))
|
||||
:component-will-unmount (fn []
|
||||
(destroy-player {:state-ref state :message-id message-id})
|
||||
(when (= @current-player-message-id message-id)
|
||||
(reset! current-active-state-ref-ref nil)
|
||||
(reset! current-player-message-id nil))
|
||||
(reset! state nil))}
|
||||
|
||||
(let [base-params {:state-ref state :message-id message-id :progress-ref progress :progress-anim progress-anim}]
|
||||
(if (= (:general @state) :error)
|
||||
[react/text {:style {:typography :main-medium
|
||||
:margin-bottom 16}} (:error-msg @state)]
|
||||
[react/view (style/container width)
|
||||
[react/view style/play-pause-slider-container
|
||||
[play-pause-button state outgoing #(play-pause base-params audio)]
|
||||
[react/view style/slider-container
|
||||
[slider/animated-slider (merge (style/slider outgoing)
|
||||
{:minimum-value 0
|
||||
:maximum-value (:duration @state)
|
||||
:value progress-anim
|
||||
:on-value-change #(seek base-params % false nil)
|
||||
:on-sliding-start #(seek (merge base-params {:slider-new-state-seeking? true}) % true nil)
|
||||
:on-sliding-complete #(seek (merge base-params {:slider-new-state-seeking? false}) % true nil)})]]]
|
||||
|
||||
[react/view style/times-container
|
||||
[react/text {:style (style/timestamp outgoing)}
|
||||
(let [time (cond
|
||||
(or (:slider-seeking @state) (> (:seek-to-ms @state) 0)) (:seek-to-ms @state)
|
||||
(#{:playing :paused :seeking} (:general @state)) @progress
|
||||
:else (:duration @state))
|
||||
s (quot time 1000)]
|
||||
(gstring/format "%02d:%02d" (quot s 60) (mod s 60)))]]]))))
|
|
@ -1,12 +1,17 @@
|
|||
(ns status-im.ui.screens.chat.message.datemark
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.screens.chat.styles.message.datemark :as style]))
|
||||
[status-im.ui.screens.chat.styles.message.datemark :as style]
|
||||
[quo2.components.text :as quo2.text]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(defn chat-datemark [value]
|
||||
[react/touchable-without-feedback
|
||||
{:on-press (fn [_]
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view style/datemark-mobile
|
||||
[react/text {:style (style/datemark-text)}
|
||||
(string/capitalize value)]]])
|
||||
[quo2.text/text {:weight :medium
|
||||
:accessibility-label :message-datemark-text
|
||||
:style {:color quo2.colors/neutral-50}}
|
||||
(string/capitalize value)]
|
||||
[react/view (style/divider)]]])
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
(ns status-im.ui.screens.chat.message.datemark-old
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.screens.chat.styles.message.datemark-old :as style]))
|
||||
|
||||
(defn chat-datemark [value]
|
||||
[react/touchable-without-feedback
|
||||
{:on-press (fn [_]
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view style/datemark-mobile
|
||||
[react/text {:style (style/datemark-text)}
|
||||
(string/capitalize value)]]])
|
|
@ -73,13 +73,13 @@
|
|||
:height 12
|
||||
:color (if pinned colors/gray colors/white)
|
||||
:accessibility-label (name outgoing-status)}])
|
||||
(when edited-at [react/text {:style (style/message-status-text (and outgoing (not pinned)))} edited-at-text])]))
|
||||
(when edited-at [react/text {:style (style/message-status-text)} edited-at-text])]))
|
||||
|
||||
(defn message-timestamp
|
||||
[{:keys [timestamp-str in-popover?] :as message} show-timestamp?]
|
||||
[{:keys [timestamp-str in-popover?]} show-timestamp?]
|
||||
(when-not in-popover? ;; We keep track if showing this message in a list in pin-limit-popover
|
||||
(let [anim-opacity (animation/create-value 0)]
|
||||
[react/animated-view {:style (style/message-timestamp-wrapper message) :opacity anim-opacity}
|
||||
[react/animated-view {:style (style/message-timestamp-wrapper) :opacity anim-opacity}
|
||||
(when @show-timestamp? (message-timestamp-anim anim-opacity show-timestamp?))
|
||||
[react/text
|
||||
{:style (style/message-timestamp-text)
|
||||
|
@ -87,16 +87,16 @@
|
|||
timestamp-str]])))
|
||||
|
||||
(defview quoted-message
|
||||
[_ {:keys [from parsed-text image]} outgoing current-public-key public? pinned]
|
||||
[_ {:keys [from parsed-text image]} current-public-key public? pinned]
|
||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||
[react/view {:style (style/quoted-message-container (and outgoing (not pinned)))}
|
||||
[react/view {:style (style/quoted-message-container)}
|
||||
[react/view {:style style/quoted-message-author-container}
|
||||
[chat.utils/format-reply-author
|
||||
from
|
||||
contact-name
|
||||
current-public-key
|
||||
(partial style/quoted-message-author (and outgoing (not pinned)))
|
||||
(and outgoing (not pinned))]]
|
||||
(partial style/quoted-message-author (not pinned))
|
||||
false]]
|
||||
(if (and image
|
||||
;; Disabling images for public-chats
|
||||
(not public?))
|
||||
|
@ -105,11 +105,11 @@
|
|||
:background-color :black
|
||||
:border-radius 4}
|
||||
:source {:uri image}}]
|
||||
[react/text {:style (style/quoted-message-text (and outgoing (not pinned)))
|
||||
[react/text {:style (style/quoted-message-text)
|
||||
:number-of-lines 5}
|
||||
(components.reply/get-quoted-text-with-mentions parsed-text)])]))
|
||||
|
||||
(defn render-inline [message-text outgoing pinned content-type acc {:keys [type literal destination]}]
|
||||
(defn render-inline [message-text content-type acc {:keys [type literal destination]}]
|
||||
(case type
|
||||
""
|
||||
(conj acc literal)
|
||||
|
@ -121,22 +121,22 @@
|
|||
literal])
|
||||
|
||||
"emph"
|
||||
(conj acc [react/text-class (style/emph-style (and outgoing (not pinned))) literal])
|
||||
(conj acc [react/text-class (style/emph-style) literal])
|
||||
|
||||
"strong"
|
||||
(conj acc [react/text-class (style/strong-style (and outgoing (not pinned))) literal])
|
||||
(conj acc [react/text-class (style/strong-style) literal])
|
||||
|
||||
"strong-emph"
|
||||
(conj acc [quo/text (style/strong-emph-style (and outgoing (not pinned))) literal])
|
||||
(conj acc [quo/text (style/strong-emph-style) literal])
|
||||
|
||||
"del"
|
||||
(conj acc [react/text-class (style/strikethrough-style (and outgoing (not pinned))) literal])
|
||||
(conj acc [react/text-class (style/strikethrough-style) literal])
|
||||
|
||||
"link"
|
||||
(conj acc
|
||||
[react/text-class
|
||||
{:style
|
||||
{:color (if (and outgoing (not pinned)) colors/white-persist colors/blue)
|
||||
{:color colors/blue
|
||||
:text-decoration-line :underline}
|
||||
:on-press
|
||||
#(when (and (security/safe-link? destination)
|
||||
|
@ -149,14 +149,13 @@
|
|||
(conj acc [react/text-class
|
||||
{:style {:color (cond
|
||||
(= content-type constants/content-type-system-text) colors/black
|
||||
(and outgoing (not pinned)) colors/mention-outgoing
|
||||
:else colors/mention-incoming)}
|
||||
:on-press (when-not (= content-type constants/content-type-system-text)
|
||||
#(re-frame/dispatch [:chat.ui/show-profile literal]))}
|
||||
[mention-element literal]])
|
||||
"status-tag"
|
||||
(conj acc [react/text-class
|
||||
{:style {:color (if (and outgoing (not pinned)) colors/white-persist colors/blue)
|
||||
{:style {:color colors/blue
|
||||
:text-decoration-line :underline}
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
|
@ -166,19 +165,19 @@
|
|||
|
||||
(conj acc literal)))
|
||||
|
||||
(defn render-block [{:keys [content outgoing content-type pinned in-popover?]} acc
|
||||
(defn render-block [{:keys [content content-type in-popover?]} acc
|
||||
{:keys [type ^js literal children]}]
|
||||
(case type
|
||||
|
||||
"paragraph"
|
||||
(conj acc (reduce
|
||||
(fn [acc e] (render-inline (:text content) outgoing pinned content-type acc e))
|
||||
[react/text-class (style/text-style (and outgoing (not pinned)) content-type in-popover?)]
|
||||
(fn [acc e] (render-inline (:text content) content-type acc e))
|
||||
[react/text-class (style/text-style content-type in-popover?)]
|
||||
children))
|
||||
|
||||
"blockquote"
|
||||
(conj acc [react/view (style/blockquote-style (and outgoing (not pinned)))
|
||||
[react/text-class (style/blockquote-text-style (and outgoing (not pinned)))
|
||||
(conj acc [react/view (style/blockquote-style)
|
||||
[react/text-class (style/blockquote-text-style)
|
||||
(.substring literal 0 (.-length literal))]])
|
||||
|
||||
"codeblock"
|
||||
|
@ -193,10 +192,10 @@
|
|||
(defn render-parsed-text [message tree]
|
||||
(reduce (fn [acc e] (render-block message acc e)) [:<>] tree))
|
||||
|
||||
(defn render-parsed-text-with-message-status [{:keys [outgoing edited-at in-popover?] :as message} tree]
|
||||
(defn render-parsed-text-with-message-status [{:keys [edited-at in-popover?] :as message} tree]
|
||||
(let [elements (render-parsed-text message tree)
|
||||
message-status [react/text {:style (style/message-status-placeholder)}
|
||||
(str (if (and outgoing (not in-popover?)) " " " ") (when (and (not in-popover?) edited-at) edited-at-text))]
|
||||
(str (if (not in-popover?) " " " ") (when (and (not in-popover?) edited-at) edited-at-text))]
|
||||
last-element (peek elements)]
|
||||
;; Using `nth` here as slightly faster than `first`, roughly 30%
|
||||
;; It's worth considering pure js structures for this code path as
|
||||
|
@ -208,10 +207,10 @@
|
|||
(conj elements message-status))))
|
||||
|
||||
(defn unknown-content-type
|
||||
[{:keys [outgoing content-type content] :as message}]
|
||||
[{:keys [content-type content] :as message}]
|
||||
[react/view (style/message-view message)
|
||||
[react/text
|
||||
{:style {:color (if outgoing colors/white-persist colors/black)}}
|
||||
{:style {:color colors/white-persist}}
|
||||
(if (seq (:text content))
|
||||
(:text content)
|
||||
(str "Unhandled content-type " content-type))]])
|
||||
|
@ -242,8 +241,8 @@
|
|||
|
||||
(def pin-icon-height 15)
|
||||
|
||||
(defn pinned-by-indicator [outgoing display-photo? pinned-by]
|
||||
[react/view {:style (style/pin-indicator outgoing display-photo?)
|
||||
(defn pinned-by-indicator [display-photo? pinned-by]
|
||||
[react/view {:style (style/pin-indicator display-photo?)
|
||||
:accessibility-label :pinned-by}
|
||||
[react/view {:style (style/pinned-by-text-icon-container)}
|
||||
[react/view {:style (style/pin-icon-container)}
|
||||
|
@ -309,33 +308,40 @@
|
|||
|
||||
(defn message-content-wrapper
|
||||
"Author, userpic and delivery wrapper"
|
||||
[{:keys [first-in-group? display-photo? display-username?
|
||||
[{:keys [last-in-group?
|
||||
identicon
|
||||
from outgoing in-popover?]
|
||||
from in-popover? timestamp-str]
|
||||
:as message} content {:keys [modal close-modal]}]
|
||||
[react/view {:style (style/message-wrapper message)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label :chat-item}
|
||||
[react/view {:style (style/message-body message)
|
||||
[react/view {:style (style/message-body)
|
||||
:pointer-events :box-none}
|
||||
(when display-photo?
|
||||
[react/view (style/message-author-userpic outgoing)
|
||||
(when first-in-group?
|
||||
[react/touchable-highlight {:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[photos/member-photo from identicon]])])
|
||||
[react/view {:style (style/message-author-wrapper outgoing display-photo? in-popover?)}
|
||||
(when display-username?
|
||||
[react/touchable-opacity {:style style/message-author-touchable
|
||||
:disabled in-popover?
|
||||
:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[message-author-name from {:modal modal}]])
|
||||
[react/view (style/message-author-userpic)
|
||||
(when last-in-group?
|
||||
[react/touchable-highlight {:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[photos/member-photo from identicon]])]
|
||||
[react/view {:style (style/message-author-wrapper)}
|
||||
(when last-in-group?
|
||||
[react/view {:style {:flex-direction :row :align-items :center}}
|
||||
[react/touchable-opacity {:style style/message-author-touchable
|
||||
:disabled in-popover?
|
||||
:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[message-author-name from {:modal modal}]]
|
||||
[react/text
|
||||
{:style (merge
|
||||
{:padding-left 5
|
||||
:margin-top 2}
|
||||
(style/message-timestamp-text))
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]])
|
||||
;;MESSAGE CONTENT
|
||||
content
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) outgoing false]]]
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
|
||||
; delivery status
|
||||
[react/view (style/delivery-status outgoing)
|
||||
[react/view (style/delivery-status)
|
||||
[message-delivery-status message]]])
|
||||
|
||||
(def image-max-width 260)
|
||||
|
@ -353,13 +359,13 @@
|
|||
(swap! dimensions assoc :loaded true)))))
|
||||
|
||||
(defn message-content-image
|
||||
[{:keys [content outgoing in-popover?] :as message}
|
||||
[{:keys [content in-popover?] :as message}
|
||||
{:keys [on-long-press]}]
|
||||
(let [dimensions (reagent/atom {:width image-max-width :height image-max-height :loaded false})
|
||||
visible (reagent/atom false)
|
||||
uri (:image content)]
|
||||
(fn []
|
||||
(let [style-opts {:outgoing outgoing
|
||||
(let [style-opts {:outgoing false
|
||||
:opacity (if (:loaded @dimensions) 1 0)
|
||||
:width (:width @dimensions)
|
||||
:height (:height @dimensions)}]
|
||||
|
@ -405,9 +411,6 @@
|
|||
[react/view (style/message-view-content)
|
||||
[render-parsed-text message (:parsed-text content)]]]]])
|
||||
|
||||
(def message-height-px 200)
|
||||
(def max-message-height-px 150)
|
||||
|
||||
(defn pin-message [{:keys [chat-id pinned] :as message}]
|
||||
(let [pinned-messages @(re-frame/subscribe [:chats/pinned chat-id])]
|
||||
(if (and (not pinned) (> (count pinned-messages) 2))
|
||||
|
@ -443,62 +446,31 @@
|
|||
:label (i18n/label :t/delete)
|
||||
:id :delete}]))))
|
||||
|
||||
(defn collapsible-text-message [{:keys [mentioned]} _]
|
||||
(defn collapsible-text-message [_ _]
|
||||
(let [collapsed? (reagent/atom false)
|
||||
collapsible? (reagent/atom false)
|
||||
show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [content outgoing current-public-key public? pinned in-popover?] :as message} on-long-press modal]
|
||||
(let [max-height (when-not (or outgoing modal)
|
||||
(if @collapsible?
|
||||
(if @collapsed? message-height-px nil)
|
||||
message-height-px))]
|
||||
[react/touchable-highlight
|
||||
(when-not modal
|
||||
{:on-press (fn [_]
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
: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)))
|
||||
:disabled in-popover?})
|
||||
[react/view (style/message-view-wrapper outgoing)
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message)}
|
||||
[react/view {:style (style/message-view-content)
|
||||
:max-height max-height}
|
||||
(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? pinned])
|
||||
[render-parsed-text-with-message-status message (:parsed-text content)]])
|
||||
(when-not @collapsible? [message-status message])
|
||||
(when (and @collapsible? (not modal))
|
||||
(if @collapsed?
|
||||
(let [color (if pinned colors/pin-background (if mentioned colors/mentioned-background colors/blue-light))]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(swap! collapsed? not)
|
||||
:style {:position :absolute :bottom 0 :left 0 :right 0 :height 72}}
|
||||
[react/linear-gradient {:colors [(str color "00") color]
|
||||
: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)
|
||||
[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)
|
||||
[icons/icon :main-icons/dropdown-up
|
||||
{:color colors/white}]]]))]]]]))))
|
||||
(fn [{:keys [content current-public-key public? pinned in-popover?] :as message} on-long-press modal]
|
||||
[react/touchable-highlight
|
||||
(when-not modal
|
||||
{:on-press (fn [_]
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
: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)))
|
||||
:disabled in-popover?})
|
||||
[react/view style/message-view-wrapper
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message)}
|
||||
[react/view {:style (style/message-view-content)}
|
||||
(let [response-to (:response-to content)]
|
||||
[react/view
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message) current-public-key public? pinned])
|
||||
[render-parsed-text-with-message-status message (:parsed-text content)]])]]]])))
|
||||
|
||||
(defmethod ->message constants/content-type-text
|
||||
[message {:keys [on-long-press modal] :as reaction-picker}]
|
||||
|
@ -511,12 +483,12 @@
|
|||
[community-content message])
|
||||
|
||||
(defmethod ->message constants/content-type-status
|
||||
[{:keys [content content-type pinned] :as message}]
|
||||
[{:keys [content content-type] :as message}]
|
||||
[message-content-wrapper message
|
||||
[react/view style/status-container
|
||||
[react/text {:style (style/status-text)}
|
||||
(reduce
|
||||
(fn [acc e] (render-inline (:text content) false pinned content-type acc e))
|
||||
(fn [acc e] (render-inline (:text content) content-type acc e))
|
||||
[react/text-class {:style (style/status-text)}]
|
||||
(-> content :parsed-text peek :children))]]])
|
||||
|
||||
|
@ -544,11 +516,11 @@
|
|||
:label (i18n/label :t/sharing-copy-to-clipboard)}]
|
||||
(when message-pin-enabled [{:on-press #(pin-message message)
|
||||
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))}]))))})
|
||||
[react/view (style/message-view-wrapper outgoing)
|
||||
[react/view style/message-view-wrapper
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view (style/message-view message)
|
||||
[react/view {:style (style/message-view-content)}
|
||||
[react/view {:style (style/style-message-text outgoing)}
|
||||
[react/view {:style (style/style-message-text)}
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message) outgoing current-public-key public? pinned])
|
||||
[react/text {:style (style/emoji-message message)}
|
||||
|
@ -624,7 +596,7 @@
|
|||
[])))
|
||||
:on-press (fn []
|
||||
(reset! show-timestamp? true))})
|
||||
[react/view (style/message-view-wrapper (:outgoing message))
|
||||
[react/view style/message-view-wrapper
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message) :accessibility-label :audio-message}
|
||||
[react/view {:style (style/message-view-content)}
|
||||
|
@ -659,8 +631,8 @@
|
|||
constants/contact-request-message-state-declined [contact-request-status-declined])])
|
||||
|
||||
(defmethod ->message constants/content-type-contact-request
|
||||
[{:keys [outgoing] :as message} _]
|
||||
[react/view {:style (style/content-type-contact-request outgoing)}
|
||||
[message _]
|
||||
[react/view {:style (style/content-type-contact-request)}
|
||||
[react/image {:source (resources/get-image :hand-wave)
|
||||
:style {:width 112
|
||||
:height 97}}]
|
||||
|
@ -678,7 +650,7 @@
|
|||
[message-content-wrapper message
|
||||
[unknown-content-type message]])
|
||||
|
||||
(defn chat-message [{:keys [outgoing display-photo? pinned pinned-by] :as message} space-keeper]
|
||||
(defn chat-message [{:keys [display-photo? pinned pinned-by] :as message} space-keeper]
|
||||
[:<>
|
||||
[reactions/with-reaction-picker
|
||||
{:message message
|
||||
|
@ -698,5 +670,5 @@
|
|||
:emoji-reaction-id emoji-reaction-id}]))
|
||||
:render ->message}]
|
||||
(when pinned
|
||||
[react/view {:style (style/pin-indicator-container outgoing)}
|
||||
[pinned-by-indicator outgoing display-photo? pinned-by]])])
|
||||
[react/view {:style (style/pin-indicator-container)}
|
||||
[pinned-by-indicator display-photo? pinned-by]])])
|
||||
|
|
|
@ -0,0 +1,702 @@
|
|||
(ns status-im.ui.screens.chat.message.message-old
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.chat.message.audio-old :as message.audio]
|
||||
[status-im.chat.models.reactions :as models.reactions]
|
||||
[status-im.ui.screens.chat.message.command :as message.command]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.chat.sheets :as sheets]
|
||||
[status-im.ui.screens.chat.message.gap :as message.gap]
|
||||
[status-im.ui.screens.chat.styles.message.message-old :as style]
|
||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||
[status-im.utils.security :as security]
|
||||
[status-im.ui.screens.chat.message.reactions :as reactions]
|
||||
[status-im.ui.screens.chat.image.preview.views :as preview]
|
||||
[quo.core :as quo]
|
||||
[status-im.utils.config :as config]
|
||||
[reagent.core :as reagent]
|
||||
[status-im.ui.screens.chat.components.reply :as components.reply]
|
||||
[status-im.ui.screens.chat.message.link-preview :as link-preview]
|
||||
[status-im.ui.screens.communities.icon :as communities.icon]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.chat.models.images :as images]
|
||||
[status-im.chat.models.pin-message :as models.pin-message]
|
||||
[status-im.ui.components.fast-image :as fast-image])
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||
|
||||
(defn message-timestamp-anim
|
||||
[anim-opacity show-timestamp?]
|
||||
(animation/start
|
||||
(animation/anim-sequence
|
||||
[(animation/timing
|
||||
anim-opacity
|
||||
{:toValue 1
|
||||
:duration 100
|
||||
:easing (.-ease ^js animation/easing)
|
||||
:useNativeDriver true})
|
||||
(animation/timing
|
||||
anim-opacity
|
||||
{:toValue 0
|
||||
:delay 2000
|
||||
:duration 100
|
||||
:easing (.-ease ^js animation/easing)
|
||||
:useNativeDriver true})]) #(reset! show-timestamp? false)))
|
||||
|
||||
(defview mention-element [from]
|
||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||
contact-name))
|
||||
|
||||
(def edited-at-text (str " ⌫ " (i18n/label :t/edited)))
|
||||
|
||||
(defn message-status [{:keys [outgoing content outgoing-status pinned edited-at in-popover?]}]
|
||||
(when-not in-popover? ;; We keep track if showing this message in a list in pin-limit-popover
|
||||
[react/view
|
||||
{:align-self :flex-end
|
||||
:position :absolute
|
||||
:bottom 9 ; 6 Bubble bottom, 3 message baseline
|
||||
(if (:rtl? content) :left :right) 0
|
||||
:flex-direction :row
|
||||
:align-items :flex-end}
|
||||
(when outgoing
|
||||
[icons/icon (case outgoing-status
|
||||
:sending :tiny-icons/tiny-pending
|
||||
:sent :tiny-icons/tiny-sent
|
||||
:not-sent :tiny-icons/tiny-warning
|
||||
:delivered :tiny-icons/tiny-delivered
|
||||
:tiny-icons/tiny-pending)
|
||||
{:width 16
|
||||
:height 12
|
||||
:color (if pinned colors/gray colors/white)
|
||||
:accessibility-label (name outgoing-status)}])
|
||||
(when edited-at [react/text {:style (style/message-status-text (and outgoing (not pinned)))} edited-at-text])]))
|
||||
|
||||
(defn message-timestamp
|
||||
[{:keys [timestamp-str in-popover?] :as message} show-timestamp?]
|
||||
(when-not in-popover? ;; We keep track if showing this message in a list in pin-limit-popover
|
||||
(let [anim-opacity (animation/create-value 0)]
|
||||
[react/animated-view {:style (style/message-timestamp-wrapper message) :opacity anim-opacity}
|
||||
(when @show-timestamp? (message-timestamp-anim anim-opacity show-timestamp?))
|
||||
[react/text
|
||||
{:style (style/message-timestamp-text)
|
||||
:accessibility-label :message-timestamp}
|
||||
timestamp-str]])))
|
||||
|
||||
(defview quoted-message
|
||||
[_ {:keys [from parsed-text image]} outgoing current-public-key public? pinned]
|
||||
(letsubs [contact-name [:contacts/contact-name-by-identity from]]
|
||||
[react/view {:style (style/quoted-message-container (and outgoing (not pinned)))}
|
||||
[react/view {:style style/quoted-message-author-container}
|
||||
[chat.utils/format-reply-author
|
||||
from
|
||||
contact-name
|
||||
current-public-key
|
||||
(partial style/quoted-message-author (and outgoing (not pinned)))
|
||||
(and outgoing (not pinned))]]
|
||||
(if (and image
|
||||
;; Disabling images for public-chats
|
||||
(not public?))
|
||||
[fast-image/fast-image {:style {:width 56
|
||||
:height 56
|
||||
:background-color :black
|
||||
:border-radius 4}
|
||||
:source {:uri image}}]
|
||||
[react/text {:style (style/quoted-message-text (and outgoing (not pinned)))
|
||||
:number-of-lines 5}
|
||||
(components.reply/get-quoted-text-with-mentions parsed-text)])]))
|
||||
|
||||
(defn render-inline [message-text outgoing pinned content-type acc {:keys [type literal destination]}]
|
||||
(case type
|
||||
""
|
||||
(conj acc literal)
|
||||
|
||||
"code"
|
||||
(conj acc [quo/text {:max-font-size-multiplier react/max-font-size-multiplier
|
||||
:style (style/inline-code-style)
|
||||
:monospace true}
|
||||
literal])
|
||||
|
||||
"emph"
|
||||
(conj acc [react/text-class (style/emph-style (and outgoing (not pinned))) literal])
|
||||
|
||||
"strong"
|
||||
(conj acc [react/text-class (style/strong-style (and outgoing (not pinned))) literal])
|
||||
|
||||
"strong-emph"
|
||||
(conj acc [quo/text (style/strong-emph-style (and outgoing (not pinned))) literal])
|
||||
|
||||
"del"
|
||||
(conj acc [react/text-class (style/strikethrough-style (and outgoing (not pinned))) literal])
|
||||
|
||||
"link"
|
||||
(conj acc
|
||||
[react/text-class
|
||||
{:style
|
||||
{:color (if (and outgoing (not pinned)) colors/white-persist colors/blue)
|
||||
:text-decoration-line :underline}
|
||||
:on-press
|
||||
#(when (and (security/safe-link? destination)
|
||||
(security/safe-link-text? message-text))
|
||||
(re-frame/dispatch
|
||||
[:browser.ui/message-link-pressed destination]))}
|
||||
destination])
|
||||
|
||||
"mention"
|
||||
(conj acc [react/text-class
|
||||
{:style {:color (cond
|
||||
(= content-type constants/content-type-system-text) colors/black
|
||||
(and outgoing (not pinned)) colors/mention-outgoing
|
||||
:else colors/mention-incoming)}
|
||||
:on-press (when-not (= content-type constants/content-type-system-text)
|
||||
#(re-frame/dispatch [:chat.ui/show-profile literal]))}
|
||||
[mention-element literal]])
|
||||
"status-tag"
|
||||
(conj acc [react/text-class
|
||||
{:style {:color (if (and outgoing (not pinned)) colors/white-persist colors/blue)
|
||||
:text-decoration-line :underline}
|
||||
:on-press
|
||||
#(re-frame/dispatch
|
||||
[:chat.ui/start-public-chat literal])}
|
||||
"#"
|
||||
literal])
|
||||
|
||||
(conj acc literal)))
|
||||
|
||||
(defn render-block [{:keys [content outgoing content-type pinned in-popover?]} acc
|
||||
{:keys [type ^js literal children]}]
|
||||
(case type
|
||||
|
||||
"paragraph"
|
||||
(conj acc (reduce
|
||||
(fn [acc e] (render-inline (:text content) outgoing pinned content-type acc e))
|
||||
[react/text-class (style/text-style (and outgoing (not pinned)) content-type in-popover?)]
|
||||
children))
|
||||
|
||||
"blockquote"
|
||||
(conj acc [react/view (style/blockquote-style (and outgoing (not pinned)))
|
||||
[react/text-class (style/blockquote-text-style (and outgoing (not pinned)))
|
||||
(.substring literal 0 (.-length literal))]])
|
||||
|
||||
"codeblock"
|
||||
(conj acc [react/view {:style style/codeblock-style}
|
||||
[quo/text {:max-font-size-multiplier react/max-font-size-multiplier
|
||||
:style style/codeblock-text-style
|
||||
:monospace true}
|
||||
(.substring literal 0 (dec (.-length literal)))]])
|
||||
|
||||
acc))
|
||||
|
||||
(defn render-parsed-text [message tree]
|
||||
(reduce (fn [acc e] (render-block message acc e)) [:<>] tree))
|
||||
|
||||
(defn render-parsed-text-with-message-status [{:keys [outgoing edited-at in-popover?] :as message} tree]
|
||||
(let [elements (render-parsed-text message tree)
|
||||
message-status [react/text {:style (style/message-status-placeholder)}
|
||||
(str (if (and outgoing (not in-popover?)) " " " ") (when (and (not in-popover?) edited-at) edited-at-text))]
|
||||
last-element (peek elements)]
|
||||
;; Using `nth` here as slightly faster than `first`, roughly 30%
|
||||
;; It's worth considering pure js structures for this code path as
|
||||
;; it's perfomance critical
|
||||
(if (= react/text-class (nth last-element 0))
|
||||
;; Append message status to last text
|
||||
(conj (pop elements) (conj last-element message-status))
|
||||
;; Append message status to new block
|
||||
(conj elements message-status))))
|
||||
|
||||
(defn unknown-content-type
|
||||
[{:keys [outgoing content-type content] :as message}]
|
||||
[react/view (style/message-view message)
|
||||
[react/text
|
||||
{:style {:color (if outgoing colors/white-persist colors/black)}}
|
||||
(if (seq (:text content))
|
||||
(:text content)
|
||||
(str "Unhandled content-type " content-type))]])
|
||||
|
||||
(defn message-not-sent-text
|
||||
[chat-id message-id]
|
||||
[react/touchable-highlight
|
||||
{:on-press
|
||||
(fn []
|
||||
(re-frame/dispatch
|
||||
[:bottom-sheet/show-sheet
|
||||
{:content (sheets/options chat-id message-id)
|
||||
:content-height 200}])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view style/not-sent-view
|
||||
[react/text {:style style/not-sent-text}
|
||||
(i18n/label :t/status-not-sent-tap)]
|
||||
[react/view style/not-sent-icon
|
||||
[icons/icon :main-icons/warning {:color colors/red}]]]])
|
||||
|
||||
(defn pin-author-name [pinned-by]
|
||||
(let [user-contact @(re-frame/subscribe [:multiaccount/contact])
|
||||
contact-names @(re-frame/subscribe [:contacts/contact-two-names-by-identity pinned-by])]
|
||||
;; We append empty spaces to the name as a workaround to make one-line and multi-line label components show correctly
|
||||
(str " " (if (= pinned-by (user-contact :public-key)) (i18n/label :t/You) (first contact-names)))))
|
||||
|
||||
(def pin-icon-width 9)
|
||||
|
||||
(def pin-icon-height 15)
|
||||
|
||||
(defn pinned-by-indicator [outgoing display-photo? pinned-by]
|
||||
[react/view {:style (style/pin-indicator outgoing display-photo?)
|
||||
:accessibility-label :pinned-by}
|
||||
[react/view {:style (style/pinned-by-text-icon-container)}
|
||||
[react/view {:style (style/pin-icon-container)}
|
||||
[icons/icon :main-icons/pin {:color colors/gray
|
||||
:height pin-icon-height
|
||||
:width pin-icon-width
|
||||
:background-color :red}]]
|
||||
[quo/text {:weight :regular
|
||||
:size :small
|
||||
:color :main
|
||||
:style (style/pinned-by-text)}
|
||||
(i18n/label :t/pinned-by)]]
|
||||
[quo/text {:weight :medium
|
||||
:size :small
|
||||
:color :main
|
||||
:style (style/pin-author-text)}
|
||||
(pin-author-name pinned-by)]])
|
||||
|
||||
(defn message-delivery-status
|
||||
[{:keys [chat-id message-id outgoing-status message-type]}]
|
||||
(when (and (not= constants/message-type-private-group-system-message message-type)
|
||||
(= outgoing-status :not-sent))
|
||||
[message-not-sent-text chat-id message-id]))
|
||||
|
||||
(defview message-author-name [from opts]
|
||||
(letsubs [contact-with-names [:contacts/contact-by-identity from]]
|
||||
(chat.utils/format-author-old contact-with-names opts)))
|
||||
|
||||
(defview message-my-name [opts]
|
||||
(letsubs [contact-with-names [:multiaccount/contact]]
|
||||
(chat.utils/format-author-old contact-with-names opts)))
|
||||
|
||||
(defview community-content [{:keys [community-id] :as message}]
|
||||
(letsubs [{:keys [name description verified] :as community} [:communities/community community-id]
|
||||
communities-enabled? [:communities/enabled?]]
|
||||
(when (and communities-enabled? community)
|
||||
[react/view {:style (assoc (style/message-wrapper message)
|
||||
:margin-vertical 10
|
||||
:margin-left 8
|
||||
:width 271)}
|
||||
(when verified
|
||||
[react/view (style/community-verified)
|
||||
[react/text {:style {:font-size 13
|
||||
:color colors/blue}} (i18n/label :t/communities-verified)]])
|
||||
[react/view (style/community-message verified)
|
||||
[react/view {:width 62
|
||||
:padding-left 14}
|
||||
(if (= community-id constants/status-community-id)
|
||||
[react/image {:source (resources/get-image :status-logo)
|
||||
:style {:width 40
|
||||
:height 40}}]
|
||||
[communities.icon/community-icon community])]
|
||||
[react/view {:padding-right 14 :flex 1}
|
||||
[react/text {:style {:font-weight "700" :font-size 17}}
|
||||
name]
|
||||
[react/text description]]]
|
||||
[react/view (style/community-view-button)
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to
|
||||
:community
|
||||
{:community-id (:id community)}])}
|
||||
[react/text {:style {:text-align :center
|
||||
:color colors/blue}} (i18n/label :t/view)]]]])))
|
||||
|
||||
(defn message-content-wrapper
|
||||
"Author, userpic and delivery wrapper"
|
||||
[{:keys [first-in-group? display-photo? display-username?
|
||||
identicon
|
||||
from outgoing in-popover?]
|
||||
:as message} content {:keys [modal close-modal]}]
|
||||
[react/view {:style (style/message-wrapper message)
|
||||
:pointer-events :box-none
|
||||
:accessibility-label :chat-item}
|
||||
[react/view {:style (style/message-body message)
|
||||
:pointer-events :box-none}
|
||||
(when display-photo?
|
||||
[react/view (style/message-author-userpic outgoing)
|
||||
(when first-in-group?
|
||||
[react/touchable-highlight {:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[photos/member-photo from identicon]])])
|
||||
[react/view {:style (style/message-author-wrapper outgoing display-photo? in-popover?)}
|
||||
(when display-username?
|
||||
[react/touchable-opacity {:style style/message-author-touchable
|
||||
:disabled in-popover?
|
||||
:on-press #(do (when modal (close-modal))
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))}
|
||||
[message-author-name from {:modal modal}]])
|
||||
;;MESSAGE CONTENT
|
||||
content
|
||||
[link-preview/link-preview-wrapper (:links (:content message)) outgoing false]]]
|
||||
; delivery status
|
||||
[react/view (style/delivery-status outgoing)
|
||||
[message-delivery-status message]]])
|
||||
|
||||
(def image-max-width 260)
|
||||
(def image-max-height 192)
|
||||
|
||||
(defn image-set-size [dimensions]
|
||||
(fn [evt]
|
||||
(let [width (.-width (.-nativeEvent evt))
|
||||
height (.-height (.-nativeEvent evt))]
|
||||
(if (< width height)
|
||||
;; if width less than the height we reduce width proportionally to height
|
||||
(let [k (/ height image-max-height)]
|
||||
(when (not= (/ width k) (first @dimensions))
|
||||
(reset! dimensions {:width (/ width k) :height image-max-height :loaded true})))
|
||||
(swap! dimensions assoc :loaded true)))))
|
||||
|
||||
(defn message-content-image
|
||||
[{:keys [content outgoing in-popover?] :as message}
|
||||
{:keys [on-long-press]}]
|
||||
(let [dimensions (reagent/atom {:width image-max-width :height image-max-height :loaded false})
|
||||
visible (reagent/atom false)
|
||||
uri (:image content)]
|
||||
(fn []
|
||||
(let [style-opts {:outgoing outgoing
|
||||
:opacity (if (:loaded @dimensions) 1 0)
|
||||
:width (:width @dimensions)
|
||||
:height (:height @dimensions)}]
|
||||
[:<>
|
||||
[preview/preview-image {:message message
|
||||
:visible @visible
|
||||
:on-close #(do (reset! visible false)
|
||||
(reagent/flush))}]
|
||||
[react/touchable-highlight {:on-press (fn []
|
||||
(reset! visible true)
|
||||
(react/dismiss-keyboard!))
|
||||
:on-long-press on-long-press
|
||||
:disabled in-popover?}
|
||||
[react/view {:style (style/image-message style-opts)
|
||||
:accessibility-label :image-message}
|
||||
(when (or (:error @dimensions) (not (:loaded @dimensions)))
|
||||
[react/view
|
||||
(merge (dissoc style-opts :opacity)
|
||||
{:flex 1 :align-items :center :justify-content :center :position :absolute})
|
||||
(if (:error @dimensions)
|
||||
[icons/icon :main-icons/cancel]
|
||||
[react/activity-indicator {:animating true}])])
|
||||
[fast-image/fast-image {:style (dissoc style-opts :outgoing)
|
||||
:on-load (image-set-size dimensions)
|
||||
:on-error #(swap! dimensions assoc :error true)
|
||||
:source {:uri uri}}]
|
||||
[react/view {:style (style/image-message-border style-opts)}]]]]))))
|
||||
|
||||
(defmulti ->message :content-type)
|
||||
|
||||
(defmethod ->message constants/content-type-command
|
||||
[message]
|
||||
[message.command/command-content message-content-wrapper message])
|
||||
|
||||
(defmethod ->message constants/content-type-gap
|
||||
[message]
|
||||
[message.gap/gap message])
|
||||
|
||||
(defmethod ->message constants/content-type-system-text [{:keys [content] :as message}]
|
||||
[react/view {:accessibility-label :chat-item}
|
||||
[react/view (style/system-message-body message)
|
||||
[react/view (style/message-view message)
|
||||
[react/view (style/message-view-content)
|
||||
[render-parsed-text message (:parsed-text content)]]]]])
|
||||
|
||||
(def message-height-px 200)
|
||||
(def max-message-height-px 150)
|
||||
|
||||
(defn pin-message [{:keys [chat-id pinned] :as message}]
|
||||
(let [pinned-messages @(re-frame/subscribe [:chats/pinned chat-id])]
|
||||
(if (and (not pinned) (> (count pinned-messages) 2))
|
||||
(do
|
||||
(js/setTimeout (fn [] (re-frame/dispatch [:dismiss-keyboard])) 500)
|
||||
(re-frame/dispatch [:show-popover {:view :pin-limit
|
||||
:message message
|
||||
:prevent-closing? true}]))
|
||||
(re-frame/dispatch [::models.pin-message/send-pin-message (assoc message :pinned (not pinned))]))))
|
||||
|
||||
(defn on-long-press-fn [on-long-press {:keys [pinned message-pin-enabled outgoing edit-enabled show-input?] :as message} content]
|
||||
(on-long-press
|
||||
(concat
|
||||
(when (and outgoing edit-enabled)
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/edit-message message])
|
||||
:label (i18n/label :t/edit)
|
||||
:id :edit}])
|
||||
(when show-input?
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||
:label (i18n/label :t/message-reply)
|
||||
:id :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)
|
||||
:id :copy}]
|
||||
(when message-pin-enabled
|
||||
[{:on-press #(pin-message message)
|
||||
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))
|
||||
:id (if pinned :unpin :pin)}])
|
||||
(when (and outgoing config/delete-message-enabled?)
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||
:label (i18n/label :t/delete)
|
||||
:id :delete}]))))
|
||||
|
||||
(defn collapsible-text-message [{:keys [mentioned]} _]
|
||||
(let [collapsed? (reagent/atom false)
|
||||
collapsible? (reagent/atom false)
|
||||
show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [content outgoing current-public-key public? pinned in-popover?] :as message} on-long-press modal]
|
||||
(let [max-height (when-not (or outgoing modal)
|
||||
(if @collapsible?
|
||||
(if @collapsed? message-height-px nil)
|
||||
message-height-px))]
|
||||
[react/touchable-highlight
|
||||
(when-not modal
|
||||
{:on-press (fn [_]
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
: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)))
|
||||
:disabled in-popover?})
|
||||
[react/view (style/message-view-wrapper outgoing)
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message)}
|
||||
[react/view {:style (style/message-view-content)
|
||||
:max-height max-height}
|
||||
(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? pinned])
|
||||
[render-parsed-text-with-message-status message (:parsed-text content)]])
|
||||
(when-not @collapsible? [message-status message])
|
||||
(when (and @collapsible? (not modal))
|
||||
(if @collapsed?
|
||||
(let [color (if pinned colors/pin-background (if mentioned colors/mentioned-background colors/blue-light))]
|
||||
[react/touchable-highlight
|
||||
{:on-press #(swap! collapsed? not)
|
||||
:style {:position :absolute :bottom 0 :left 0 :right 0 :height 72}}
|
||||
[react/linear-gradient {:colors [(str color "00") color]
|
||||
: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)
|
||||
[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)
|
||||
[icons/icon :main-icons/dropdown-up
|
||||
{:color colors/white}]]]))]]]]))))
|
||||
|
||||
(defmethod ->message constants/content-type-text
|
||||
[message {:keys [on-long-press modal] :as reaction-picker}]
|
||||
[message-content-wrapper message
|
||||
[collapsible-text-message message on-long-press modal]
|
||||
reaction-picker])
|
||||
|
||||
(defmethod ->message constants/content-type-community
|
||||
[message]
|
||||
[community-content message])
|
||||
|
||||
(defmethod ->message constants/content-type-status
|
||||
[{:keys [content content-type pinned] :as message}]
|
||||
[message-content-wrapper message
|
||||
[react/view style/status-container
|
||||
[react/text {:style (style/status-text)}
|
||||
(reduce
|
||||
(fn [acc e] (render-inline (:text content) false pinned content-type acc e))
|
||||
[react/text-class {:style (style/status-text)}]
|
||||
(-> content :parsed-text peek :children))]]])
|
||||
|
||||
(defmethod ->message constants/content-type-emoji []
|
||||
(let [show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [content current-public-key outgoing public? pinned in-popover? message-pin-enabled] :as message}
|
||||
{:keys [on-long-press modal]
|
||||
:as reaction-picker}]
|
||||
(let [response-to (:response-to content)]
|
||||
[message-content-wrapper message
|
||||
[react/touchable-highlight (when-not modal
|
||||
{:disabled in-popover?
|
||||
:on-press (fn []
|
||||
(react/dismiss-keyboard!)
|
||||
(reset! show-timestamp? true))
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
(on-long-press
|
||||
(concat
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||
:id :reply
|
||||
:label (i18n/label :t/message-reply)}
|
||||
{:on-press #(react/copy-to-clipboard (get content :text))
|
||||
:id :copy
|
||||
:label (i18n/label :t/sharing-copy-to-clipboard)}]
|
||||
(when message-pin-enabled [{:on-press #(pin-message message)
|
||||
:label (if pinned (i18n/label :t/unpin) (i18n/label :t/pin))}]))))})
|
||||
[react/view (style/message-view-wrapper outgoing)
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view (style/message-view message)
|
||||
[react/view {:style (style/message-view-content)}
|
||||
[react/view {:style (style/style-message-text outgoing)}
|
||||
(when (and (seq response-to) (:quoted-message message))
|
||||
[quoted-message response-to (:quoted-message message) outgoing current-public-key public? pinned])
|
||||
[react/text {:style (style/emoji-message message)}
|
||||
(:text content)]]
|
||||
[message-status message]]]]]
|
||||
reaction-picker]))))
|
||||
|
||||
(defmethod ->message constants/content-type-sticker
|
||||
[{:keys [content from outgoing in-popover?]
|
||||
:as message}
|
||||
{:keys [on-long-press modal]
|
||||
:as reaction-picker}]
|
||||
(let [pack (get-in content [:sticker :pack])]
|
||||
[message-content-wrapper message
|
||||
[react/touchable-highlight (when-not modal
|
||||
{:disabled in-popover?
|
||||
:accessibility-label :sticker-message
|
||||
:on-press (fn [_]
|
||||
(when pack
|
||||
(re-frame/dispatch [:stickers/open-sticker-pack (str pack)]))
|
||||
(react/dismiss-keyboard!))
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
(on-long-press
|
||||
(when-not outgoing
|
||||
[{:on-press #(when pack
|
||||
(re-frame/dispatch [:chat.ui/show-profile from]))
|
||||
:label (i18n/label :t/view-details)}])))})
|
||||
[fast-image/fast-image {:style {:margin 10 :width 140 :height 140}
|
||||
:source {:uri (str (-> content :sticker :url) "&download=true")}}]]
|
||||
reaction-picker]))
|
||||
|
||||
(defmethod ->message constants/content-type-image
|
||||
[{:keys [content in-popover? outgoing] :as message}
|
||||
{:keys [on-long-press modal]
|
||||
:as reaction-picker}]
|
||||
[message-content-wrapper message
|
||||
[message-content-image message
|
||||
{:modal modal
|
||||
:disabled in-popover?
|
||||
:delay-long-press 100
|
||||
:on-long-press (fn []
|
||||
(on-long-press
|
||||
(concat [{:on-press #(re-frame/dispatch [:chat.ui/reply-to-message message])
|
||||
:id :reply
|
||||
:label (i18n/label :t/message-reply)}
|
||||
{:on-press #(re-frame/dispatch [:chat.ui/save-image-to-gallery (:image content)])
|
||||
:id :save
|
||||
:label (i18n/label :t/save)}
|
||||
{:on-press #(images/download-image-http
|
||||
(get-in message [:content :image]) preview/share)
|
||||
:id :share
|
||||
:label (i18n/label :t/share)}]
|
||||
(when (and outgoing config/delete-message-enabled?)
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||
:label (i18n/label :t/delete)
|
||||
:id :delete}]))))}]
|
||||
reaction-picker])
|
||||
|
||||
(defmethod ->message constants/content-type-audio []
|
||||
(let [show-timestamp? (reagent/atom false)]
|
||||
(fn [{:keys [outgoing] :as message}
|
||||
{:keys [on-long-press modal]
|
||||
:as reaction-picker}]
|
||||
[message-content-wrapper message
|
||||
[react/touchable-highlight
|
||||
(when-not modal
|
||||
{:on-long-press
|
||||
(fn [] (on-long-press (if (and outgoing config/delete-message-enabled?)
|
||||
[{:on-press #(re-frame/dispatch [:chat.ui/soft-delete-message message])
|
||||
:label (i18n/label :t/delete)
|
||||
:id :delete}]
|
||||
[])))
|
||||
:on-press (fn []
|
||||
(reset! show-timestamp? true))})
|
||||
[react/view (style/message-view-wrapper (:outgoing message))
|
||||
[message-timestamp message show-timestamp?]
|
||||
[react/view {:style (style/message-view message) :accessibility-label :audio-message}
|
||||
[react/view {:style (style/message-view-content)}
|
||||
[message.audio/message-content message] [message-status message]]]]]
|
||||
reaction-picker])))
|
||||
|
||||
(defn contact-request-status-pending []
|
||||
[react/view {:style {:flex-direction :row}}
|
||||
[quo/text {:style {:margin-right 5.27}
|
||||
:weight :medium
|
||||
:color :secondary}
|
||||
(i18n/label :t/contact-request-pending)]
|
||||
[react/activity-indicator {:animating true
|
||||
:size :small
|
||||
:color colors/gray}]])
|
||||
|
||||
(defn contact-request-status-accepted []
|
||||
[quo/text {:style {:color colors/green}
|
||||
:weight :medium}
|
||||
(i18n/label :t/contact-request-accepted)])
|
||||
|
||||
(defn contact-request-status-declined []
|
||||
[quo/text {:style {:color colors/red}
|
||||
:weight :medium}
|
||||
(i18n/label :t/contact-request-declined)])
|
||||
|
||||
(defn contact-request-status-label [state]
|
||||
[react/view {:style (style/contact-request-status-label state)}
|
||||
(case state
|
||||
constants/contact-request-message-state-pending [contact-request-status-pending]
|
||||
constants/contact-request-message-state-accepted [contact-request-status-accepted]
|
||||
constants/contact-request-message-state-declined [contact-request-status-declined])])
|
||||
|
||||
(defmethod ->message constants/content-type-contact-request
|
||||
[{:keys [outgoing] :as message} _]
|
||||
[react/view {:style (style/content-type-contact-request outgoing)}
|
||||
[react/image {:source (resources/get-image :hand-wave)
|
||||
:style {:width 112
|
||||
:height 97}}]
|
||||
[quo/text {:style {:margin-top 6}
|
||||
:weight :bold
|
||||
:size :large}
|
||||
(i18n/label :t/contact-request)]
|
||||
[react/view {:style {:padding-horizontal 16}}
|
||||
[quo/text {:style {:margin-top 2
|
||||
:margin-bottom 14}}
|
||||
(get-in message [:content :text])]]
|
||||
[contact-request-status-label (:contact-request-state message)]])
|
||||
|
||||
(defmethod ->message :default [message]
|
||||
[message-content-wrapper message
|
||||
[unknown-content-type message]])
|
||||
|
||||
(defn chat-message [{:keys [outgoing display-photo? pinned pinned-by] :as message} space-keeper]
|
||||
[:<>
|
||||
[reactions/with-reaction-picker
|
||||
{:message message
|
||||
:reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message) (:chat-id message)])
|
||||
:picker-on-open (fn []
|
||||
(space-keeper true))
|
||||
:picker-on-close (fn []
|
||||
(space-keeper false))
|
||||
:send-emoji (fn [{:keys [emoji-id]}]
|
||||
(re-frame/dispatch [::models.reactions/send-emoji-reaction
|
||||
{:message-id (:message-id message)
|
||||
:emoji-id emoji-id}]))
|
||||
:retract-emoji (fn [{:keys [emoji-id emoji-reaction-id]}]
|
||||
(re-frame/dispatch [::models.reactions/send-emoji-reaction-retraction
|
||||
{:message-id (:message-id message)
|
||||
:emoji-id emoji-id
|
||||
:emoji-reaction-id emoji-reaction-id}]))
|
||||
:render ->message}]
|
||||
(when pinned
|
||||
[react/view {:style (style/pin-indicator-container outgoing)}
|
||||
[pinned-by-indicator outgoing display-photo? pinned-by]])])
|
|
@ -8,7 +8,7 @@
|
|||
[status-im.chat.models.pin-message :as models.pin-message]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.utils.handlers :refer [<sub]]
|
||||
[status-im.ui.screens.chat.message.message :as message]))
|
||||
[status-im.ui.screens.chat.message.message-old :as message]))
|
||||
|
||||
(def selected-unpin (reagent/atom nil))
|
||||
|
||||
|
|
|
@ -81,8 +81,8 @@
|
|||
{:justify-content :flex-end}
|
||||
{:justify-content :flex-start})
|
||||
(if (or display-photo? timeline)
|
||||
{:padding-left (+ 16 photos/default-size (when timeline 8))}
|
||||
{:padding-left 8})))
|
||||
{:padding-left (+ 30 photos/default-size (when timeline 8))}
|
||||
{:padding-left 30})))
|
||||
|
||||
(defn reaction-button [active]
|
||||
(merge {:width 40
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.chat.views :as chat]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.ui.screens.chat.message.message-old :as message]
|
||||
[status-im.utils.datetime :as time]))
|
||||
|
||||
(defn pins-topbar [chat]
|
||||
|
|
|
@ -17,22 +17,16 @@
|
|||
:align-items :stretch
|
||||
:flex-grow 1})
|
||||
|
||||
(defn slider [outgoing]
|
||||
(defn slider []
|
||||
{:style (merge {:margin-left 12
|
||||
:height 34}
|
||||
(when platform/ios? {:margin-bottom 4}))
|
||||
:thumb-tint-color (if outgoing
|
||||
colors/white
|
||||
colors/blue)
|
||||
:minimum-track-tint-color (if outgoing
|
||||
colors/white
|
||||
colors/blue)
|
||||
:maximum-track-tint-color (if outgoing
|
||||
colors/white-transparent
|
||||
colors/gray-transparent-40)})
|
||||
:thumb-tint-color colors/white
|
||||
:minimum-track-tint-color colors/white
|
||||
:maximum-track-tint-color colors/white-transparent})
|
||||
|
||||
(defn play-pause-container [outgoing? loading?]
|
||||
{:background-color (if outgoing? colors/white-persist colors/blue)
|
||||
(defn play-pause-container [loading?]
|
||||
{:background-color colors/white-persist
|
||||
:width 28
|
||||
:height 28
|
||||
:padding (if loading? 4 2)
|
||||
|
@ -42,6 +36,6 @@
|
|||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn timestamp [outgoing]
|
||||
(merge (message.style/audio-message-timestamp-text outgoing)
|
||||
(defn timestamp []
|
||||
(merge (message.style/audio-message-timestamp-text)
|
||||
{:margin-left 40}))
|
|
@ -0,0 +1,47 @@
|
|||
(ns status-im.ui.screens.chat.styles.message.audio-old
|
||||
(:require [quo.design-system.colors :as colors]
|
||||
[status-im.ui.screens.chat.styles.message.message-old :as message.style]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(defn container [window-width]
|
||||
{:width (* window-width 0.60)
|
||||
:flex-direction :column
|
||||
:justify-content :space-between})
|
||||
|
||||
(def play-pause-slider-container
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def slider-container
|
||||
{:flex-direction :column
|
||||
:align-items :stretch
|
||||
:flex-grow 1})
|
||||
|
||||
(defn slider [outgoing]
|
||||
{:style (merge {:margin-left 12
|
||||
:height 34}
|
||||
(when platform/ios? {:margin-bottom 4}))
|
||||
:thumb-tint-color (if outgoing
|
||||
colors/white
|
||||
colors/blue)
|
||||
:minimum-track-tint-color (if outgoing
|
||||
colors/white
|
||||
colors/blue)
|
||||
:maximum-track-tint-color (if outgoing
|
||||
colors/white-transparent
|
||||
colors/gray-transparent-40)})
|
||||
|
||||
(defn play-pause-container [outgoing? loading?]
|
||||
{:background-color (if outgoing? colors/white-persist colors/blue)
|
||||
:width 28
|
||||
:height 28
|
||||
:padding (if loading? 4 2)
|
||||
:border-radius 15})
|
||||
|
||||
(def times-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between})
|
||||
|
||||
(defn timestamp [outgoing]
|
||||
(merge (message.style/audio-message-timestamp-text outgoing)
|
||||
{:margin-left 40}))
|
|
@ -1,11 +1,22 @@
|
|||
(ns status-im.ui.screens.chat.styles.message.datemark
|
||||
(:require [quo.design-system.colors :as colors]))
|
||||
(:require [quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(def datemark-mobile
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:margin-top 16
|
||||
:height 22})
|
||||
:justify-content :center
|
||||
:margin-vertical 16
|
||||
:padding-left 65})
|
||||
|
||||
(defn divider []
|
||||
{:flex 1
|
||||
:width "100%"
|
||||
:height 1
|
||||
:padding-left 53
|
||||
:background-color (quo2.colors/theme-colors quo2.colors/divider-light quo2.colors/divider-dark)
|
||||
:margin-top 5})
|
||||
|
||||
(defn datemark-text []
|
||||
{:color colors/gray})
|
||||
{:color quo2.colors/neutral-50
|
||||
:font-size 14
|
||||
:line-height 16
|
||||
:font-weight "500"})
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
(ns status-im.ui.screens.chat.styles.message.datemark-old
|
||||
(:require [quo.design-system.colors :as colors]))
|
||||
|
||||
(def datemark-mobile
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:margin-top 16
|
||||
:height 22})
|
||||
|
||||
(defn datemark-text []
|
||||
{:color colors/gray})
|
|
@ -3,11 +3,11 @@
|
|||
[quo.design-system.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]))
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(defn style-message-text
|
||||
[outgoing]
|
||||
{:color (if outgoing colors/white-persist colors/text)})
|
||||
[]
|
||||
{:color colors/text})
|
||||
|
||||
(defn system-message-body
|
||||
[_]
|
||||
|
@ -18,9 +18,9 @@
|
|||
:align-items :center})
|
||||
|
||||
(defn message-body
|
||||
[{:keys [outgoing]}]
|
||||
(let [align (if outgoing :flex-end :flex-start)
|
||||
direction (if outgoing :row-reverse :row)]
|
||||
[]
|
||||
(let [align :flex-start
|
||||
direction :row]
|
||||
{:flex-direction direction
|
||||
:margin-top 4
|
||||
:align-self align
|
||||
|
@ -33,14 +33,10 @@
|
|||
[]
|
||||
(merge message-timestamp {:opacity 0 :color "rgba(0,0,0,0)"}))
|
||||
|
||||
(defn message-timestamp-wrapper [{:keys [last-in-group? outgoing group-chat]}]
|
||||
(defn message-timestamp-wrapper []
|
||||
{:justify-content :center
|
||||
(if outgoing :margin-right :margin-left) 12 ;; horizontal margin is only required at the adjust side of the message.
|
||||
:margin-top (if (and last-in-group?
|
||||
(or outgoing
|
||||
(not group-chat)))
|
||||
16
|
||||
0) ;; Add gap between message groups
|
||||
:margin-left 12 ;; horizontal margin is only required at the adjust side of the message.
|
||||
:margin-top 0
|
||||
:opacity 0})
|
||||
|
||||
(defn message-timestamp-text []
|
||||
|
@ -48,49 +44,38 @@
|
|||
{:color colors/gray
|
||||
:text-align :center}))
|
||||
|
||||
(defn message-status-text [outgoing]
|
||||
(defn message-status-text []
|
||||
{:font-size 10
|
||||
:line-height 10
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)})
|
||||
:color colors/gray})
|
||||
|
||||
(defn audio-message-timestamp-text
|
||||
[outgoing]
|
||||
[]
|
||||
(merge message-timestamp
|
||||
{:line-height 10
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)}))
|
||||
:color colors/gray}))
|
||||
|
||||
(defn message-wrapper [{:keys [outgoing in-popover?]}]
|
||||
(if (and outgoing (not in-popover?))
|
||||
{:margin-left 96}
|
||||
{:margin-right 96}))
|
||||
(defn message-wrapper [{:keys [in-popover?]}]
|
||||
(if (not in-popover?)
|
||||
{:margin-left 10
|
||||
:padding-right 5}
|
||||
{:margin-right 10}))
|
||||
|
||||
(defn message-author-wrapper
|
||||
[outgoing display-photo? in-popover?]
|
||||
(let [align (if (and outgoing (not in-popover?)) :flex-end :flex-start)]
|
||||
(merge {:flex-direction :column
|
||||
:flex-shrink 1
|
||||
:align-items align}
|
||||
(if (and outgoing (not in-popover?))
|
||||
{:margin-right 8}
|
||||
(when-not display-photo?
|
||||
{:margin-left 8})))))
|
||||
(defn message-author-wrapper []
|
||||
{:flex-direction :column
|
||||
:flex-shrink 1
|
||||
:align-items :flex-start
|
||||
:margin-left 4})
|
||||
|
||||
(defn delivery-status [outgoing]
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:padding-right 8}
|
||||
{:align-self :flex-start
|
||||
:padding-left 8}))
|
||||
(defn delivery-status []
|
||||
{:align-self :flex-start
|
||||
:padding-left 8})
|
||||
|
||||
(defn pin-indicator [outgoing display-photo?]
|
||||
(defn pin-indicator [display-photo?]
|
||||
(merge
|
||||
{:flex-direction :row
|
||||
:border-top-left-radius (if outgoing 12 4)
|
||||
:border-top-right-radius (if outgoing 4 12)
|
||||
:border-top-left-radius 4
|
||||
:border-top-right-radius 12
|
||||
:border-bottom-left-radius 12
|
||||
:border-bottom-right-radius 12
|
||||
:padding-left 8
|
||||
|
@ -98,27 +83,18 @@
|
|||
:padding-vertical 5
|
||||
:background-color colors/gray-lighter
|
||||
:justify-content :center
|
||||
:max-width "80%"}
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:align-items :flex-end}
|
||||
{:align-self :flex-start
|
||||
:align-items :flex-start})
|
||||
:max-width "80%"
|
||||
:align-self :flex-start
|
||||
:align-items :flex-start}
|
||||
(when display-photo?
|
||||
{:margin-left 44})))
|
||||
|
||||
(defn pin-indicator-container [outgoing]
|
||||
(merge
|
||||
{:margin-top 2
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:align-items :flex-end
|
||||
:padding-right 8}
|
||||
{:align-self :flex-start
|
||||
:align-items :flex-start
|
||||
:padding-left 8})))
|
||||
(defn pin-indicator-container []
|
||||
{:margin-top 2
|
||||
:justify-content :center
|
||||
:align-self :flex-start
|
||||
:align-items :flex-start
|
||||
:padding-left 8})
|
||||
|
||||
(defn pinned-by-text-icon-container []
|
||||
{:flex-direction :row
|
||||
|
@ -145,17 +121,14 @@
|
|||
{:margin-left 5})
|
||||
|
||||
(def message-author-touchable
|
||||
{:margin-left 12
|
||||
{:margin-left 0
|
||||
:flex-direction :row})
|
||||
|
||||
(defn message-author-userpic [outgoing]
|
||||
(defn message-author-userpic []
|
||||
(merge
|
||||
{:width (+ 16 photos/default-size) ;; 16 is for the padding
|
||||
:align-self :flex-end}
|
||||
(if outgoing
|
||||
{:padding-left 8}
|
||||
{:padding-horizontal 8
|
||||
:padding-right 8})))
|
||||
{:width (+ 16 photos/default-size)} ;; 16 is for the padding
|
||||
{:padding-left 8
|
||||
:padding-right 8}))
|
||||
|
||||
(def delivery-text
|
||||
{:color colors/gray
|
||||
|
@ -178,10 +151,10 @@
|
|||
:padding-left 3})
|
||||
|
||||
(defn emoji-message
|
||||
[{:keys [incoming-group outgoing]}]
|
||||
[{:keys [incoming-group]}]
|
||||
{:font-size 28
|
||||
:line-height 34 ;TODO: Smaller crops the icon on the top
|
||||
:margin-right (if outgoing 18 0) ;; Margin to display outgoing message status
|
||||
:margin-right 0 ;; Margin to display outgoing message status
|
||||
:margin-top (if incoming-group 4 0)})
|
||||
|
||||
(defn collapse-button []
|
||||
|
@ -193,37 +166,25 @@
|
|||
:shadow-color (:shadow-01 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})
|
||||
|
||||
(defn message-view-wrapper [outgoing]
|
||||
(def message-view-wrapper
|
||||
{:align-self :flex-end
|
||||
:flex-direction (if outgoing :row :row-reverse)})
|
||||
:flex-direction :row-reverse})
|
||||
|
||||
(defn message-view
|
||||
[{:keys [content-type outgoing group-chat last-in-group? mentioned pinned]}]
|
||||
[{:keys [content-type mentioned pinned]}]
|
||||
(merge
|
||||
{:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-right-radius 16
|
||||
:border-bottom-left-radius 16
|
||||
:padding-top 6
|
||||
:padding-horizontal 12
|
||||
:border-radius 8
|
||||
:margin-top (if (and last-in-group?
|
||||
(or outgoing
|
||||
(not group-chat)))
|
||||
16
|
||||
0)}
|
||||
(if outgoing
|
||||
{:border-bottom-right-radius 4}
|
||||
{:border-bottom-left-radius 4})
|
||||
{:border-radius 10}
|
||||
|
||||
(cond
|
||||
pinned {:background-color colors/pin-background}
|
||||
(= content-type constants/content-type-system-text) nil
|
||||
outgoing {:background-color colors/blue}
|
||||
mentioned {:background-color colors/mentioned-background
|
||||
:border-color colors/mentioned-border
|
||||
:border-width 1}
|
||||
:else {:background-color colors/blue-light})
|
||||
(= content-type constants/content-type-audio) {:background-color colors/blue
|
||||
:padding-horizontal 12
|
||||
:padding-top 6}
|
||||
:else {:background-color colors/white})
|
||||
|
||||
(when (= content-type constants/content-type-emoji)
|
||||
{:flex-direction :row})))
|
||||
|
@ -247,12 +208,10 @@
|
|||
:padding-left 12
|
||||
:text-align-vertical :center})
|
||||
|
||||
(defn quoted-message-container [outgoing]
|
||||
(defn quoted-message-container []
|
||||
{:margin-bottom 6
|
||||
:padding-bottom 6
|
||||
:border-bottom-color (if outgoing
|
||||
colors/white-transparent-10
|
||||
colors/black-transparent)
|
||||
:border-bottom-color colors/black-transparent
|
||||
:border-bottom-width 2
|
||||
:border-bottom-left-radius 2
|
||||
:border-bottom-right-radius 2})
|
||||
|
@ -262,29 +221,31 @@
|
|||
:align-items :center
|
||||
:justify-content :flex-start})
|
||||
|
||||
(defn quoted-message-author [outgoing chosen?]
|
||||
(defn quoted-message-author [chosen?]
|
||||
(assoc (message-author-name chosen?)
|
||||
:padding-bottom 6
|
||||
:padding-top 0
|
||||
:padding-left 0
|
||||
:line-height 18
|
||||
:font-weight "500"
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)))
|
||||
:color colors/gray))
|
||||
|
||||
(defn quoted-message-text [outgoing]
|
||||
(defn quoted-message-text []
|
||||
{:font-size 14
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)})
|
||||
:color colors/gray})
|
||||
|
||||
(defn message-default-style []
|
||||
{:font-family "Inter-Regular"
|
||||
:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)
|
||||
:font-size 15
|
||||
:line-height 21.75
|
||||
:letter-spacing -0.135})
|
||||
|
||||
;; Markdown styles
|
||||
|
||||
(defn default-text-style []
|
||||
{:max-font-size-multiplier react/max-font-size-multiplier
|
||||
:style (assoc (typography/default-style)
|
||||
:line-height 22)})
|
||||
:style (message-default-style)})
|
||||
|
||||
(defn outgoing-text-style []
|
||||
(update (default-text-style) :style
|
||||
|
@ -298,12 +259,11 @@
|
|||
:text-align :center
|
||||
:font-weight "400"))
|
||||
|
||||
(defn text-style [outgoing content-type in-popover?]
|
||||
(defn text-style [content-type in-popover?]
|
||||
(merge
|
||||
(when in-popover? {:number-of-lines 2})
|
||||
(cond
|
||||
(= content-type constants/content-type-system-text) (system-text-style)
|
||||
outgoing (outgoing-text-style)
|
||||
:else (default-text-style))))
|
||||
|
||||
(defn emph-text-style []
|
||||
|
@ -314,10 +274,8 @@
|
|||
(update (emph-text-style) :style
|
||||
assoc :color colors/white-persist))
|
||||
|
||||
(defn emph-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-emph-text-style)
|
||||
(emph-text-style)))
|
||||
(defn emph-style []
|
||||
(emph-text-style))
|
||||
|
||||
(defn strong-text-style []
|
||||
(update (default-text-style) :style
|
||||
|
@ -327,20 +285,17 @@
|
|||
(update (strong-text-style) :style
|
||||
assoc :color colors/white-persist))
|
||||
|
||||
(defn strong-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-strong-text-style)
|
||||
(strong-text-style)))
|
||||
(defn strong-style []
|
||||
(outgoing-strong-text-style)
|
||||
(strong-text-style))
|
||||
|
||||
(defn strong-emph-style [outgoing]
|
||||
(update (strong-style outgoing) :style
|
||||
(defn strong-emph-style []
|
||||
(update (strong-style) :style
|
||||
assoc :font-style :italic))
|
||||
|
||||
(defn strikethrough-style [outgoing]
|
||||
(defn strikethrough-style []
|
||||
(cond-> (update (default-text-style) :style
|
||||
assoc :text-decoration-line :line-through)
|
||||
outgoing
|
||||
(update :style assoc :color colors/white-persist)))
|
||||
assoc :text-decoration-line :line-through)))
|
||||
|
||||
(def code-block-background "#2E386B")
|
||||
|
||||
|
@ -366,10 +321,8 @@
|
|||
assoc
|
||||
:border-left-color colors/white-transparent-70-persist))
|
||||
|
||||
(defn blockquote-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-blockquote-style)
|
||||
(default-blockquote-style)))
|
||||
(defn blockquote-style []
|
||||
(default-blockquote-style))
|
||||
|
||||
(defn default-blockquote-text-style []
|
||||
(update (default-text-style) :style
|
||||
|
@ -383,20 +336,16 @@
|
|||
assoc
|
||||
:color colors/white-transparent-70-persist))
|
||||
|
||||
(defn blockquote-text-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-blockquote-text-style)
|
||||
(default-blockquote-text-style)))
|
||||
(defn blockquote-text-style []
|
||||
(outgoing-blockquote-text-style)
|
||||
(default-blockquote-text-style))
|
||||
|
||||
(defn image-message
|
||||
[{:keys [outgoing width height]}]
|
||||
{:overflow :hidden
|
||||
:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-left-radius (if outgoing 16 4)
|
||||
:border-bottom-right-radius (if outgoing 4 16)
|
||||
:width width
|
||||
:height height})
|
||||
[{:keys [width height]}]
|
||||
{:overflow :hidden
|
||||
:border-radius 8
|
||||
:width width
|
||||
:height height})
|
||||
|
||||
(defn image-message-border [opts]
|
||||
(merge (image-message opts)
|
||||
|
@ -453,7 +402,7 @@
|
|||
:padding-vertical 10
|
||||
:padding-horizontal 16})
|
||||
|
||||
(defn content-type-contact-request [outgoing]
|
||||
(defn content-type-contact-request []
|
||||
{:width 168
|
||||
:min-height 224.71
|
||||
:border-radius 8
|
||||
|
@ -462,6 +411,6 @@
|
|||
:align-items :center
|
||||
:padding-bottom 10
|
||||
:margin-vertical 4
|
||||
:align-self (if outgoing :flex-end :flex-start)
|
||||
:margin-right (if outgoing 8 0)
|
||||
:margin-left (if outgoing 0 8)})
|
||||
:align-self :flex-start
|
||||
:margin-right 0
|
||||
:margin-left 8})
|
||||
|
|
|
@ -0,0 +1,467 @@
|
|||
(ns status-im.ui.screens.chat.styles.message.message-old
|
||||
(:require [status-im.constants :as constants]
|
||||
[quo.design-system.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]))
|
||||
|
||||
(defn style-message-text
|
||||
[outgoing]
|
||||
{:color (if outgoing colors/white-persist colors/text)})
|
||||
|
||||
(defn system-message-body
|
||||
[_]
|
||||
{:margin-top 4
|
||||
:margin-left 8
|
||||
:margin-right 8
|
||||
:align-self :center
|
||||
:align-items :center})
|
||||
|
||||
(defn message-body
|
||||
[{:keys [outgoing]}]
|
||||
(let [align (if outgoing :flex-end :flex-start)
|
||||
direction (if outgoing :row-reverse :row)]
|
||||
{:flex-direction direction
|
||||
:margin-top 4
|
||||
:align-self align
|
||||
:align-items align}))
|
||||
|
||||
(def message-timestamp
|
||||
{:font-size 10})
|
||||
|
||||
(defn message-status-placeholder
|
||||
[]
|
||||
(merge message-timestamp {:opacity 0 :color "rgba(0,0,0,0)"}))
|
||||
|
||||
(defn message-timestamp-wrapper [{:keys [last-in-group? outgoing group-chat]}]
|
||||
{:justify-content :center
|
||||
(if outgoing :margin-right :margin-left) 12 ;; horizontal margin is only required at the adjust side of the message.
|
||||
:margin-top (if (and last-in-group?
|
||||
(or outgoing
|
||||
(not group-chat)))
|
||||
16
|
||||
0) ;; Add gap between message groups
|
||||
:opacity 0})
|
||||
|
||||
(defn message-timestamp-text []
|
||||
(merge message-timestamp
|
||||
{:color colors/gray
|
||||
:text-align :center}))
|
||||
|
||||
(defn message-status-text [outgoing]
|
||||
{:font-size 10
|
||||
:line-height 10
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)})
|
||||
|
||||
(defn audio-message-timestamp-text
|
||||
[outgoing]
|
||||
(merge message-timestamp
|
||||
{:line-height 10
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)}))
|
||||
|
||||
(defn message-wrapper [{:keys [outgoing in-popover?]}]
|
||||
(if (and outgoing (not in-popover?))
|
||||
{:margin-left 96}
|
||||
{:margin-right 96}))
|
||||
|
||||
(defn message-author-wrapper
|
||||
[outgoing display-photo? in-popover?]
|
||||
(let [align (if (and outgoing (not in-popover?)) :flex-end :flex-start)]
|
||||
(merge {:flex-direction :column
|
||||
:flex-shrink 1
|
||||
:align-items align}
|
||||
(if (and outgoing (not in-popover?))
|
||||
{:margin-right 8}
|
||||
(when-not display-photo?
|
||||
{:margin-left 8})))))
|
||||
|
||||
(defn delivery-status [outgoing]
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:padding-right 8}
|
||||
{:align-self :flex-start
|
||||
:padding-left 8}))
|
||||
|
||||
(defn pin-indicator [outgoing display-photo?]
|
||||
(merge
|
||||
{:flex-direction :row
|
||||
:border-top-left-radius (if outgoing 12 4)
|
||||
:border-top-right-radius (if outgoing 4 12)
|
||||
:border-bottom-left-radius 12
|
||||
:border-bottom-right-radius 12
|
||||
:padding-left 8
|
||||
:padding-right 10
|
||||
:padding-vertical 5
|
||||
:background-color colors/gray-lighter
|
||||
:justify-content :center
|
||||
:max-width "80%"}
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:align-items :flex-end}
|
||||
{:align-self :flex-start
|
||||
:align-items :flex-start})
|
||||
(when display-photo?
|
||||
{:margin-left 44})))
|
||||
|
||||
(defn pin-indicator-container [outgoing]
|
||||
(merge
|
||||
{:margin-top 2
|
||||
:align-items :center
|
||||
:justify-content :center}
|
||||
(if outgoing
|
||||
{:align-self :flex-end
|
||||
:align-items :flex-end
|
||||
:padding-right 8}
|
||||
{:align-self :flex-start
|
||||
:align-items :flex-start
|
||||
:padding-left 8})))
|
||||
|
||||
(defn pinned-by-text-icon-container []
|
||||
{:flex-direction :row
|
||||
:align-items :flex-start
|
||||
:top 5
|
||||
:left 8
|
||||
:position :absolute})
|
||||
|
||||
(defn pin-icon-container []
|
||||
{:flex-direction :row
|
||||
:margin-top 1})
|
||||
|
||||
(defn pin-author-text []
|
||||
{:margin-left 2
|
||||
:margin-right 12
|
||||
:padding-right 0
|
||||
:left 12
|
||||
:flex-direction :row
|
||||
:flex-shrink 1
|
||||
:align-self :flex-start
|
||||
:overflow :hidden})
|
||||
|
||||
(defn pinned-by-text []
|
||||
{:margin-left 5})
|
||||
|
||||
(def message-author-touchable
|
||||
{:margin-left 12
|
||||
:flex-direction :row})
|
||||
|
||||
(defn message-author-userpic [outgoing]
|
||||
(merge
|
||||
{:width (+ 16 photos/default-size) ;; 16 is for the padding
|
||||
:align-self :flex-end}
|
||||
(if outgoing
|
||||
{:padding-left 8}
|
||||
{:padding-horizontal 8
|
||||
:padding-right 8})))
|
||||
|
||||
(def delivery-text
|
||||
{:color colors/gray
|
||||
:margin-top 2
|
||||
:font-size 12})
|
||||
|
||||
(def not-sent-view
|
||||
{:flex-direction :row
|
||||
:margin-bottom 2
|
||||
:padding-top 2})
|
||||
|
||||
(def not-sent-text
|
||||
(assoc delivery-text
|
||||
:color colors/red
|
||||
:text-align :right
|
||||
:padding-top 4))
|
||||
|
||||
(def not-sent-icon
|
||||
{:padding-top 3
|
||||
:padding-left 3})
|
||||
|
||||
(defn emoji-message
|
||||
[{:keys [incoming-group outgoing]}]
|
||||
{:font-size 28
|
||||
:line-height 34 ;TODO: Smaller crops the icon on the top
|
||||
:margin-right (if outgoing 18 0) ;; Margin to display outgoing message status
|
||||
: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 @colors/theme)
|
||||
:shadow-offset {:width 0 :height 4}})
|
||||
|
||||
(defn message-view-wrapper [outgoing]
|
||||
{:align-self :flex-end
|
||||
:flex-direction (if outgoing :row :row-reverse)})
|
||||
|
||||
(defn message-view
|
||||
[{:keys [content-type outgoing group-chat last-in-group? mentioned pinned]}]
|
||||
(merge
|
||||
{:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-right-radius 16
|
||||
:border-bottom-left-radius 16
|
||||
:padding-top 6
|
||||
:padding-horizontal 12
|
||||
:border-radius 8
|
||||
:margin-top (if (and last-in-group?
|
||||
(or outgoing
|
||||
(not group-chat)))
|
||||
16
|
||||
0)}
|
||||
(if outgoing
|
||||
{:border-bottom-right-radius 4}
|
||||
{:border-bottom-left-radius 4})
|
||||
|
||||
(cond
|
||||
pinned {:background-color colors/pin-background}
|
||||
(= content-type constants/content-type-system-text) nil
|
||||
outgoing {:background-color colors/blue}
|
||||
mentioned {:background-color colors/mentioned-background
|
||||
:border-color colors/mentioned-border
|
||||
:border-width 1}
|
||||
:else {:background-color colors/blue-light})
|
||||
|
||||
(when (= content-type constants/content-type-emoji)
|
||||
{:flex-direction :row})))
|
||||
|
||||
(defn message-view-content []
|
||||
{:padding-bottom 6
|
||||
:overflow :hidden})
|
||||
|
||||
(def status-container
|
||||
{:padding-horizontal 5})
|
||||
|
||||
(defn status-text []
|
||||
{:margin-top 9
|
||||
:font-size 14
|
||||
:color colors/gray})
|
||||
|
||||
(defn message-author-name [chosen?]
|
||||
{:font-size (if chosen? 13 12)
|
||||
:font-weight (if chosen? "500" "400")
|
||||
:padding-top 6
|
||||
:padding-left 12
|
||||
:text-align-vertical :center})
|
||||
|
||||
(defn quoted-message-container [outgoing]
|
||||
{:margin-bottom 6
|
||||
:padding-bottom 6
|
||||
:border-bottom-color (if outgoing
|
||||
colors/white-transparent-10
|
||||
colors/black-transparent)
|
||||
:border-bottom-width 2
|
||||
:border-bottom-left-radius 2
|
||||
:border-bottom-right-radius 2})
|
||||
|
||||
(def quoted-message-author-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:justify-content :flex-start})
|
||||
|
||||
(defn quoted-message-author [outgoing chosen?]
|
||||
(assoc (message-author-name chosen?)
|
||||
:padding-bottom 6
|
||||
:padding-top 0
|
||||
:padding-left 0
|
||||
:line-height 18
|
||||
:font-weight "500"
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)))
|
||||
|
||||
(defn quoted-message-text [outgoing]
|
||||
{:font-size 14
|
||||
:color (if outgoing
|
||||
colors/white-transparent-70-persist
|
||||
colors/gray)})
|
||||
|
||||
;; Markdown styles
|
||||
|
||||
(defn default-text-style []
|
||||
{:max-font-size-multiplier react/max-font-size-multiplier
|
||||
:style (assoc (typography/default-style)
|
||||
:line-height 22)})
|
||||
|
||||
(defn outgoing-text-style []
|
||||
(update (default-text-style) :style
|
||||
assoc :color colors/white-persist))
|
||||
|
||||
(defn system-text-style []
|
||||
(update (default-text-style) :style assoc
|
||||
:color colors/gray
|
||||
:line-height 20
|
||||
:font-size 14
|
||||
:text-align :center
|
||||
:font-weight "400"))
|
||||
|
||||
(defn text-style [outgoing content-type in-popover?]
|
||||
(merge
|
||||
(when in-popover? {:number-of-lines 2})
|
||||
(cond
|
||||
(= content-type constants/content-type-system-text) (system-text-style)
|
||||
outgoing (outgoing-text-style)
|
||||
:else (default-text-style))))
|
||||
|
||||
(defn emph-text-style []
|
||||
(update (default-text-style) :style
|
||||
assoc :font-style :italic))
|
||||
|
||||
(defn outgoing-emph-text-style []
|
||||
(update (emph-text-style) :style
|
||||
assoc :color colors/white-persist))
|
||||
|
||||
(defn emph-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-emph-text-style)
|
||||
(emph-text-style)))
|
||||
|
||||
(defn strong-text-style []
|
||||
(update (default-text-style) :style
|
||||
assoc :font-weight "700"))
|
||||
|
||||
(defn outgoing-strong-text-style []
|
||||
(update (strong-text-style) :style
|
||||
assoc :color colors/white-persist))
|
||||
|
||||
(defn strong-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-strong-text-style)
|
||||
(strong-text-style)))
|
||||
|
||||
(defn strong-emph-style [outgoing]
|
||||
(update (strong-style outgoing) :style
|
||||
assoc :font-style :italic))
|
||||
|
||||
(defn strikethrough-style [outgoing]
|
||||
(cond-> (update (default-text-style) :style
|
||||
assoc :text-decoration-line :line-through)
|
||||
outgoing
|
||||
(update :style assoc :color colors/white-persist)))
|
||||
|
||||
(def code-block-background "#2E386B")
|
||||
|
||||
(defn inline-code-style []
|
||||
{:color colors/white-persist
|
||||
:background-color code-block-background})
|
||||
|
||||
(def codeblock-style
|
||||
{:padding 10
|
||||
:background-color code-block-background
|
||||
:border-radius 4})
|
||||
|
||||
(def codeblock-text-style
|
||||
{:color colors/white-persist})
|
||||
|
||||
(defn default-blockquote-style []
|
||||
{:style {:border-left-width 2
|
||||
:padding-left 3
|
||||
:border-left-color colors/gray-transparent-40}})
|
||||
|
||||
(defn outgoing-blockquote-style []
|
||||
(update (default-blockquote-style) :style
|
||||
assoc
|
||||
:border-left-color colors/white-transparent-70-persist))
|
||||
|
||||
(defn blockquote-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-blockquote-style)
|
||||
(default-blockquote-style)))
|
||||
|
||||
(defn default-blockquote-text-style []
|
||||
(update (default-text-style) :style
|
||||
assoc
|
||||
:line-height 19
|
||||
:font-size 14
|
||||
:color colors/black-transparent-50))
|
||||
|
||||
(defn outgoing-blockquote-text-style []
|
||||
(update (default-blockquote-text-style) :style
|
||||
assoc
|
||||
:color colors/white-transparent-70-persist))
|
||||
|
||||
(defn blockquote-text-style [outgoing]
|
||||
(if outgoing
|
||||
(outgoing-blockquote-text-style)
|
||||
(default-blockquote-text-style)))
|
||||
|
||||
(defn image-message
|
||||
[{:keys [outgoing width height]}]
|
||||
{:overflow :hidden
|
||||
:border-top-left-radius 16
|
||||
:border-top-right-radius 16
|
||||
:border-bottom-left-radius (if outgoing 16 4)
|
||||
:border-bottom-right-radius (if outgoing 4 16)
|
||||
:width width
|
||||
:height height})
|
||||
|
||||
(defn image-message-border [opts]
|
||||
(merge (image-message opts)
|
||||
{:opacity (:opacity opts)
|
||||
:border-width 1
|
||||
:top 0
|
||||
:left 0
|
||||
:position :absolute
|
||||
:background-color :transparent
|
||||
:border-color colors/black-transparent}))
|
||||
|
||||
(defn community-verified []
|
||||
{:border-right-width 1
|
||||
:border-left-width 1
|
||||
:border-top-width 1
|
||||
:border-left-color colors/gray-lighter
|
||||
:border-right-color colors/gray-lighter
|
||||
:border-top-left-radius 10
|
||||
:border-top-right-radius 10
|
||||
:padding-vertical 8
|
||||
:padding-horizontal 15
|
||||
:border-top-color colors/gray-lighter})
|
||||
|
||||
(defn community-message [verified]
|
||||
{:flex-direction :row
|
||||
:padding-vertical 12
|
||||
:border-top-left-radius (when-not verified 10)
|
||||
:border-top-right-radius (when-not verified 10)
|
||||
:border-right-width 1
|
||||
:border-left-width 1
|
||||
:border-top-width 1
|
||||
:border-color colors/gray-lighter})
|
||||
|
||||
(defn community-view-button []
|
||||
{:border-width 1
|
||||
:padding-vertical 8
|
||||
:border-bottom-left-radius 10
|
||||
:border-bottom-right-radius 10
|
||||
:border-color colors/gray-lighter})
|
||||
|
||||
(defn contact-request-status-label [state]
|
||||
{:width 136
|
||||
:border-radius 8
|
||||
:flex 1
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:background-color (when (= :retry state)
|
||||
colors/blue-light)
|
||||
:border-width 1
|
||||
:border-color (case state
|
||||
constants/contact-request-message-state-accepted colors/green-transparent-10
|
||||
constants/contact-request-message-state-declined colors/red-light
|
||||
constants/contact-request-message-state-pending colors/gray-lighter)
|
||||
:padding-vertical 10
|
||||
:padding-horizontal 16})
|
||||
|
||||
(defn content-type-contact-request [outgoing]
|
||||
{:width 168
|
||||
:min-height 224.71
|
||||
:border-radius 8
|
||||
:border-width 1
|
||||
:border-color colors/gray-lighter
|
||||
:align-items :center
|
||||
:padding-bottom 10
|
||||
:margin-vertical 4
|
||||
:align-self (if outgoing :flex-end :flex-start)
|
||||
:margin-right (if outgoing 8 0)
|
||||
:margin-left (if outgoing 0 8)})
|
|
@ -7,8 +7,8 @@
|
|||
|
||||
(def ^:private reply-symbol "↪ ")
|
||||
|
||||
(defn format-author
|
||||
([contact] (format-author contact nil))
|
||||
(defn format-author-old
|
||||
([contact] (format-author-old contact nil))
|
||||
([{:keys [names] :as contact} {:keys [modal profile? you?]}]
|
||||
(let [{:keys [nickname ens-name]} names
|
||||
[first-name second-name] (multiaccounts/contact-two-names contact false)]
|
||||
|
@ -31,6 +31,32 @@
|
|||
:font-weight "400"}}
|
||||
first-name]))))
|
||||
|
||||
(defn format-author
|
||||
([contact] (format-author contact nil))
|
||||
([{:keys [names] :as contact} {:keys [modal profile? you?]}]
|
||||
(let [{:keys [nickname ens-name]} names
|
||||
[first-name second-name] (multiaccounts/contact-two-names contact false)]
|
||||
(if (or nickname ens-name)
|
||||
[react/nested-text {:number-of-lines 2
|
||||
:style {:color (if modal colors/white-persist colors/black)
|
||||
:font-size (if profile? 15 13)
|
||||
:line-height (if profile? 22 18)
|
||||
:letter-spacing -0.2
|
||||
:font-weight "600"}}
|
||||
(subs first-name 0 81)
|
||||
(when you?
|
||||
[{:style {:color colors/black-light :font-weight "500" :font-size 13}}
|
||||
(str " " (i18n/label :t/You))])
|
||||
(when nickname
|
||||
[{:style {:color colors/black-light :font-weight "500"}}
|
||||
(str " " (subs second-name 0 81))])]
|
||||
[react/text {:style {:color (if modal colors/white-persist colors/black)
|
||||
:font-size (if profile? 15 13)
|
||||
:line-height (if profile? 22 18)
|
||||
:font-weight "600"
|
||||
:letter-spacing -0.2}}
|
||||
first-name]))))
|
||||
|
||||
(defn format-reply-author [from username current-public-key style outgoing]
|
||||
(let [contact-name (str reply-symbol username)]
|
||||
(or (and (= from current-public-key)
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[quo.react-native :as rn]
|
||||
[status-im.ui.screens.chat.audio-message.views :as audio-message]
|
||||
[quo.react :as quo.react]
|
||||
[status-im.ui.screens.chat.message.message-old :as message-old]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.ui.screens.chat.stickers.views :as stickers]
|
||||
[status-im.ui.screens.chat.styles.main :as style]
|
||||
|
@ -27,6 +28,7 @@
|
|||
[status-im.ui.screens.chat.message.gap :as gap]
|
||||
[status-im.ui.screens.chat.components.accessory :as accessory]
|
||||
[status-im.ui.screens.chat.components.input :as components]
|
||||
[status-im.ui.screens.chat.message.datemark-old :as message-datemark-old]
|
||||
[status-im.ui.screens.chat.message.datemark :as message-datemark]
|
||||
[status-im.ui.components.toolbar :as toolbar]
|
||||
[quo.core :as quo]
|
||||
|
@ -37,7 +39,10 @@
|
|||
[status-im.ui.screens.chat.sheets :as sheets]
|
||||
[status-im.utils.debounce :as debounce]
|
||||
[status-im.navigation.state :as navigation.state]
|
||||
[status-im.react-native.resources :as resources]))
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[quo2.foundations.colors :as quo2.colors]
|
||||
[quo2.components.button :as quo2.button]))
|
||||
|
||||
(defn invitation-requests [chat-id admins]
|
||||
(let [current-pk @(re-frame/subscribe [:multiaccount/public-key])
|
||||
|
@ -53,6 +58,18 @@
|
|||
(i18n/label :t/group-membership-request)]]])))))
|
||||
|
||||
(defn add-contact-bar [public-key]
|
||||
(when-not (or @(re-frame/subscribe [:contacts/contact-added? public-key])
|
||||
@(re-frame/subscribe [:contacts/contact-blocked? public-key]))
|
||||
[react/touchable-highlight
|
||||
{:on-press
|
||||
#(re-frame/dispatch [:contact.ui/add-to-contact-pressed public-key])
|
||||
:accessibility-label :add-to-contacts-button}
|
||||
[react/view {:style (merge (style/add-contact) {:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/divider-dark)})}
|
||||
[icons/icon :main-icons/add
|
||||
{:color colors/blue}]
|
||||
[react/i18n-text {:style style/add-contact-text :key :add-to-contacts}]]]))
|
||||
|
||||
(defn add-contact-bar-old [public-key]
|
||||
(when-not (or @(re-frame/subscribe [:contacts/contact-added? public-key])
|
||||
@(re-frame/subscribe [:contacts/contact-blocked? public-key]))
|
||||
[react/touchable-highlight
|
||||
|
@ -286,6 +303,29 @@
|
|||
[react/view {:style (when platform/android? {:scaleY -1})}
|
||||
[chat.group/group-chat-footer chat-id invitation-admin]]))
|
||||
|
||||
(defn render-fn-old [{:keys [outgoing type] :as message}
|
||||
idx
|
||||
_
|
||||
{:keys [group-chat public? community? current-public-key space-keeper
|
||||
chat-id show-input? message-pin-enabled edit-enabled in-pinned-view?]}]
|
||||
[react/view {:style (when (and platform/android? (not in-pinned-view?)) {:scaleY -1})}
|
||||
(if (= type :datemark)
|
||||
[message-datemark-old/chat-datemark (:value message)]
|
||||
(if (= type :gap)
|
||||
[gap/gap message idx messages-list-ref false chat-id]
|
||||
; message content
|
||||
[message-old/chat-message
|
||||
(assoc message
|
||||
:incoming-group (and group-chat (not outgoing))
|
||||
:group-chat group-chat
|
||||
:public? public?
|
||||
:community? community?
|
||||
:current-public-key current-public-key
|
||||
:show-input? show-input?
|
||||
:message-pin-enabled message-pin-enabled
|
||||
:edit-enabled edit-enabled)
|
||||
space-keeper]))])
|
||||
|
||||
(defn render-fn [{:keys [outgoing type] :as message}
|
||||
idx
|
||||
_
|
||||
|
@ -342,6 +382,57 @@
|
|||
:edit-enabled edit-enabled
|
||||
:in-pinned-view? in-pinned-view?}))
|
||||
|
||||
(defn messages-view-old [{:keys [chat
|
||||
bottom-space
|
||||
pan-responder
|
||||
mutual-contact-requests-enabled?
|
||||
space-keeper
|
||||
show-input?]}]
|
||||
(let [{:keys [group-chat chat-type chat-id public? community-id admins]} chat
|
||||
|
||||
messages @(re-frame/subscribe [:chats/raw-chat-messages-stream chat-id])
|
||||
one-to-one? (= chat-type constants/one-to-one-chat-type)
|
||||
contact-added? (when one-to-one? @(re-frame/subscribe [:contacts/contact-added? chat-id]))
|
||||
should-send-contact-request?
|
||||
(and
|
||||
mutual-contact-requests-enabled?
|
||||
one-to-one?
|
||||
(not contact-added?))]
|
||||
|
||||
;;do not use anonymous functions for handlers
|
||||
[list/flat-list
|
||||
(merge
|
||||
pan-responder
|
||||
{:key-fn list-key-fn
|
||||
:ref list-ref
|
||||
:header [list-header chat]
|
||||
:footer [list-footer chat]
|
||||
:data (when-not should-send-contact-request?
|
||||
messages)
|
||||
:render-data (get-render-data {:group-chat group-chat
|
||||
:chat-id chat-id
|
||||
:public? public?
|
||||
:community-id community-id
|
||||
:admins admins
|
||||
:space-keeper space-keeper
|
||||
:show-input? show-input?
|
||||
:edit-enabled true
|
||||
:in-pinned-view? false})
|
||||
:render-fn render-fn-old
|
||||
:on-viewable-items-changed on-viewable-items-changed
|
||||
:on-end-reached list-on-end-reached
|
||||
:on-scroll-to-index-failed identity ;;don't remove this
|
||||
:content-container-style {:padding-top (+ bottom-space 16)
|
||||
:padding-bottom 16}
|
||||
:scroll-indicator-insets {:top bottom-space} ;;ios only
|
||||
:keyboard-dismiss-mode :interactive
|
||||
:keyboard-should-persist-taps :handled
|
||||
:onMomentumScrollBegin state/start-scrolling
|
||||
:onMomentumScrollEnd state/stop-scrolling
|
||||
;;TODO https://github.com/facebook/react-native/issues/30034
|
||||
:inverted (when platform/ios? true)
|
||||
:style (when platform/android? {:scaleY -1})})]))
|
||||
|
||||
(defn messages-view [{:keys [chat
|
||||
bottom-space
|
||||
pan-responder
|
||||
|
@ -393,13 +484,29 @@
|
|||
:inverted (when platform/ios? true)
|
||||
:style (when platform/android? {:scaleY -1})})]))
|
||||
|
||||
(defn back-button []
|
||||
[quo2.button/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label "back-button"
|
||||
:on-press #(re-frame/dispatch [:navigate-back])}
|
||||
[icons/icon :main-icons/arrow-left {:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}]])
|
||||
|
||||
(defn search-button []
|
||||
[quo2.button/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label "search-button"}
|
||||
[icons/icon :main-icons/search {:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}]])
|
||||
|
||||
(defn topbar-content []
|
||||
(let [window-width @(re-frame/subscribe [:dimensions/window-width])
|
||||
{:keys [group-chat chat-id] :as chat-info} @(re-frame/subscribe [:chats/current-chat])]
|
||||
[react/touchable-highlight {:on-press #(when-not group-chat
|
||||
(debounce/dispatch-and-chill [:chat.ui/show-profile chat-id] 1000))
|
||||
:style {:flex 1 :width (- window-width 120)}}
|
||||
[toolbar-content/toolbar-content-view-inner chat-info]]))
|
||||
[react/view {:flex-direction :row :align-items :center :height 56}
|
||||
[react/touchable-highlight {:on-press #(when-not group-chat
|
||||
(debounce/dispatch-and-chill [:chat.ui/show-profile chat-id] 1000))
|
||||
:style {:flex 1 :margin-left 12 :width (- window-width 120)}}
|
||||
[toolbar-content/toolbar-content-view-inner chat-info]]]))
|
||||
|
||||
(defn navigate-back-handler []
|
||||
(when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat))
|
||||
|
@ -407,7 +514,15 @@
|
|||
(re-frame/dispatch [:close-chat])
|
||||
(re-frame/dispatch [:navigate-back])))
|
||||
|
||||
(defn topbar []
|
||||
(defn topbar-content-old []
|
||||
(let [window-width @(re-frame/subscribe [:dimensions/window-width])
|
||||
{:keys [group-chat chat-id] :as chat-info} @(re-frame/subscribe [:chats/current-chat])]
|
||||
[react/touchable-highlight {:on-press #(when-not group-chat
|
||||
(debounce/dispatch-and-chill [:chat.ui/show-profile chat-id] 1000))
|
||||
:style {:flex 1 :width (- window-width 120)}}
|
||||
[toolbar-content/toolbar-content-view-inner chat-info]]))
|
||||
|
||||
(defn topbar-old []
|
||||
;;we don't use topbar component, because we want chat view as simple (fast) as possible
|
||||
[react/view {:height 56}
|
||||
[react/touchable-highlight {:on-press-in navigate-back-handler
|
||||
|
@ -416,7 +531,7 @@
|
|||
:padding-left 16}}
|
||||
[icons/icon :main-icons/arrow-left {:color colors/black}]]
|
||||
[react/view {:flex 1 :left 52 :right 52 :top 0 :bottom 0 :position :absolute}
|
||||
[topbar-content]]
|
||||
[topbar-content-old]]
|
||||
[react/touchable-highlight {:on-press-in #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[sheets/current-chat-actions])
|
||||
|
@ -427,6 +542,64 @@
|
|||
:padding-right 16}}
|
||||
[icons/icon :main-icons/more {:color colors/black}]]])
|
||||
|
||||
(defn chat-render-old []
|
||||
(let [bottom-space (reagent/atom 0)
|
||||
panel-space (reagent/atom 52)
|
||||
active-panel (reagent/atom nil)
|
||||
position-y (animated/value 0)
|
||||
pan-state (animated/value 0)
|
||||
text-input-ref (quo.react/create-ref)
|
||||
on-update #(when-not (zero? %) (reset! panel-space %))
|
||||
pan-responder (accessory/create-pan-responder position-y pan-state)
|
||||
space-keeper (get-space-keeper-ios bottom-space panel-space active-panel text-input-ref)
|
||||
set-active-panel (get-set-active-panel active-panel)
|
||||
on-close #(set-active-panel nil)]
|
||||
(fn []
|
||||
(let [{:keys [chat-id show-input? group-chat admins invitation-admin] :as chat}
|
||||
;;we want to react only on these fields, do not use full chat map here
|
||||
@(re-frame/subscribe [:chats/current-chat-chat-view])
|
||||
mutual-contact-requests-enabled? @(re-frame/subscribe [:mutual-contact-requests/enabled?])
|
||||
max-bottom-space (max @bottom-space @panel-space)]
|
||||
[:<>
|
||||
[topbar-old]
|
||||
[connectivity/loading-indicator]
|
||||
(when chat-id
|
||||
(if group-chat
|
||||
[invitation-requests chat-id admins]
|
||||
(when-not mutual-contact-requests-enabled? [add-contact-bar-old chat-id])))
|
||||
;;MESSAGES LIST
|
||||
[messages-view-old {:chat chat
|
||||
:bottom-space max-bottom-space
|
||||
:pan-responder pan-responder
|
||||
:mutual-contact-requests-enabled? mutual-contact-requests-enabled?
|
||||
:space-keeper space-keeper
|
||||
:show-input? show-input?}]
|
||||
(when (and group-chat invitation-admin)
|
||||
[accessory/view {:y position-y
|
||||
:on-update-inset on-update}
|
||||
[invitation-bar chat-id]])
|
||||
[components/autocomplete-mentions text-input-ref max-bottom-space]
|
||||
(when show-input?
|
||||
;; NOTE: this only accepts two children
|
||||
[accessory/view {:y position-y
|
||||
:pan-state pan-state
|
||||
:has-panel (boolean @active-panel)
|
||||
:on-close on-close
|
||||
:on-update-inset on-update}
|
||||
[react/view
|
||||
[edit/edit-message-auto-focus-wrapper text-input-ref]
|
||||
[reply/reply-message-auto-focus-wrapper text-input-ref]
|
||||
;; We set the key so we can force a re-render as
|
||||
;; it does not rely on ratom but just atoms
|
||||
^{:key (str @components/chat-input-key "chat-input")}
|
||||
[components/chat-toolbar
|
||||
{:chat-id chat-id
|
||||
:active-panel @active-panel
|
||||
:set-active-panel set-active-panel
|
||||
:text-input-ref text-input-ref}]
|
||||
[contact-request/contact-request-message-auto-focus-wrapper text-input-ref]]
|
||||
[bottom-sheet @active-panel]])]))))
|
||||
|
||||
(defn chat-render []
|
||||
(let [bottom-space (reagent/atom 0)
|
||||
panel-space (reagent/atom 52)
|
||||
|
@ -446,7 +619,15 @@
|
|||
mutual-contact-requests-enabled? @(re-frame/subscribe [:mutual-contact-requests/enabled?])
|
||||
max-bottom-space (max @bottom-space @panel-space)]
|
||||
[:<>
|
||||
[topbar]
|
||||
;; It is better to not use topbar component because of performance
|
||||
[topbar/topbar {:navigation :none
|
||||
:left-component [react/view {:flex-direction :row :margin-left 16}
|
||||
[back-button]]
|
||||
:title-component [topbar-content]
|
||||
:right-component [react/view {:flex-direction :row :margin-right 16}
|
||||
[search-button]]
|
||||
:border-bottom false
|
||||
:new-ui? true}]
|
||||
[connectivity/loading-indicator]
|
||||
(when chat-id
|
||||
(if group-chat
|
||||
|
@ -485,6 +666,14 @@
|
|||
[contact-request/contact-request-message-auto-focus-wrapper text-input-ref]]
|
||||
[bottom-sheet @active-panel]])]))))
|
||||
|
||||
(defn chat-old []
|
||||
(reagent/create-class
|
||||
{:component-did-mount (fn []
|
||||
(react/hw-back-remove-listener navigate-back-handler)
|
||||
(react/hw-back-add-listener navigate-back-handler))
|
||||
:component-will-unmount (fn [] (react/hw-back-remove-listener navigate-back-handler))
|
||||
:reagent-render chat-render-old}))
|
||||
|
||||
(defn chat []
|
||||
(reagent/create-class
|
||||
{:component-did-mount (fn []
|
||||
|
|
|
@ -148,7 +148,7 @@
|
|||
text]])
|
||||
|
||||
(defn community-chat-item [{:keys [chat-id] :as home-item} _ _ _]
|
||||
[inner-item/home-list-item
|
||||
[inner-item/home-list-item-old
|
||||
;; We want communities to behave as public chats when it comes to
|
||||
;; unread indicator
|
||||
(assoc home-item :public? true)
|
||||
|
@ -271,7 +271,7 @@
|
|||
[community-chat-list id categories false from-chat]
|
||||
[community-channel-preview-list id chats])
|
||||
(when admin
|
||||
[components.plus-button/plus-button
|
||||
[components.plus-button/plus-button-old
|
||||
{:on-press #(>evt [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[community-plus-actions community])}])
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
[quo/checkbox {:value selected
|
||||
:on-change on-change}]]
|
||||
[react/view {:flex 1}
|
||||
[inner-item/home-list-item
|
||||
[inner-item/home-list-item-old
|
||||
(assoc home-item :public? true)
|
||||
{:on-press on-change}]]]))
|
||||
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
{:title first-name
|
||||
:subtitle second-name
|
||||
:accessibility-label :member-item
|
||||
:icon [chat-icon/profile-photo-plus-dot-view
|
||||
:icon [chat-icon/profile-photo-plus-dot-view-old
|
||||
{:public-key public-key
|
||||
:photo-path (multiaccounts/displayed-photo member)}]
|
||||
:accessory (when (not= public-key my-public-key)
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
:on-press #(show-delete-chat-confirmation community-id chat-id)}
|
||||
[icons/icon :main-icons/delete-circle {:no-color true}]]
|
||||
[rn/view {:flex 1}
|
||||
[inner-item/home-list-item (assoc home-item :edit? true) {:active-opacity 1}]]
|
||||
[inner-item/home-list-item-old (assoc home-item :edit? true) {:active-opacity 1}]]
|
||||
[rn/touchable-opacity {:on-long-press drag
|
||||
:delay-long-press 100
|
||||
:accessibility-label :chat-drag-handle
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
[quo/list-item
|
||||
{:title first-name
|
||||
:subtitle second-name
|
||||
:icon [chat-icon.screen/profile-photo-plus-dot-view
|
||||
:icon [chat-icon.screen/profile-photo-plus-dot-view-old
|
||||
{:public-key public-key
|
||||
:photo-path (multiaccounts/displayed-photo contact)}]
|
||||
:chevron true
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
[react/view {:flex 1}
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:search/currency-filter-changed nil])
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||
[status-im.ui.components.toolbar :as toolbar]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.ui.screens.chat.message.message-old :as message]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.profile.components.views :as profile.components]
|
||||
[status-im.utils.debounce :as debounce]
|
||||
|
@ -639,10 +639,10 @@
|
|||
(views/defview my-name []
|
||||
(views/letsubs [contact-name [:multiaccount/preferred-name]]
|
||||
(when-not (string/blank? contact-name)
|
||||
(chat.utils/format-author {:names {:ens-name
|
||||
(str "@"
|
||||
(or (stateofus/username contact-name)
|
||||
contact-name))}}))))
|
||||
(chat.utils/format-author-old {:names {:ens-name
|
||||
(str "@"
|
||||
(or (stateofus/username contact-name)
|
||||
contact-name))}}))))
|
||||
|
||||
(views/defview registered [names {:keys [preferred-name] :as account} _ registrations]
|
||||
[react/view {:style {:flex 1}}
|
||||
|
|
|
@ -149,8 +149,8 @@
|
|||
(fn [{:keys [contacts no-contacts-label toggle-fn allow-new-users?]}]
|
||||
[react/view {:style {:flex 1}}
|
||||
[react/view {:style (styles/search-container)}
|
||||
[search/search-input {:on-cancel #(reset! search-value nil)
|
||||
:on-change #(reset! search-value %)}]]
|
||||
[search/search-input-old {:on-cancel #(reset! search-value nil)
|
||||
:on-change #(reset! search-value %)}]]
|
||||
[react/view {:style {:flex 1
|
||||
:padding-vertical 8}}
|
||||
(if (seq contacts)
|
||||
|
|
|
@ -9,11 +9,10 @@
|
|||
|
||||
(def public-unread
|
||||
{:background-color colors/blue
|
||||
:border-radius 6
|
||||
:margin-right 5
|
||||
:margin-bottom 5
|
||||
:width 12
|
||||
:height 12})
|
||||
:border-radius 5
|
||||
:margin-right 16
|
||||
:width 10
|
||||
:height 10})
|
||||
|
||||
(def datetime-text
|
||||
{:color colors/text-gray
|
||||
|
|
|
@ -18,13 +18,18 @@
|
|||
[status-im.add-new.db :as db]
|
||||
[status-im.utils.debounce :as debounce]
|
||||
[status-im.utils.utils :as utils]
|
||||
[quo.components.safe-area :as safe-area]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.components.plus-button :as components.plus-button]
|
||||
[status-im.ui.screens.chat.sheets :as sheets]
|
||||
[status-im.ui.components.tabbar.core :as tabbar]
|
||||
[status-im.ui.components.invite.views :as invite]
|
||||
[status-im.utils.config :as config])
|
||||
[status-im.utils.config :as config]
|
||||
[quo2.components.text :as quo2.text]
|
||||
[status-im.qr-scanner.core :as qr-scanner]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]
|
||||
[quo2.foundations.colors :as quo2.colors]
|
||||
[quo2.components.button :as quo2.button])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(defn home-tooltip-view []
|
||||
|
@ -71,6 +76,26 @@
|
|||
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
|
||||
(debounce/debounce-and-dispatch [:new-chat/set-new-identity text] 300))}]])
|
||||
|
||||
(defn search-input-wrapper-old [search-filter chats-empty]
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:search/home-filter-changed nil])
|
||||
:on-blur (fn []
|
||||
(when chats-empty
|
||||
(re-frame/dispatch [:search/home-filter-changed nil]))
|
||||
(re-frame/dispatch [::new-chat/clear-new-identity]))
|
||||
:on-focus (fn [search-filter]
|
||||
(when-not search-filter
|
||||
(re-frame/dispatch [:search/home-filter-changed ""])
|
||||
(re-frame/dispatch [::new-chat/clear-new-identity])))
|
||||
:on-change (fn [text]
|
||||
(re-frame/dispatch [:search/home-filter-changed text])
|
||||
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
|
||||
(debounce/debounce-and-dispatch [:new-chat/set-new-identity text] 300))}]])
|
||||
|
||||
(defn start-suggestion [search-value]
|
||||
(let [{:keys [state ens-name public-key]}
|
||||
@(re-frame/subscribe [:contacts/new-identity])
|
||||
|
@ -114,6 +139,23 @@
|
|||
[sheets/actions home-item])}])}]
|
||||
[communities.views/community-home-list-item home-item]))
|
||||
|
||||
(defn render-fn-old [{:keys [chat-id] :as home-item}]
|
||||
;; We use `chat-id` to distinguish communities from chats
|
||||
(if chat-id
|
||||
[inner-item/home-list-item-old
|
||||
home-item
|
||||
{:on-press (fn []
|
||||
(re-frame/dispatch [:dismiss-keyboard])
|
||||
(if (and @config/new-ui-enabled? platform/android?)
|
||||
(re-frame/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
|
||||
(re-frame/dispatch [:chat.ui/navigate-to-chat chat-id]))
|
||||
(re-frame/dispatch [:search/home-filter-changed nil])
|
||||
(re-frame/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
|
||||
:on-long-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
[sheets/actions home-item])}])}]
|
||||
[communities.views/community-home-list-item home-item]))
|
||||
|
||||
(defn chat-list-key-fn [item]
|
||||
(or (:chat-id item) (:id item)))
|
||||
|
||||
|
@ -145,6 +187,31 @@
|
|||
[home-tooltip-view]
|
||||
[react/view {:height 68}])}])))
|
||||
|
||||
(views/defview communities-and-chats-old []
|
||||
(views/letsubs [{:keys [items search-filter]} [:home-items]
|
||||
hide-home-tooltip? [:hide-home-tooltip?]]
|
||||
(if (and (empty? items)
|
||||
(empty? search-filter)
|
||||
hide-home-tooltip?
|
||||
(not @search-active?))
|
||||
[welcome-blank-page]
|
||||
[list/flat-list
|
||||
{:key-fn chat-list-key-fn
|
||||
:getItemLayout get-item-layout
|
||||
:on-end-reached #(re-frame/dispatch [:chat.ui/show-more-chats])
|
||||
:keyboard-should-persist-taps :always
|
||||
:data items
|
||||
:render-fn render-fn-old
|
||||
:header [:<>
|
||||
(when (or (seq items) @search-active? (seq search-filter))
|
||||
[search-input-wrapper-old search-filter (empty? items)])
|
||||
(when (and (empty? items)
|
||||
(or @search-active? (seq search-filter)))
|
||||
[start-suggestion search-filter])]
|
||||
:footer (if (and (not hide-home-tooltip?) (not @search-active?))
|
||||
[home-tooltip-view]
|
||||
[react/view {:height 68}])}])))
|
||||
|
||||
(views/defview chats-list []
|
||||
(views/letsubs [loading? [:chats/loading?]]
|
||||
[:<>
|
||||
|
@ -154,6 +221,15 @@
|
|||
[react/activity-indicator {:animating true}]]
|
||||
[communities-and-chats])]))
|
||||
|
||||
(views/defview chats-list-old []
|
||||
(views/letsubs [loading? [:chats/loading?]]
|
||||
[:<>
|
||||
[connectivity/loading-indicator]
|
||||
(if loading?
|
||||
[react/view {:flex 1 :align-items :center :justify-content :center}
|
||||
[react/activity-indicator {:animating true}]]
|
||||
[communities-and-chats-old])]))
|
||||
|
||||
(views/defview plus-button []
|
||||
(views/letsubs [logging-in? [:multiaccounts/login]]
|
||||
[components.plus-button/plus-button
|
||||
|
@ -162,7 +238,33 @@
|
|||
:loading logging-in?
|
||||
:accessibility-label :new-chat-button}]))
|
||||
|
||||
(views/defview plus-button-old []
|
||||
(views/letsubs [logging-in? [:multiaccounts/login]]
|
||||
[components.plus-button/plus-button-old
|
||||
{:on-press (when-not logging-in?
|
||||
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
|
||||
:loading logging-in?
|
||||
:accessibility-label :new-chat-button}]))
|
||||
|
||||
(views/defview notifications-button []
|
||||
(views/letsubs [notif-count [:activity.center/notifications-count]]
|
||||
[react/view
|
||||
[quo2.button/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:style {:margin-left 12}
|
||||
:accessibility-label :notifications-button
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
|
||||
(re-frame/dispatch [:navigate-to :notifications-center]))}
|
||||
[icons/icon :main-icons/notification2 {:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}]]
|
||||
(when (pos? notif-count)
|
||||
[react/view {:style (merge (styles/counter-public-container) {:top 5 :right 5})
|
||||
:pointer-events :none}
|
||||
[react/view {:style styles/counter-public
|
||||
:accessibility-label :notifications-unread-badge}]])]))
|
||||
|
||||
(views/defview notifications-button-old []
|
||||
(views/letsubs [notif-count [:activity.center/notifications-count]]
|
||||
[react/view
|
||||
[quo/button {:type :icon
|
||||
|
@ -179,19 +281,57 @@
|
|||
[react/view {:style styles/counter-public
|
||||
:accessibility-label :notifications-unread-badge}]])]))
|
||||
|
||||
(defn qr-button []
|
||||
[quo2.button/button {:type :grey
|
||||
:accessibility-label "qr-button"
|
||||
:size 32
|
||||
:width 32
|
||||
:style {:margin-left 12}
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [::qr-scanner/scan-code
|
||||
{:handler ::qr-scanner/on-scan-success}]))}
|
||||
[icons/icon :main-icons/qr2 {:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}]])
|
||||
|
||||
(defn scan-button []
|
||||
[quo2.button/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:accessibility-label "scan-button"
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [::qr-scanner/scan-code
|
||||
{:handler ::qr-scanner/on-scan-success}]))}
|
||||
[icons/icon :main-icons/scan2 {:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}]])
|
||||
|
||||
(views/defview profile-button []
|
||||
(views/letsubs [{:keys [public-key preferred-name emoji]} [:multiaccount]]
|
||||
[react/view
|
||||
[chat-icon.screen/emoji-chat-icon-view public-key false preferred-name emoji
|
||||
{:size 28
|
||||
:chat-icon chat-icon.styles/chat-icon-chat-list}]]))
|
||||
|
||||
(defn home []
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
[react/keyboard-avoiding-view {:style {:flex 1 :padding-top (:top insets)}
|
||||
:ignore-offset true}
|
||||
[topbar/topbar {:title (i18n/label :t/chat)
|
||||
:navigation :none
|
||||
:right-component [react/view {:flex-direction :row :margin-right 16}
|
||||
[connectivity/connectivity-button]
|
||||
[notifications-button]]}]
|
||||
[chats-list]
|
||||
[plus-button]
|
||||
[tabbar/tabs-counts-subscriptions]])])
|
||||
[react/keyboard-avoiding-view {:style {:flex 1 :background-color (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/switcher-background)}
|
||||
:ignore-offset true}
|
||||
[topbar/topbar {:navigation :none
|
||||
:use-insets true
|
||||
:background (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/switcher-background)
|
||||
:left-component [react/view {:flex-direction :row :margin-left 16}
|
||||
[profile-button]]
|
||||
:right-component [react/view {:flex-direction :row :margin-right 16}
|
||||
[scan-button]
|
||||
[qr-button]
|
||||
[notifications-button]]
|
||||
:border-bottom false}]
|
||||
[react/view {:flex-direction :row
|
||||
:justify-content :space-between
|
||||
:align-items :center
|
||||
:margin-horizontal 16
|
||||
:margin-top 15
|
||||
:margin-bottom 8}
|
||||
[quo2.text/text {:size :heading-1 :weight :semi-bold} (i18n/label :t/messages)]
|
||||
[plus-button]]
|
||||
[chats-list]
|
||||
[tabbar/tabs-counts-subscriptions]])
|
||||
|
||||
(defn home-old []
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}
|
||||
|
@ -200,7 +340,7 @@
|
|||
:navigation :none
|
||||
:right-component [react/view {:flex-direction :row :margin-right 16}
|
||||
[connectivity/connectivity-button]
|
||||
[notifications-button]]}]
|
||||
[chats-list]
|
||||
[plus-button]
|
||||
[tabbar/tabs-counts-subscriptions]])
|
||||
[notifications-button-old]]}]
|
||||
[chats-list-old]
|
||||
[plus-button-old]
|
||||
[tabbar/tabs-counts-subscriptions]])
|
|
@ -12,7 +12,10 @@
|
|||
[status-im.ui.components.icons.icons :as icons]
|
||||
[status-im.utils.core :as utils]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]))
|
||||
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]
|
||||
[quo2.components.text :as quo2.text]
|
||||
[status-im.utils.utils :as utils.utils]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(defn preview-label [label-key label-fn]
|
||||
[react/text {:style styles/last-message-text
|
||||
|
@ -116,6 +119,22 @@
|
|||
(defn unviewed-indicator [{:keys [unviewed-mentions-count
|
||||
unviewed-messages-count
|
||||
public?]}]
|
||||
(when (pos? unviewed-messages-count)
|
||||
[react/view {:position :absolute :right 16}
|
||||
(cond
|
||||
(and public? (not (pos? unviewed-mentions-count)))
|
||||
[react/view {:style styles/public-unread
|
||||
:accessibility-label :unviewed-messages-public}]
|
||||
|
||||
(and public? (pos? unviewed-mentions-count))
|
||||
[badge/message-counter unviewed-mentions-count]
|
||||
|
||||
:else
|
||||
[badge/message-counter unviewed-messages-count])]))
|
||||
|
||||
(defn unviewed-indicator-old [{:keys [unviewed-mentions-count
|
||||
unviewed-messages-count
|
||||
public?]}]
|
||||
(when (pos? unviewed-messages-count)
|
||||
[react/view {:position :absolute :right 16 :bottom 12}
|
||||
(cond
|
||||
|
@ -151,6 +170,23 @@
|
|||
[icons/icon :main-icons/tiny-new-contact (icon-style)]))
|
||||
|
||||
(defn chat-item-title [chat-id muted group-chat chat-name edit?]
|
||||
[quo2.text/text {:weight :semi-bold
|
||||
:color (when muted :secondary)
|
||||
:accessibility-label :chat-name-text
|
||||
:ellipsize-mode :tail
|
||||
:number-of-lines 1
|
||||
:style {:position :absolute
|
||||
:left 72
|
||||
:top 10
|
||||
:right (if edit? 50 90)}}
|
||||
(if group-chat
|
||||
(utils/truncate-str chat-name 30)
|
||||
;; This looks a bit odd, but I would like only to subscribe
|
||||
;; if it's a one-to-one. If wrapped in a component styling
|
||||
;; won't be applied correctly.
|
||||
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))])
|
||||
|
||||
(defn chat-item-title-old [chat-id muted group-chat chat-name edit?]
|
||||
[quo/text {:weight :medium
|
||||
:color (when muted :secondary)
|
||||
:accessibility-label :chat-name-text
|
||||
|
@ -168,12 +204,62 @@
|
|||
(first @(re-frame/subscribe [:contacts/contact-two-names-by-identity chat-id])))])
|
||||
|
||||
(defn home-list-item [home-item opts]
|
||||
(let [{:keys [chat-id chat-name color group-chat muted emoji highlight edit? public? unviewed-messages-count contacts]} home-item
|
||||
background-color (when highlight (colors/get-color :interactive-02))]
|
||||
[react/touchable-opacity (merge {:style {:height 64 :background-color background-color}} opts)
|
||||
[:<>
|
||||
(when (pos? unviewed-messages-count)
|
||||
[react/view {:position :absolute :top 2 :left 8 :right 8 :bottom 2 :border-radius 16 :background-color quo2.colors/primary-50-opa-5}])
|
||||
[chat-icon.screen/emoji-chat-icon-view chat-id group-chat chat-name emoji
|
||||
{:container (assoc chat-icon.styles/container-chat-list
|
||||
:top 12 :left 20 :position :absolute)
|
||||
:size 32
|
||||
:chat-icon chat-icon.styles/chat-icon-chat-list
|
||||
:default-chat-icon (chat-icon.styles/default-chat-icon-chat-list color)
|
||||
:default-chat-icon-text (if (string/blank? emoji)
|
||||
(chat-icon.styles/default-chat-icon-text 40)
|
||||
(chat-icon.styles/emoji-chat-icon-text 40))}]
|
||||
[chat-item-title chat-id muted group-chat chat-name edit?]
|
||||
(when-not edit?
|
||||
[react/view {:height "100%" :justify-content :center}
|
||||
[unviewed-indicator home-item]])
|
||||
[react/view {:position :absolute :left 72 :top 32 :right 80}
|
||||
(if public?
|
||||
[quo2.text/text {:color :secondary
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle
|
||||
:weight :medium
|
||||
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-50 quo2.colors/neutral-40)}}
|
||||
(i18n/label :t/public)]
|
||||
(if group-chat
|
||||
[react/view {:flex-direction :row
|
||||
:flex 1
|
||||
:padding-right 16
|
||||
:align-items :center}
|
||||
[icons/icon :main-icons/tiny-group2
|
||||
{:width 16
|
||||
:height 16
|
||||
:no-color true
|
||||
:container-style {:width 16
|
||||
:height 16
|
||||
:margin-right 4}}]
|
||||
[quo2.text/text {:weight :medium
|
||||
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-50 quo2.colors/neutral-40)}}
|
||||
(i18n/label :t/members-count {:count (count contacts)})]]
|
||||
[quo2.text/text {:monospace true
|
||||
:weight :medium
|
||||
:style {:color (quo2.colors/theme-colors quo2.colors/neutral-50 quo2.colors/neutral-40)}
|
||||
:number-of-lines 1
|
||||
:ellipsize-mode :middle}
|
||||
(utils.utils/get-shortened-address chat-id)]))]]]))
|
||||
|
||||
(defn home-list-item-old [home-item opts]
|
||||
(let [{:keys [chat-id chat-name color group-chat public? timestamp last-message muted emoji highlight edit?]} home-item
|
||||
background-color (when highlight (colors/get-color :interactive-02))]
|
||||
[react/touchable-opacity (merge {:style {:height 64 :background-color background-color}} opts)
|
||||
[:<>
|
||||
[chat-item-icon muted (and group-chat (not public?)) (and group-chat public?)]
|
||||
[chat-icon.screen/emoji-chat-icon-view chat-id group-chat chat-name emoji
|
||||
[chat-icon.screen/emoji-chat-icon-view-old chat-id group-chat chat-name emoji
|
||||
{:container (assoc chat-icon.styles/container-chat-list
|
||||
:top 12 :left 16 :position :absolute)
|
||||
:size 40
|
||||
|
@ -182,7 +268,7 @@
|
|||
:default-chat-icon-text (if (string/blank? emoji)
|
||||
(chat-icon.styles/default-chat-icon-text 40)
|
||||
(chat-icon.styles/emoji-chat-icon-text 40))}]
|
||||
[chat-item-title chat-id muted group-chat chat-name edit?]
|
||||
[chat-item-title-old chat-id muted group-chat chat-name edit?]
|
||||
(when-not edit?
|
||||
[:<>
|
||||
[react/text {:style styles/datetime-text
|
||||
|
@ -192,5 +278,5 @@
|
|||
(memo-timestamp (if (pos? (:whisper-timestamp last-message))
|
||||
(:whisper-timestamp last-message)
|
||||
timestamp))]
|
||||
[unviewed-indicator home-item]])
|
||||
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]]]))
|
||||
[unviewed-indicator-old home-item]])
|
||||
[message-content-text (select-keys last-message [:content :content-type :community-id]) true]]]))
|
|
@ -13,7 +13,7 @@
|
|||
[status-im.ui.screens.profile.components.styles :as profile.components.styles]
|
||||
[status-im.ui.components.topbar :as topbar]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.ui.screens.chat.message.message-old :as message]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.chat.utils :as chat.utils]
|
||||
[status-im.utils.debounce :as debounce])
|
||||
|
@ -109,7 +109,7 @@
|
|||
:content-type constants/content-type-text}]
|
||||
[react/view {:margin-bottom 8 :margin-right 16}
|
||||
[react/view {:padding-left 72}
|
||||
(chat.utils/format-author contact)]
|
||||
(chat.utils/format-author-old contact)]
|
||||
[react/view {:flex-direction :row :align-items :flex-end}
|
||||
[react/view {:padding-left 16 :padding-top 4}
|
||||
[photos/photo (multiaccounts/displayed-photo contact) {:size 36}]]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.ui.screens.profile.visibility-status.styles
|
||||
(:require [quo.design-system.colors :as colors]))
|
||||
(:require [quo.design-system.colors :as colors]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
(defn visibility-status-button-container []
|
||||
{:background-color (:interactive-02 @colors/theme)
|
||||
|
@ -14,6 +15,14 @@
|
|||
:padding-right 12})
|
||||
|
||||
(defn visibility-status-dot [dot-color size]
|
||||
{:background-color dot-color
|
||||
:width size
|
||||
:height size
|
||||
:border-radius (/ size 2)
|
||||
:border-width 3.5
|
||||
:border-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)})
|
||||
|
||||
(defn visibility-status-dot-old [dot-color size]
|
||||
{:background-color dot-color
|
||||
:width size
|
||||
:height size
|
||||
|
@ -21,8 +30,8 @@
|
|||
:border-width 1
|
||||
:border-color colors/white})
|
||||
|
||||
(defn visibility-status-profile-dot [color size border-width margin-left]
|
||||
(merge (visibility-status-dot color size)
|
||||
(defn visibility-status-profile-dot-old [color size border-width margin-left]
|
||||
(merge (visibility-status-dot-old color size)
|
||||
{:margin-right 6
|
||||
:margin-left margin-left
|
||||
:border-width border-width}))
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
[status-im.utils.handlers :refer [<sub]]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[quo.design-system.colors :as colors]
|
||||
[clojure.string :as string]))
|
||||
[clojure.string :as string]
|
||||
[quo2.foundations.colors :as quo2.colors]))
|
||||
|
||||
;; Specs:
|
||||
;; :visibility-status-automatic
|
||||
|
@ -19,6 +20,26 @@
|
|||
;; Display - Offline forever
|
||||
;; Note: Only send pings if the user interacted with the app in the last x minutes.
|
||||
(def visibility-status-type-data
|
||||
{constants/visibility-status-unknown
|
||||
{:color colors/red
|
||||
:title (i18n/label :t/error)}
|
||||
constants/visibility-status-automatic
|
||||
{:color quo2.colors/color-online
|
||||
:title (i18n/label :t/status-automatic)
|
||||
:subtitle (i18n/label :t/status-automatic-subtitle)}
|
||||
constants/visibility-status-dnd
|
||||
{:color colors/color-dnd
|
||||
:title (i18n/label :t/status-dnd)
|
||||
:subtitle (i18n/label :t/status-dnd-subtitle)}
|
||||
constants/visibility-status-always-online
|
||||
{:color quo2.colors/color-online
|
||||
:title (i18n/label :t/status-always-online)}
|
||||
constants/visibility-status-inactive
|
||||
{:color colors/color-inactive
|
||||
:title (i18n/label :t/status-inactive)
|
||||
:subtitle (i18n/label :t/status-inactive-subtitle)}})
|
||||
|
||||
(def visibility-status-type-data-old
|
||||
{constants/visibility-status-unknown
|
||||
{:color colors/red
|
||||
:title (i18n/label :t/error)}
|
||||
|
@ -63,11 +84,20 @@
|
|||
[{:keys [status-type] :as visibility-status-update} my-icon?]
|
||||
(if my-icon?
|
||||
(if (= status-type constants/visibility-status-inactive)
|
||||
colors/color-inactive colors/color-online)
|
||||
colors/color-inactive quo2.colors/color-online)
|
||||
(let [{:keys [real-status-type]}
|
||||
(calculate-real-status-type-and-time-left visibility-status-update)]
|
||||
(:color (get visibility-status-type-data real-status-type)))))
|
||||
|
||||
(defn dot-color-old
|
||||
[{:keys [status-type] :as visibility-status-update} my-icon?]
|
||||
(if my-icon?
|
||||
(if (= status-type constants/visibility-status-inactive)
|
||||
colors/color-inactive colors/color-online)
|
||||
(let [{:keys [real-status-type]}
|
||||
(calculate-real-status-type-and-time-left visibility-status-update)]
|
||||
(:color (get visibility-status-type-data-old real-status-type)))))
|
||||
|
||||
(defn my-icon? [public-key]
|
||||
(or (string/blank? public-key)
|
||||
(= public-key (<sub [:multiaccount/public-key]))))
|
||||
|
@ -77,16 +107,31 @@
|
|||
(<sub [:multiaccount/current-user-visibility-status])
|
||||
(<sub [:visibility-status-updates/visibility-status-update public-key])))
|
||||
|
||||
(defn icon-visibility-status-dot [public-key container-size identicon?]
|
||||
(defn icon-visibility-status-dot [public-key container-size _]
|
||||
(let [my-icon? (my-icon? public-key)
|
||||
visibility-status-update (visibility-status-update public-key my-icon?)
|
||||
size (/ container-size 2.4)
|
||||
margin -2
|
||||
dot-color (dot-color visibility-status-update my-icon?)
|
||||
accessibility-label (if (= dot-color quo2.colors/color-online)
|
||||
:online-profile-photo-dot
|
||||
:offline-profile-photo-dot)]
|
||||
(merge (styles/visibility-status-dot dot-color size)
|
||||
{:bottom margin
|
||||
:right margin
|
||||
:position :absolute
|
||||
:accessibility-label accessibility-label})))
|
||||
|
||||
(defn icon-visibility-status-dot-old [public-key container-size identicon?]
|
||||
(let [my-icon? (my-icon? public-key)
|
||||
visibility-status-update (visibility-status-update public-key my-icon?)
|
||||
size (/ container-size 4)
|
||||
margin (if identicon? (/ size 6) (/ size 7))
|
||||
dot-color (dot-color visibility-status-update my-icon?)
|
||||
dot-color (dot-color-old visibility-status-update my-icon?)
|
||||
accessibility-label (if (= dot-color colors/color-online)
|
||||
:online-profile-photo-dot
|
||||
:offline-profile-photo-dot)]
|
||||
(merge (styles/visibility-status-dot dot-color size)
|
||||
(merge (styles/visibility-status-dot-old dot-color size)
|
||||
{:bottom margin
|
||||
:right margin
|
||||
:position :absolute
|
||||
|
|
|
@ -36,9 +36,9 @@
|
|||
[border-width margin-left size] (if automatic? [1 -10 12] [0 6 10])]
|
||||
[:<>
|
||||
(when automatic?
|
||||
[rn/view {:style (styles/visibility-status-profile-dot
|
||||
[rn/view {:style (styles/visibility-status-profile-dot-old
|
||||
colors/color-inactive size border-width 6)}])
|
||||
[rn/view {:style (styles/visibility-status-profile-dot
|
||||
[rn/view {:style (styles/visibility-status-profile-dot-old
|
||||
color size border-width margin-left)}]]))
|
||||
|
||||
(defn visibility-status-button [on-press props]
|
||||
|
@ -50,7 +50,7 @@
|
|||
constants/visibility-status-automatic)
|
||||
constants/visibility-status-automatic)
|
||||
status-type)
|
||||
{:keys [color title]} (get utils/visibility-status-type-data status-type)]
|
||||
{:keys [color title]} (get utils/visibility-status-type-data-old status-type)]
|
||||
[rn/touchable-opacity
|
||||
(merge
|
||||
{:on-press on-press
|
||||
|
@ -97,7 +97,7 @@
|
|||
|
||||
(defn status-option [{:keys [request-close status-type]}]
|
||||
(let [{:keys [color title subtitle]}
|
||||
(get utils/visibility-status-type-data status-type)]
|
||||
(get utils/visibility-status-type-data-old status-type)]
|
||||
[rn/touchable-opacity {:style {:padding 6}
|
||||
:accessibility-label :visibility-status-option
|
||||
:on-press #(status-option-pressed
|
||||
|
|
|
@ -224,7 +224,7 @@
|
|||
:hardwareBackButton {:dismissModalOnPress false
|
||||
:popStackOnPress false}
|
||||
:topBar {:visible false}}
|
||||
:component chat/chat}
|
||||
:component chat/chat-old}
|
||||
|
||||
;Pinned messages
|
||||
{:name :chat-pinned-messages
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(ns status-im.ui.screens.status.views
|
||||
(:require [status-im.ui.screens.chat.message.message :as message]
|
||||
(:require [status-im.ui.screens.chat.message.message-old :as message]
|
||||
[status-im.ui.components.react :as react]
|
||||
[quo.design-system.colors :as colors]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
|
@ -210,5 +210,5 @@
|
|||
:on-scroll-to-index-failed #()
|
||||
:header [react/view {:height 8}]
|
||||
:footer [react/view {:height 68}]}]))
|
||||
[components.plus-button/plus-button
|
||||
[components.plus-button/plus-button-old
|
||||
{:on-press #(re-frame/dispatch [:open-modal :my-status])}]]))
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
(let [search-filter @(re-frame/subscribe [:search/recipient-filter])]
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:search/recipient-filter-changed nil])
|
||||
|
|
|
@ -80,7 +80,7 @@
|
|||
[react/view {:flex 1}
|
||||
[react/view {:padding-horizontal 16
|
||||
:padding-vertical 10}
|
||||
[search-input/search-input
|
||||
[search-input/search-input-old
|
||||
{:search-active? search-active?
|
||||
:search-filter search-filter
|
||||
:on-cancel #(re-frame/dispatch [:search/token-filter-changed nil])
|
||||
|
|
|
@ -55,7 +55,7 @@
|
|||
(i18n/label :t/select-token-to-receive))
|
||||
:modal? true}]
|
||||
|
||||
[search-input/search-input
|
||||
[search-input/search-input-old
|
||||
{:search-active? true}]
|
||||
|
||||
[react/scroll-view
|
||||
|
|
|
@ -1756,5 +1756,6 @@
|
|||
"mutual-contact-requests": "Mutual contact requests",
|
||||
"pending": "Pending",
|
||||
"negative": "Negative",
|
||||
"positive": "Positive"
|
||||
"positive": "Positive",
|
||||
"public": "Public"
|
||||
}
|
||||
|
|