Skip to content

Commit 3e9d5dd

Browse files
authored
Reimplement composer: add reply (#15736)
* feat: add composer reply
1 parent 2eed30b commit 3e9d5dd

File tree

15 files changed

+291
-72
lines changed

15 files changed

+291
-72
lines changed
103 Bytes
Loading
154 Bytes
Loading

src/status_im/chat/models/input.cljs

-6
Original file line numberDiff line numberDiff line change
@@ -51,12 +51,6 @@
5151
(let [current-chat-id (or chat-id (:current-chat-id db))]
5252
{:db (assoc-in db [:chat/inputs current-chat-id :input-maximized?] maximized?)}))
5353

54-
(rf/defn set-input-refocus
55-
{:events [:chat.ui/set-input-refocus]}
56-
[{db :db} refocus? chat-id]
57-
(let [current-chat-id (or chat-id (:current-chat-id db))]
58-
{:db (assoc-in db [:chat/inputs current-chat-id :input-refocus?] refocus?)}))
59-
6054
(rf/defn select-mention
6155
{:events [:chat.ui/select-mention]}
6256
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]

src/status_im2/config.cljs

+2
Original file line numberDiff line numberDiff line change
@@ -158,3 +158,5 @@
158158
["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im"]})
159159

160160
(def default-kdf-iterations 3200)
161+
162+
(def ^:const new-composer-enabled? false)

src/status_im2/contexts/chat/bottom_sheet_composer/actions/view.cljs

+5-9
Original file line numberDiff line numberDiff line change
@@ -88,17 +88,13 @@
8888

8989
(defn open-photo-selector
9090
[{:keys [input-ref]}
91-
{:keys [focused?]}
9291
{:keys [height]}
9392
insets]
9493
(permissions/request-permissions
9594
{:permissions [:read-external-storage :write-external-storage]
9695
:on-allowed (fn []
97-
(when platform/android?
98-
(when @focused?
99-
(rf/dispatch [:chat.ui/set-input-refocus true]))
100-
(when @input-ref
101-
(.blur ^js @input-ref)))
96+
(when (and platform/android? @input-ref)
97+
(.blur ^js @input-ref))
10298
(rf/dispatch [:chat.ui/set-input-content-height
10399
(reanimated/get-shared-value height)])
104100
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
@@ -108,9 +104,9 @@
108104
:t/external-storage-denied)))}))
109105

110106
(defn image-button
111-
[props state animations insets]
107+
[props animations insets]
112108
[quo/button
113-
{:on-press #(open-photo-selector props state animations insets)
109+
{:on-press #(open-photo-selector props animations insets)
114110
:icon true
115111
:type :outline
116112
:size 32
@@ -141,7 +137,7 @@
141137
[rn/view {:style style/actions-container}
142138
[rn/view {:style {:flex-direction :row}}
143139
[camera-button]
144-
[image-button props state animations insets]
140+
[image-button props animations insets]
145141
[reaction-button]
146142
[format-button]]
147143
[send-button props state animations window-height images?]

src/status_im2/contexts/chat/bottom_sheet_composer/constants.cljs

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
(def ^:const images-container-height 76)
1919

20+
(def ^:const reply-container-height 32)
21+
2022
(def ^:const extra-content-offset (if platform/ios? 6 0))
2123

2224
(def ^:const content-change-threshold 10)

src/status_im2/contexts/chat/bottom_sheet_composer/effects.cljs

+21-18
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
[react-native.reanimated :as reanimated]
66
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
77
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
8-
[utils.re-frame :as rf]
98
[utils.number :as utils.number]))
109

1110
(defn reenter-screen-effect
@@ -29,13 +28,6 @@
2928
(reanimated/set-shared-value saved-height max-height)
3029
(reanimated/set-shared-value last-height max-height)))
3130

32-
(defn refocus-effect
33-
[{:keys [input-ref]}
34-
{:keys [input-refocus?]}]
35-
(when (and input-refocus? @input-ref)
36-
(.focus ^js @input-ref)
37-
(rf/dispatch [:chat.ui/set-input-refocus false])))
38-
3931
(defn layout-effect
4032
[{:keys [lock-layout?]}]
4133
(when-not @lock-layout?
@@ -56,17 +48,29 @@
5648
(reanimated/set-shared-value background-y 0)
5749
(reanimated/animate opacity 1)))
5850

59-
(defn images-effect
51+
(defn images-or-reply-effect
6052
[{:keys [container-opacity]}
61-
images?]
62-
(when images?
63-
(reanimated/animate container-opacity 1)))
53+
{:keys [replying? sending-images? input-ref]}
54+
images? reply?]
55+
(when (or images? reply?)
56+
(reanimated/animate container-opacity 1))
57+
(when (and (not @sending-images?) images? @input-ref)
58+
(.focus ^js @input-ref)
59+
(reset! sending-images? true))
60+
(when (and (not @replying?) reply? @input-ref)
61+
(.focus ^js @input-ref)
62+
(reset! replying? true))
63+
(when-not images?
64+
(reset! sending-images? false))
65+
(when-not reply?
66+
(reset! replying? false)))
6467

6568
(defn empty-effect
6669
[{:keys [text-value maximized? focused?]}
6770
{:keys [container-opacity]}
68-
images?]
69-
(when (and (empty? @text-value) (not images?) (not @maximized?) (not @focused?))
71+
images?
72+
reply?]
73+
(when (and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?))
7074
(reanimated/animate-delay container-opacity constants/empty-opacity 200)))
7175

