Skip to content

Composer collapsing when editing canceled/done #17785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 26 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
b84561b
fix: composer height when entering and canceling edit
clauxx Nov 2, 2023
99250ea
fix: blur the composer input when canceling edit
clauxx Nov 2, 2023
f86fde2
Merge branch 'develop' into 17433-composer-expanded-on-cancel
clauxx Nov 2, 2023
ec5c580
fix: focusing animation and composer height after blur
clauxx Nov 3, 2023
7d69fa9
fix: input height when canceling edit while unfocused
clauxx Nov 3, 2023
ba4d618
Merge branch 'develop' into 17433-composer-expanded-on-cancel
clauxx Nov 6, 2023
7ad8165
ref: removed arbitrary keyboard check
clauxx Nov 6, 2023
8c9c93a
fix: moved edit-mentions logic to use-edit to fix unresolved mention
clauxx Nov 6, 2023
1e0664a
fix: composer edit should put the cursor at the end
clauxx Nov 7, 2023
cb9ae2a
Merge branch 'develop' into 17433-composer-expanded-on-cancel
clauxx Nov 7, 2023
a175f3d
fix: (potentially) fixing the mention not resolved during edit
clauxx Nov 9, 2023
2a3b4aa
fix: emoji-kb handler changing the height when default kb appears
clauxx Nov 9, 2023
bb02d86
Fix text content when editing and reentering chat
ibrkhalil Nov 11, 2023
964b196
prevent composer when focusing on opening chat with edit/reply
ibrkhalil Nov 11, 2023
b9f5f73
clean
ibrkhalil Nov 11, 2023
3bbaee2
Clauxx comments
ibrkhalil Nov 11, 2023
abecc38
Apply for reply
ibrkhalil Nov 11, 2023
3ebf345
Lintil soup = yummy
ibrkhalil Nov 13, 2023
17a8824
refactor variable name
ibrkhalil Nov 13, 2023
4fc07bd
Extract the focusing logic from the data setting logic
ibrkhalil Nov 15, 2023
a4568e5
Edge case
ibrkhalil Nov 15, 2023
6397f3e
Merge remote-tracking branch 'origin/17825' into 17433-composer-expan…
clauxx Nov 16, 2023
6940ccd
fix: composer mention key & edit re-enter issues
clauxx Nov 16, 2023
97e7d46
fix: reply cancel input blur and smooth reply focus
clauxx Nov 16, 2023
b41760e
Merge branch 'develop' into 17433-composer-expanded-on-cancel
clauxx Nov 16, 2023
cdd3859
Merge branch 'develop' into 17433-composer-expanded-on-cancel
clauxx Nov 16, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/status_im/chat/models/input.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -107,14 +107,15 @@
[{:keys [db] :as cofx} message]
(let [current-chat-id (:current-chat-id db)
text (get-in message [:content :text])]
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))
:dispatch [:mention/to-input-field text current-chat-id]}))
{:db (-> db
(assoc-in [:chat/inputs current-chat-id :metadata :editing-message]
message)
(assoc-in [:chat/inputs current-chat-id :metadata :responding-to-message] nil)
(update-in [:chat/inputs current-chat-id :metadata]
dissoc
:sending-image))
:dispatch-n [[:chat.ui/set-chat-input-text nil current-chat-id]
[:mention/to-input-field text current-chat-id]]}))

(rf/defn show-contact-request-input
"Sets reference to previous chat message and focuses on input"
Expand Down
14 changes: 6 additions & 8 deletions src/status_im2/contexts/chat/composer/edit/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
[utils.re-frame :as rf]))

(defn edit-message
[state]
[{:keys [text-value input-ref]}]
[rn/view
{:style style/container
:accessibility-label :edit-message}
Expand All @@ -30,20 +30,18 @@
{:size 24
:icon-only? true
:accessibility-label :edit-cancel-button
:on-press (fn []
(utils/cancel-edit-message state)
(rf/dispatch [:chat.ui/cancel-message-edit]))
:on-press #(utils/cancel-edit-message text-value input-ref)
:type :outline}
:i/close]])

(defn- f-view
[state]
[props]
(let [edit (rf/sub [:chats/edit-message])
height (reanimated/use-shared-value (if edit constants/edit-container-height 0))]
(rn/use-effect #(reanimated/animate height (if edit constants/edit-container-height 0)) [edit])
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
(when edit [edit-message state])]))
(when edit [edit-message props])]))

(defn view
[state]
[:f> f-view state])
[props]
[:f> f-view props])
84 changes: 47 additions & 37 deletions src/status_im2/contexts/chat/composer/effects.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]
[reagent.core :as reagent]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.keyboard :as kb]
[status-im2.contexts.chat.composer.utils :as utils]
Expand Down Expand Up @@ -105,53 +106,62 @@

(defn use-edit
[{:keys [input-ref]}
{:keys [text-value saved-cursor-position]}
{:keys [edit]}]
(rn/use-effect
(fn []
(let [edit-text (get-in edit [:content :text])
text-value-count (count @text-value)]
(when (and edit @input-ref)
;; A small setTimeout is necessary to ensure the statement is enqueued and will get executed
;; ASAP.
;; https://github.com/software-mansion/react-native-screens/issues/472
(js/setTimeout #(.focus ^js @input-ref) 250)
(.setNativeProps ^js @input-ref (clj->js {:text edit-text}))
(reset! text-value edit-text)
(reset! saved-cursor-position (if (zero? text-value-count)
(count edit-text)
text-value-count)))))
[(:message-id edit)]))
{:keys [text-value saved-cursor-position cursor-position]}
{:keys [edit input-with-mentions]}
messages-list-on-layout-finished?]
(let [mention? (some #(= :mention (first %)) (seq input-with-mentions))
composer-just-opened? (not @messages-list-on-layout-finished?)]
(rn/use-effect
(fn []
(let [mention-text (reduce (fn [acc item]
(str acc (second item)))
""
input-with-mentions)
edit-text (cond
mention? mention-text
;; NOTE: using text-value for cases when the user
;; leaves the app with an unfinished edit and re-opens
;; the chat.
(and (seq @text-value) composer-just-opened?)
@text-value
:else (get-in edit [:content :text]))
selection-pos (count edit-text)
inject-edit-text (fn []
(reset! text-value edit-text)
(reset! cursor-position selection-pos)
(reset! saved-cursor-position selection-pos)
(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:text edit-text}))))]

(when (and edit @input-ref)
;; NOTE: A small setTimeout is necessary to ensure the focus is enqueued and is executed
;; ASAP. Check https://github.com/software-mansion/react-native-screens/issues/472
;;
;; The nested setTimeout is necessary to avoid both `on-focus` and
;; `on-content-size-change` handlers triggering the height animation simultaneously, as
;; this causes a jump in the
;; UI. This way, `on-focus` will trigger first without changing the height, after which
;; `on-content-size-change` will animate the height of the input based on the injected
;; text.
(js/setTimeout #(do (when @messages-list-on-layout-finished? (.focus ^js @input-ref))
(reagent/next-tick inject-edit-text))
600))))
[(:message-id edit)])))