7276
(defn component-will-unmount
@@ -76,17 +80,16 @@
7680
(.remove ^js @keyboard-frame-listener))
7781

7882
(defn initialize
79-
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images?]
83+
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply?]
8084
(rn/use-effect
8185
(fn []
8286
(maximized-effect state animations dimensions chat-input)
83-
(refocus-effect props chat-input)
8487
(reenter-screen-effect state dimensions chat-input)
8588
(layout-effect state)
8689
(kb-default-height-effect state)
8790
(background-effect state animations dimensions chat-input)
88-
(images-effect animations images?)
89-
(empty-effect state animations images?)
91+
(images-or-reply-effect animations props images? reply?)
92+
(empty-effect state animations images? reply?)
9093
(kb/add-kb-listeners props state animations dimensions keyboard-height)
9194
#(component-will-unmount props))
9295
[max-height]))

src/status_im2/contexts/chat/bottom_sheet_composer/handlers.cljs

+3-2
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
maximized?]}
3535
{:keys [height saved-height last-height gradient-opacity container-opacity opacity background-y]}
3636
{:keys [lines content-height max-height window-height]}
37-
images]
37+
images
38+
reply]
3839
(let [min-height (utils/get-min-height lines)
3940
reopen-height (utils/calc-reopen-height text-value min-height content-height saved-height)]
4041
(reset! focused? false)
@@ -43,7 +44,7 @@
4344
(reanimated/set-shared-value saved-height min-height)
4445
(reanimated/animate opacity 0)
4546
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)
46-
(when (and (empty? @text-value) (empty? images))
47+
(when (utils/empty-input? @text-value images reply)
4748
(reanimated/animate container-opacity constants/empty-opacity))
4849
(reanimated/animate gradient-opacity 0)
4950
(reset! lock-selection? true)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
(ns status-im2.contexts.chat.bottom-sheet-composer.reply.style)
2+
3+
(defn reply-content
4+
[pin?]
5+
{:padding-right (when-not pin? 10)
6+
:flex 1
7+
:flex-direction :row})
8+
9+
(defn quoted-message
10+
[pin?]
11+
(merge {:flex-direction :row
12+
:flex 1
13+
:align-items :center}
14+
(when-not pin?
15+
{:left 22
16+
:margin-right 22})))
17+
18+
(def reply-from
19+
{:flex-direction :row
20+
:align-items :center})
21+
22+
(def message-author-text
23+
{:margin-left 4})
24+
25+
(def message-text
26+
{:text-transform :none
27+
:margin-left 4
28+
:margin-top 2
29+
:flex 1})
30+
31+
(def gradient
32+
{:position :absolute
33+
:right 0
34+
:top 0
35+
:bottom 0
36+
:width "50%"})
37+
38+
(def reply-deleted-message
39+
{:text-transform :none
40+
:margin-left 4
41+
:margin-top 2})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
(ns status-im2.contexts.chat.bottom-sheet-composer.reply.view
2+
(:require [clojure.string :as string]
3+
[react-native.core :as rn]
4+
[react-native.reanimated :as reanimated]
5+
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
6+
[utils.i18n :as i18n]
7+
[quo2.core :as quo]
8+
[quo2.foundations.colors :as colors]
9+
[status-im2.constants :as constant]
10+
[status-im.ethereum.stateofus :as stateofus]
11+
[utils.re-frame :as rf]
12+
[status-im2.contexts.chat.bottom-sheet-composer.reply.style :as style]
13+
[react-native.linear-gradient :as linear-gradient]))
14+
15+
(defn get-quoted-text-with-mentions
16+
[parsed-text]
17+
(string/join
18+
(mapv (fn [{:keys [type literal children]}]
19+
(cond
20+
(= type "paragraph")
21+
(get-quoted-text-with-mentions children)
22+
23+
(= type "mention")
24+
(rf/sub [:messages/resolve-mention literal])
25+
26+
(seq children)
27+
(get-quoted-text-with-mentions children)
28+
29+
:else
30+
literal))
31+
parsed-text)))
32+
33+
(defn format-author
34+
[contact-name]
35+
(let [author (if (or (= (first contact-name) "@")
36+
;; in case of replies
37+
(= (second contact-name) "@"))
38+
(or (stateofus/username contact-name)
39+
(subs contact-name 0 81))
40+
contact-name)]
41+
author))
42+
43+
(defn format-reply-author
44+
[from username current-public-key]
45+
(or (and (= from current-public-key)
46+
(i18n/label :t/You))
47+
(when username (format-author username))))
48+
49+
(defn reply-deleted-message
50+
[]
51+
[rn/view
52+
{:style {:flex-direction :row
53+
:align-items :center}}
54+
[quo/icon :i/sad-face {:size 16}]
55+
[quo/text
56+
{:number-of-lines 1
57+
:size :label
58+
:weight :regular
59+
:accessibility-label :quoted-message
60+
:style style/reply-deleted-message}
61+
(i18n/label :t/message-deleted)]])
62+
63+
(defn reply-from
64+
[{:keys [from contact-name current-public-key]}]
65+
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
66+
contact (rf/sub [:contacts/contact-by-address from])
67+
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))]
68+
[rn/view {:style style/reply-from}
69+
[quo/user-avatar
70+
{:full-name display-name
71+
:profile-picture photo-path
72+
:status-indicator? false
73+
:size :xxxs}]
74+
[quo/text
75+
{:weight :semi-bold
76+
:size :paragraph-2
77+
:number-of-lines 1
78+
:style style/message-author-text}
79+
(format-reply-author from contact-name current-public-key)]]))
80+
81+
(defn reply-message
82+
[{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?
83+
album-images-count]}
84+
in-chat-input? pin? recording-audio?]
85+
(let [contact-name (rf/sub [:contacts/contact-name-by-identity from])
86+
current-public-key (rf/sub [:multiaccount/public-key])
87+
content-type (or content-type contentType)]
88+
[rn/view
89+
{:style {:flex-direction :row
90+
:height (when-not pin? 24)
91+
:accessibility-label :reply-message}}
92+
[rn/view {:style (style/reply-content pin?)}
93+
(when-not pin?
94+
[quo/icon :i/connector
95+
{:size 16
96+
:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
97+
:container-style {:position :absolute :left 0 :bottom -4 :width 16 :height 16}}])
98+
(if (or deleted? deleted-for-me?)
99+
[rn/view {:style (style/quoted-message pin?)}
100+
[reply-deleted-message]]
101+
[rn/view {:style (style/quoted-message pin?)}
102+
[reply-from
103+
{:from from
104+
:identicon identicon
105+
:contact-name contact-name
106+
:current-public-key current-public-key}]
107+
[quo/text
108+
{:number-of-lines 1
109+
:size :label
110+
:weight :regular
111+
:accessibility-label :quoted-message
112+
:ellipsize-mode :tail
113+
:style (merge
114+
style/message-text
115+
(when (or (= constant/content-type-image content-type)
116+
(= constant/content-type-sticker content-type)
117+
(= constant/content-type-audio content-type))
118+
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}))}
119+
(case (or content-type contentType)
120+
constant/content-type-image (if album-images-count
121+
(i18n/label :t/images-albums-count
122+
{:album-images-count album-images-count})
123+
(i18n/label :t/image))
124+
constant/content-type-sticker (i18n/label :t/sticker)
125+
constant/content-type-audio (i18n/label :t/audio)
126+
(get-quoted-text-with-mentions (or parsed-text (:parsed-text content))))]])]
127+
(when (and in-chat-input? (not recording-audio?))
128+
[quo/button
129+
{:icon true
130+
:type :outline
131+
:size 24
132+
:on-press #(rf/dispatch [:chat.ui/cancel-message-reply])}
133+
:i/close])
134+
(when (and in-chat-input? recording-audio?)
135+
[linear-gradient/linear-gradient
136+
{:colors [(colors/theme-colors colors/white-opa-0 colors/neutral-90-opa-0)
137+
(colors/theme-colors colors/white colors/neutral-90)]
138+
:start {:x 0 :y 0}
139+
:end {:x 0.7 :y 0}
140+
:style style/gradient}])]))
141+
142+
(defn- f-view
143+
[]
144+
(let [reply (rf/sub [:chats/reply-message])
145+
height (reanimated/use-shared-value (if reply constants/reply-container-height 0))]
146+
(rn/use-effect #(reanimated/animate height (if reply constants/reply-container-height 0)) [reply])
147+
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
148+
(when reply [reply-message reply true false false])]))
149+
150+
(defn view
151+
[]
152+
[:f> f-view])

src/status_im2/contexts/chat/bottom_sheet_composer/style.cljs

+4-4
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]))
77

88
(defn shadow
9-
[lines]
9+
[elevation?]
1010
(if platform/ios?
1111
{:shadow-radius 20
1212
:shadow-opacity (colors/theme-colors 0.1 0.7)
1313
:shadow-color colors/neutral-100
1414
:shadow-offset {:width 0 :height (colors/theme-colors -4 -8)}}
15-
{:elevation (if (> lines 1) 10 0)}))
15+
{:elevation (if elevation? 10 0)}))
1616

1717
(defn sheet-container
18-
[insets opacity lines]
18+
[insets opacity elevation?]
1919
(reanimated/apply-animations-to-style
2020
{:opacity opacity}
2121
(merge
@@ -29,7 +29,7 @@
2929
:background-color (colors/theme-colors colors/white colors/neutral-95)
3030
:z-index 3
3131
:padding-bottom (:bottom insets)}
32-
(shadow lines))))
32+
(shadow elevation?))))
3333

3434
(def bar-container
3535
{:height constants/bar-container-height

0 commit comments

Comments
 (0)