(defn use-reply
[{:keys [input-ref]}
{:keys [container-opacity]}
{:keys [reply]}]
{:keys [reply]}
messages-list-on-layout-finished?]
(rn/use-effect
(fn []
(when reply
(reanimated/animate container-opacity 1))
(when (and reply @input-ref)
(js/setTimeout #(.focus ^js @input-ref) 250)))
(when (and reply @input-ref @messages-list-on-layout-finished?)
(js/setTimeout #(.focus ^js @input-ref) 600)))
[(:message-id reply)]))

(defn edit-mentions
[{:keys [input-ref]} {:keys [text-value cursor-position]} {:keys [input-with-mentions]}]
(rn/use-effect (fn []
(let [input-text (reduce (fn [acc item]
(str acc (second item)))
""
input-with-mentions)]
(reset! text-value input-text)
(reset! cursor-position (count input-text))
(js/setTimeout #(when @input-ref
(.setNativeProps ^js @input-ref
(clj->js {:selection {:start (count input-text)
:end (count
input-text)}})))
300)))
[(some #(= :mention (first %)) (seq input-with-mentions))]))

(defn update-input-mention
[{:keys [input-ref]}
{:keys [text-value]}
Expand Down
9 changes: 4 additions & 5 deletions src/status_im2/contexts/chat/composer/gesture.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,7 @@
(reset! emoji-kb-extra-height nil))
(reset! maximized? false)
(rf/dispatch [:chat.ui/set-input-maximized false])
(when @input-ref
(.blur ^js @input-ref)))
(utils/blur-input input-ref))

(defn bounce-back
[{:keys [height saved-height opacity background-y]}
Expand Down Expand Up @@ -96,13 +95,13 @@
max-height
bounded-height
saved-height))
(when @input-ref ; sheet at min-height, collapse keyboard
(.blur ^js @input-ref)))))))
; sheet at min-height, collapse keyboard
(utils/blur-input input-ref))))))
(gesture/on-end (fn []
(let [diff (- (reanimated/get-shared-value height)
(reanimated/get-shared-value saved-height))]
(if @gesture-enabled?
(if (>= diff 0)
(if (and @expanding? (>= diff 0))
(if (> diff constants/drag-threshold)
(maximize state animations dimensions)
(bounce-back animations dimensions starting-opacity))
Expand Down
19 changes: 11 additions & 8 deletions src/status_im2/contexts/chat/composer/handlers.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,14 @@
show-floating-scroll-down-button?]
(reset! focused? true)
(rf/dispatch [:chat.ui/set-input-focused true])
(reanimated/animate height (reanimated/get-shared-value last-height))
(reanimated/set-shared-value saved-height (reanimated/get-shared-value last-height))
(reanimated/animate container-opacity 1)
(when (> (reanimated/get-shared-value last-height) (* constants/background-threshold max-height))
(reanimated/animate opacity 1)
(reanimated/set-shared-value background-y 0))
(let [last-height-value (reanimated/get-shared-value last-height)]
(reanimated/animate height last-height-value)
(reanimated/set-shared-value saved-height last-height-value)
(reanimated/animate container-opacity 1)
(when (> last-height-value (* constants/background-threshold max-height))
(reanimated/animate opacity 1)
(reanimated/set-shared-value background-y 0)))

(js/setTimeout #(reset! lock-selection? false) 300)
(when (and (not-empty @text-value) @input-ref)
(.setNativeProps ^js @input-ref
Expand Down Expand Up @@ -72,7 +74,7 @@
"Save new text height, expand composer if possible, show background overlay if needed"
[event
{:keys [maximized? lock-layout? text-value]}
{:keys [height saved-height opacity background-y]}
{:keys [height saved-height last-height opacity background-y]}
{:keys [content-height window-height max-height]}
keyboard-shown]
(when keyboard-shown
Expand All @@ -87,8 +89,9 @@
max-height)
new-height (min new-height max-height)]
(reset! content-height content-size)
(when (utils/update-height? content-size height max-height maximized?)
(when (utils/update-height? content-size height max-height)
(reanimated/animate height new-height)
(reanimated/set-shared-value last-height new-height)
(reanimated/set-shared-value saved-height new-height))
(when (= new-height max-height)
(reset! maximized? true)
Expand Down
29 changes: 18 additions & 11 deletions src/status_im2/contexts/chat/composer/keyboard.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
[react-native.async-storage :as async-storage]
[react-native.core :as rn]
[react-native.platform :as platform]
[react-native.reanimated :as reanimated]))
[react-native.reanimated :as reanimated]
[status-im2.contexts.chat.composer.utils :as utils]))

(defn get-kb-height
[curr-height default-height]
Expand All @@ -20,18 +21,24 @@
(async-storage/set-item! :kb-default-height (str height)))))

(defn handle-emoji-kb-ios
"Opening emoji KB on iOS while maximized will cause a flicker up and down. This method handles that."
"Opening emoji KB on iOS will cause a flicker up and down due to height differences.
This method handles that by adding the extra difference between the keyboards. When the input is
expanded to a point where the added difference will make the composer go beyond the screen causing a flicker,
we're subtracting the difference so it only reaches the allowed max-height. We're not animating these
changes to make it appear seamless during transitions between keyboard types when maximized."
[event
{:keys [emoji-kb-extra-height]}
{:keys [text-value]}
{:keys [text-value kb-height]}
{:keys [height saved-height]}
{:keys [max-height]}]
(let [start-h (oops/oget event "startCoordinates.height")
end-h (oops/oget event "endCoordinates.height")
diff (- end-h start-h)
max-height-diff (- max-height diff)
curr-text @text-value]
(if (> (reanimated/get-shared-value height) max-height-diff)
(let [start-h (oops/oget event "startCoordinates.height")
end-h (oops/oget event "endCoordinates.height")
diff (- end-h start-h)
max-height-diff (- max-height diff)
curr-text @text-value
bigger-than-default-kb? (> end-h @kb-height)
almost-expanded? (> (reanimated/get-shared-value height) max-height-diff)]
(if (and almost-expanded? bigger-than-default-kb? (pos? diff))
(do
(reanimated/set-shared-value height (- (reanimated/get-shared-value height) diff))
(reanimated/set-shared-value saved-height (- (reanimated/get-shared-value saved-height) diff))
Expand All @@ -58,8 +65,8 @@
#(handle-emoji-kb-ios % props state animations dimensions)))
(reset! keyboard-hide-listener (.addListener rn/keyboard
"keyboardDidHide"
#(when (and platform/android? @input-ref)
(.blur ^js @input-ref)))))
#(when platform/android?
(utils/blur-input input-ref)))))

(defn handle-refocus-emoji-kb-ios
[{:keys [saved-emoji-kb-extra-height]}
Expand Down
13 changes: 7 additions & 6 deletions src/status_im2/contexts/chat/composer/reply/view.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[status-im2.constants :as constant]
[status-im2.contexts.chat.composer.constants :as constants]
[status-im2.contexts.chat.composer.reply.style :as style]
[status-im2.contexts.chat.composer.utils :as utils]
[utils.ens.stateofus :as stateofus]
[utils.i18n :as i18n]
[utils.re-frame :as rf]))
Expand Down Expand Up @@ -85,7 +86,7 @@
(defn quoted-message
[{:keys [from content-type contentType parsed-text content deleted? deleted-for-me?
album-images-count]}
in-chat-input? pin? recording-audio?]
in-chat-input? pin? recording-audio? input-ref]
(let [[primary-name _] (rf/sub [:contacts/contact-two-names-by-identity from])
current-public-key (rf/sub [:multiaccount/public-key])
content-type (or content-type contentType)
Expand Down Expand Up @@ -136,7 +137,7 @@
{:icon-only? true
:size 24
:accessibility-label :reply-cancel-button
:on-press #(rf/dispatch [:chat.ui/cancel-message-reply])
:on-press #(utils/cancel-reply-message input-ref)
:type :outline}
:i/close])
(when (and in-chat-input? recording-audio?)
Expand All @@ -148,13 +149,13 @@
:style style/gradient}])]))

(defn- f-view
[recording?]
[recording? input-ref]
(let [reply (rf/sub [:chats/reply-message])
height (reanimated/use-shared-value (if reply constants/reply-container-height 0))]
(rn/use-effect #(reanimated/animate height (if reply constants/reply-container-height 0)) [reply])
[reanimated/view {:style (reanimated/apply-animations-to-style {:height height} {})}
(when reply [quoted-message reply true false recording?])]))
(when reply [quoted-message reply true false recording? input-ref])]))

(defn view
[{:keys [recording?]}]
[:f> f-view @recording?])
[{:keys [recording?]} input-ref]
[:f> f-view @recording? input-ref])
31 changes: 24 additions & 7 deletions src/status_im2/contexts/chat/composer/utils.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,10 @@
(max min-v (min v max-v)))

(defn update-height?
[content-size height max-height maximized?]
(when-not @maximized?
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff constants/content-change-threshold)))))
[content-size height max-height]
(let [diff (Math/abs (- content-size (reanimated/get-shared-value height)))]
(and (not= (reanimated/get-shared-value height) max-height)
(> diff constants/content-change-threshold))))

(defn show-top-gradient?
[y lines max-lines gradient-opacity focused?]
Expand Down Expand Up @@ -100,10 +99,28 @@
(not reply?)
(not audio?)))

(defn blur-input
[input-ref]
(when @input-ref
(rf/dispatch [:chat.ui/set-input-focused false])
(.blur ^js @input-ref)))

(defn cancel-reply-message
[input-ref]
(js/setTimeout #(blur-input input-ref) 100)
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height])
(rf/dispatch [:chat.ui/cancel-message-reply]))

(defn cancel-edit-message
[{:keys [text-value]}]
[text-value input-ref]
(reset! text-value "")
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height]))
;; NOTE: adding a timeout to assure the input is blurred on the next tick
;; after the `text-value` was cleared. Otherwise the height will be calculated
;; with the old `text-value`, leading to wrong composer height after blur.
(js/setTimeout #(blur-input input-ref) 100)
(.setNativeProps ^js @input-ref (clj->js {:text ""}))
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height])
(rf/dispatch [:chat.ui/cancel-message-edit]))

(defn count-lines
[s]
Expand Down
Loading