Compare commits
13
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f357e67529 | ||
|
|
a7b27a0ef3 | ||
|
|
88aeb0ccfb | ||
|
|
b54d8ad5f3 | ||
|
|
7666026764 | ||
|
|
963745ecb6 | ||
|
|
c689b81e01 | ||
|
|
b0f0e29706 | ||
|
|
b035c4621b | ||
|
|
10eb4330e6 | ||
|
|
c5d472ab9b | ||
|
|
1ae8dae700 | ||
|
|
35fb6354c6 |
Binary file not shown.
|
After Width: | Height: | Size: 528 B |
Binary file not shown.
|
After Width: | Height: | Size: 769 B |
Binary file not shown.
|
Before Width: | Height: | Size: 525 B After Width: | Height: | Size: 628 B |
Binary file not shown.
|
Before Width: | Height: | Size: 759 B After Width: | Height: | Size: 913 B |
@@ -6,6 +6,7 @@
|
||||
[status-im.chat.models.mentions :as mentions]
|
||||
[status-im.chat.models.message :as chat.message]
|
||||
[status-im.chat.models.message-content :as message-content]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.i18n :as i18n]
|
||||
@@ -51,12 +52,6 @@
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
{:db (assoc-in db [:chat/inputs current-chat-id :input-maximized?] maximized?)}))
|
||||
|
||||
(rf/defn set-input-refocus
|
||||
{:events [:chat.ui/set-input-refocus]}
|
||||
[{db :db} refocus? chat-id]
|
||||
(let [current-chat-id (or chat-id (:current-chat-id db))]
|
||||
{:db (assoc-in db [:chat/inputs current-chat-id :input-refocus?] refocus?)}))
|
||||
|
||||
(rf/defn select-mention
|
||||
{:events [:chat.ui/select-mention]}
|
||||
[{:keys [db] :as cofx} text-input-ref {:keys [primary-name searched-text match public-key] :as user}]
|
||||
@@ -106,7 +101,8 @@
|
||||
(update-in [:chat/inputs current-chat-id :metadata]
|
||||
dissoc
|
||||
:sending-image))}
|
||||
(input/set-input-text text current-chat-id))))
|
||||
(when-not config/new-composer-enabled?
|
||||
(input/set-input-text text current-chat-id)))))
|
||||
|
||||
(rf/defn show-contact-request-input
|
||||
"Sets reference to previous chat message and focuses on input"
|
||||
@@ -181,7 +177,8 @@
|
||||
[{:keys [db] :as cofx}]
|
||||
(let [current-chat-id (:current-chat-id db)]
|
||||
(rf/merge cofx
|
||||
{:set-text-input-value [current-chat-id ""]}
|
||||
(when-not config/new-composer-enabled?
|
||||
{:set-text-input-value [current-chat-id ""]})
|
||||
(clean-input current-chat-id)
|
||||
(mentions/clear-mentions))))
|
||||
|
||||
@@ -225,22 +222,21 @@
|
||||
|
||||
(rf/defn send-edited-message
|
||||
[{:keys [db] :as cofx} text {:keys [message-id quoted-message chat-id]}]
|
||||
(let [pinned-message (get-in db [:pin-messages chat-id message-id])]
|
||||
(rf/merge
|
||||
cofx
|
||||
{:json-rpc/call [{:method "wakuext_editMessage"
|
||||
:params [{:id message-id
|
||||
:text text
|
||||
:content-type (if (message-content/emoji-only-content?
|
||||
{:text text :response-to quoted-message})
|
||||
constants/content-type-emoji
|
||||
constants/content-type-text)}]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to edit message " %)
|
||||
:on-success (fn [result]
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response
|
||||
result]))}]}
|
||||
(cancel-message-edit))))
|
||||
(rf/merge
|
||||
cofx
|
||||
{:json-rpc/call [{:method "wakuext_editMessage"
|
||||
:params [{:id message-id
|
||||
:text text
|
||||
:content-type (if (message-content/emoji-only-content?
|
||||
{:text text :response-to quoted-message})
|
||||
constants/content-type-emoji
|
||||
constants/content-type-text)}]
|
||||
:js-response true
|
||||
:on-error #(log/error "failed to edit message " %)
|
||||
:on-success (fn [result]
|
||||
(re-frame/dispatch [:sanitize-messages-and-process-response
|
||||
result]))}]}
|
||||
(cancel-message-edit)))
|
||||
|
||||
(rf/defn send-current-message
|
||||
"Sends message from current chat input"
|
||||
|
||||
@@ -158,3 +158,5 @@
|
||||
["enrtree://AOGECG2SPND25EEFMAJ5WF3KSGJNSGV356DSTL2YVLLZWIV6SAYBM@test.waku.nodes.status.im"]})
|
||||
|
||||
(def default-kdf-iterations 3200)
|
||||
|
||||
(def ^:const new-composer-enabled? true)
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.actions.style :as style]))
|
||||
|
||||
(defn send-message
|
||||
[{:keys [input-ref]}
|
||||
{:keys [text-value focused? maximized?]}
|
||||
[{:keys [text-value focused? maximized?]}
|
||||
{:keys [height saved-height last-height opacity background-y container-opacity]}
|
||||
window-height]
|
||||
(reanimated/animate height constants/input-height)
|
||||
@@ -33,13 +32,10 @@
|
||||
(rf/dispatch [:chat.ui/set-chat-input-text nil])
|
||||
(reset! maximized? false)
|
||||
(reset! text-value "")
|
||||
(when @input-ref
|
||||
(.clear ^js @input-ref))
|
||||
(messages.list/scroll-to-bottom))
|
||||
|
||||
(defn send-button
|
||||
[props
|
||||
{:keys [text-value] :as state}
|
||||
[{:keys [text-value] :as state}
|
||||
animations
|
||||
window-height
|
||||
images?]
|
||||
@@ -64,7 +60,7 @@
|
||||
{:icon true
|
||||
:size 32
|
||||
:accessibility-label :send-message-button
|
||||
:on-press #(send-message props state animations window-height)}
|
||||
:on-press #(send-message state animations window-height)}
|
||||
:i/arrow-up]])]))])
|
||||
|
||||
(defn audio-button
|
||||
@@ -88,17 +84,13 @@
|
||||
|
||||
(defn open-photo-selector
|
||||
[{:keys [input-ref]}
|
||||
{:keys [focused?]}
|
||||
{:keys [height]}
|
||||
insets]
|
||||
(permissions/request-permissions
|
||||
{:permissions [:read-external-storage :write-external-storage]
|
||||
:on-allowed (fn []
|
||||
(when platform/android?
|
||||
(when @focused?
|
||||
(rf/dispatch [:chat.ui/set-input-refocus true]))
|
||||
(when @input-ref
|
||||
(.blur ^js @input-ref)))
|
||||
(when (and platform/android? @input-ref)
|
||||
(.blur ^js @input-ref))
|
||||
(rf/dispatch [:chat.ui/set-input-content-height
|
||||
(reanimated/get-shared-value height)])
|
||||
(rf/dispatch [:open-modal :photo-selector {:insets insets}]))
|
||||
@@ -108,9 +100,9 @@
|
||||
:t/external-storage-denied)))}))
|
||||
|
||||
(defn image-button
|
||||
[props state animations insets]
|
||||
[props animations insets]
|
||||
[quo/button
|
||||
{:on-press #(open-photo-selector props state animations insets)
|
||||
{:on-press #(open-photo-selector props animations insets)
|
||||
:icon true
|
||||
:type :outline
|
||||
:size 32
|
||||
@@ -141,8 +133,8 @@
|
||||
[rn/view {:style style/actions-container}
|
||||
[rn/view {:style {:flex-direction :row}}
|
||||
[camera-button]
|
||||
[image-button props state animations insets]
|
||||
[image-button props animations insets]
|
||||
[reaction-button]
|
||||
[format-button]]
|
||||
[send-button props state animations window-height images?]
|
||||
[send-button state animations window-height images?]
|
||||
[audio-button]])
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
(def ^:const images-container-height 76)
|
||||
|
||||
(def ^:const reply-container-height 32)
|
||||
|
||||
(def ^:const edit-container-height 32)
|
||||
|
||||
(def ^:const extra-content-offset (if platform/ios? 6 0))
|
||||
|
||||
(def ^:const content-change-threshold 10)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.edit.style)
|
||||
|
||||
(def container
|
||||
{:flex-direction :row
|
||||
:height 24})
|
||||
|
||||
(def content-container
|
||||
{:flex 1
|
||||
:flex-direction :row})
|
||||
|
||||
(def icon-container
|
||||
{:position :absolute
|
||||
:left 0
|
||||
:bottom -4
|
||||
:width 16
|
||||
:height 16})
|
||||
|
||||
(def text-container
|
||||
{:position :absolute
|
||||
:left 24
|
||||
:top 3
|
||||
:flex-direction :row
|
||||
:align-items :center})
|
||||
@@ -0,0 +1,49 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.edit.view
|
||||
(:require
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[re-frame.core :as rf]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.edit.style :as style]))
|
||||
|
||||
(defn edit-message
|
||||
[cancel]
|
||||
[rn/view
|
||||
{:style style/container
|
||||
:accessibility-label :edit-message}
|
||||
[rn/view {:style style/content-container}
|
||||
[quo/icon
|
||||
:i/connector-dotted
|
||||
{:size 16
|
||||
:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
|
||||
:container-style style/icon-container}]
|
||||
[rn/view {:style style/text-container}
|
||||
[quo/text
|
||||
{:weight :medium
|
||||
:size :paragraph-2}
|
||||
(i18n/label :t/editing-message)]]]
|
||||
[quo/button
|
||||
{:width 24
|
||||
:size 24
|
||||
:accessibility-label :reply-cancel-button
|
||||
:on-press #(do
|
||||
(cancel)
|
||||
(rf/dispatch [:chat.ui/cancel-message-edit]))
|
||||
:type :outline}
|
||||
[quo/icon :i/close
|
||||
{:size 16
|
||||
:color (colors/theme-colors colors/neutral-100 colors/neutral-40)}]]])
|
||||
|
||||
(defn- f-view
|
||||
[edit cancel]
|
||||
(let [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 cancel])]))
|
||||
|
||||
(defn view
|
||||
[edit cancel]
|
||||
[:f> f-view edit cancel])
|
||||
@@ -5,7 +5,6 @@
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.keyboard :as kb]
|
||||
[utils.re-frame :as rf]
|
||||
[utils.number :as utils.number]))
|
||||
|
||||
(defn reenter-screen-effect
|
||||
@@ -29,13 +28,6 @@
|
||||
(reanimated/set-shared-value saved-height max-height)
|
||||
(reanimated/set-shared-value last-height max-height)))
|
||||
|
||||
(defn refocus-effect
|
||||
[{:keys [input-ref]}
|
||||
{:keys [input-refocus?]}]
|
||||
(when (and input-refocus? @input-ref)
|
||||
(.focus ^js @input-ref)
|
||||
(rf/dispatch [:chat.ui/set-input-refocus false])))
|
||||
|
||||
(defn layout-effect
|
||||
[{:keys [lock-layout?]}]
|
||||
(when-not @lock-layout?
|
||||
@@ -56,17 +48,42 @@
|
||||
(reanimated/set-shared-value background-y 0)
|
||||
(reanimated/animate opacity 1)))
|
||||
|
||||
(defn images-effect
|
||||
(defn images-or-reply-effect
|
||||
[{:keys [container-opacity]}
|
||||
images?]
|
||||
(when images?
|
||||
(reanimated/animate container-opacity 1)))
|
||||
{:keys [replying? sending-images? input-ref]}
|
||||
images? reply?]
|
||||
(when (or images? reply?)
|
||||
(reanimated/animate container-opacity 1))
|
||||
(when (and (not @sending-images?) images? @input-ref)
|
||||
(.focus ^js @input-ref)
|
||||
(reset! sending-images? true))
|
||||
(when (and (not @replying?) reply? @input-ref)
|
||||
(.focus ^js @input-ref)
|
||||
(reset! replying? true))
|
||||
(when-not images?
|
||||
(reset! sending-images? false))
|
||||
(when-not reply?
|
||||
(reset! replying? false)))
|
||||
|
||||
(defn edit-effect
|
||||
[{:keys [text-value saved-cursor-position]}
|
||||
{:keys [editing? input-ref]}
|
||||
edit]
|
||||
(let [edit-text (get-in edit [:content :text])]
|
||||
(when (and (not @editing?) edit @input-ref)
|
||||
(.focus ^js @input-ref)
|
||||
(reset! editing? true)
|
||||
(reset! text-value edit-text)
|
||||
(reset! saved-cursor-position (count edit-text)))
|
||||
(when-not edit-text
|
||||
(reset! editing? false))))
|
||||
|
||||
(defn empty-effect
|
||||
[{:keys [text-value maximized? focused?]}
|
||||
{:keys [container-opacity]}
|
||||
images?]
|
||||
(when (and (empty? @text-value) (not images?) (not @maximized?) (not @focused?))
|
||||
images?
|
||||
reply?]
|
||||
(when (and (empty? @text-value) (not images?) (not reply?) (not @maximized?) (not @focused?))
|
||||
(reanimated/animate-delay container-opacity constants/empty-opacity 200)))
|
||||
|
||||
(defn component-will-unmount
|
||||
@@ -76,17 +93,18 @@
|
||||
(.remove ^js @keyboard-frame-listener))
|
||||
|
||||
(defn initialize
|
||||
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images?]
|
||||
[props state animations {:keys [max-height] :as dimensions} chat-input keyboard-height images? reply?
|
||||
edit]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(maximized-effect state animations dimensions chat-input)
|
||||
(refocus-effect props chat-input)
|
||||
(reenter-screen-effect state dimensions chat-input)
|
||||
(layout-effect state)
|
||||
(kb-default-height-effect state)
|
||||
(background-effect state animations dimensions chat-input)
|
||||
(images-effect animations images?)
|
||||
(empty-effect state animations images?)
|
||||
(images-or-reply-effect animations props images? reply?)
|
||||
(edit-effect state props edit)
|
||||
(empty-effect state animations images? reply?)
|
||||
(kb/add-kb-listeners props state animations dimensions keyboard-height)
|
||||
#(component-will-unmount props))
|
||||
[max-height]))
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
maximized?]}
|
||||
{:keys [height saved-height last-height gradient-opacity container-opacity opacity background-y]}
|
||||
{:keys [lines content-height max-height window-height]}
|
||||
images]
|
||||
images
|
||||
reply]
|
||||
(let [min-height (utils/get-min-height lines)
|
||||
reopen-height (utils/calc-reopen-height text-value min-height content-height saved-height)]
|
||||
(reset! focused? false)
|
||||
@@ -43,7 +44,7 @@
|
||||
(reanimated/set-shared-value saved-height min-height)
|
||||
(reanimated/animate opacity 0)
|
||||
(js/setTimeout #(reanimated/set-shared-value background-y (- window-height)) 300)
|
||||
(when (and (empty? @text-value) (empty? images))
|
||||
(when (utils/empty-input? @text-value images reply)
|
||||
(reanimated/animate container-opacity constants/empty-opacity))
|
||||
(reanimated/animate gradient-opacity 0)
|
||||
(reset! lock-selection? true)
|
||||
@@ -58,6 +59,7 @@
|
||||
{:keys [height saved-height opacity background-y]}
|
||||
{:keys [content-height window-height max-height]}
|
||||
keyboard-shown]
|
||||
(println "qqq" (oops/oget event "nativeEvent.contentSize.height") keyboard-shown)
|
||||
(when keyboard-shown
|
||||
(let [content-size (+ (oops/oget event "nativeEvent.contentSize.height")
|
||||
constants/extra-content-offset)
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.reply.style)
|
||||
|
||||
(defn reply-content
|
||||
[pin?]
|
||||
{:padding-right (when-not pin? 10)
|
||||
:flex 1
|
||||
:flex-direction :row})
|
||||
|
||||
(defn quoted-message
|
||||
[pin?]
|
||||
(merge {:flex-direction :row
|
||||
:flex 1
|
||||
:align-items :center}
|
||||
(when-not pin?
|
||||
{:left 22
|
||||
:margin-right 22})))
|
||||
|
||||
(def reply-from
|
||||
{:flex-direction :row
|
||||
:align-items :center})
|
||||
|
||||
(def message-author-text
|
||||
{:margin-left 4})
|
||||
|
||||
(def message-text
|
||||
{:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2
|
||||
:flex 1})
|
||||
|
||||
(def gradient
|
||||
{:position :absolute
|
||||
:right 0
|
||||
:top 0
|
||||
:bottom 0
|
||||
:width "50%"})
|
||||
|
||||
(def reply-deleted-message
|
||||
{:text-transform :none
|
||||
:margin-left 4
|
||||
:margin-top 2})
|
||||
@@ -0,0 +1,151 @@
|
||||
(ns status-im2.contexts.chat.bottom-sheet-composer.reply.view
|
||||
(:require [clojure.string :as string]
|
||||
[react-native.core :as rn]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[utils.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[status-im2.constants :as constant]
|
||||
[status-im.ethereum.stateofus :as stateofus]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.reply.style :as style]
|
||||
[react-native.linear-gradient :as linear-gradient]))
|
||||
|
||||
(defn get-quoted-text-with-mentions
|
||||
[parsed-text]
|
||||
(string/join
|
||||
(mapv (fn [{:keys [type literal children]}]
|
||||
(cond
|
||||
(= type "paragraph")
|
||||
(get-quoted-text-with-mentions children)
|
||||
|
||||
(= type "mention")
|
||||
(rf/sub [:messages/resolve-mention literal])
|
||||
|
||||
(seq children)
|
||||
(get-quoted-text-with-mentions children)
|
||||
|
||||
:else
|
||||
literal))
|
||||
parsed-text)))
|
||||
|
||||
(defn format-author
|
||||
[contact-name]
|
||||
(let [author (if (or (= (first contact-name) "@")
|
||||
;; in case of replies
|
||||
(= (second contact-name) "@"))
|
||||
(or (stateofus/username contact-name)
|
||||
(subs contact-name 0 81))
|
||||
contact-name)]
|
||||
author))
|
||||
|
||||
(defn format-reply-author
|
||||
[from username current-public-key]
|
||||
(or (and (= from current-public-key)
|
||||
(i18n/label :t/You))
|
||||
(when username (format-author username))))
|
||||
|
||||
(defn reply-deleted-message
|
||||
[]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:align-items :center}}
|
||||
[quo/icon :i/sad-face {:size 16}]
|
||||
[quo/text
|
||||
{:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:accessibility-label :quoted-message
|
||||
:style style/reply-deleted-message}
|
||||
(i18n/label :t/message-deleted)]])
|
||||
|
||||
(defn reply-from
|
||||
[{:keys [from contact-name current-public-key]}]
|
||||
(let [display-name (first (rf/sub [:contacts/contact-two-names-by-identity from]))
|
||||
contact (rf/sub [:contacts/contact-by-address from])
|
||||
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path from]))]
|
||||
[rn/view {:style style/reply-from}
|
||||
[quo/user-avatar
|
||||
{:full-name display-name
|
||||
:profile-picture photo-path
|
||||
:status-indicator? false
|
||||
:size :xxxs}]
|
||||
[quo/text
|
||||
{:weight :semi-bold
|
||||
:size :paragraph-2
|
||||
:number-of-lines 1
|
||||
:style style/message-author-text}
|
||||
(format-reply-author from contact-name current-public-key)]]))
|
||||
|
||||
(defn reply-message
|
||||
[{:keys [from identicon content-type contentType parsed-text content deleted? deleted-for-me?
|
||||
album-images-count]}
|
||||
in-chat-input? pin? recording-audio?]
|
||||
(let [contact-name (rf/sub [:contacts/contact-name-by-identity from])
|
||||
current-public-key (rf/sub [:multiaccount/public-key])
|
||||
content-type (or content-type contentType)]
|
||||
[rn/view
|
||||
{:style {:flex-direction :row
|
||||
:height (when-not pin? 24)
|
||||
:accessibility-label :reply-message}}
|
||||
[rn/view {:style (style/reply-content pin?)}
|
||||
(when-not pin?
|
||||
[quo/icon :i/connector
|
||||
{:size 16
|
||||
:color (colors/theme-colors colors/neutral-40 colors/neutral-60)
|
||||
:container-style {:position :absolute :left 0 :bottom -4 :width 16 :height 16}}])
|
||||
(if (or deleted? deleted-for-me?)
|
||||
[rn/view {:style (style/quoted-message pin?)}
|
||||
[reply-deleted-message]]
|
||||
[rn/view {:style (style/quoted-message pin?)}
|
||||
[reply-from
|
||||
{:from from
|
||||
:identicon identicon
|
||||
:contact-name contact-name
|
||||
:current-public-key current-public-key}]
|
||||
[quo/text
|
||||
{:number-of-lines 1
|
||||
:size :label
|
||||
:weight :regular
|
||||
:accessibility-label :quoted-message
|
||||
:ellipsize-mode :tail
|
||||
:style (merge
|
||||
style/message-text
|
||||
(when (or (= constant/content-type-image content-type)
|
||||
(= constant/content-type-sticker content-type)
|
||||
(= constant/content-type-audio content-type))
|
||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}))}
|
||||
(case (or content-type contentType)
|
||||
constant/content-type-image (if album-images-count
|
||||
(i18n/label :t/images-albums-count
|
||||
{:album-images-count album-images-count})
|
||||
(i18n/label :t/image))
|
||||
constant/content-type-sticker (i18n/label :t/sticker)
|
||||
constant/content-type-audio (i18n/label :t/audio)
|
||||
(get-quoted-text-with-mentions (or parsed-text (:parsed-text content))))]])]
|
||||
(when (and in-chat-input? (not recording-audio?))
|
||||
[quo/button
|
||||
{:icon true
|
||||
:type :outline
|
||||
:size 24
|
||||
:on-press #(rf/dispatch [:chat.ui/cancel-message-reply])}
|
||||
:i/close])
|
||||
(when (and in-chat-input? recording-audio?)
|
||||
[linear-gradient/linear-gradient
|
||||
{:colors [(colors/theme-colors colors/white-opa-0 colors/neutral-90-opa-0)
|
||||
(colors/theme-colors colors/white colors/neutral-90)]
|
||||
:start {:x 0 :y 0}
|
||||
:end {:x 0.7 :y 0}
|
||||
:style style/gradient}])]))
|
||||
|
||||
(defn- f-view
|
||||
[reply]
|
||||
(let [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 [reply-message reply true false false])]))
|
||||
|
||||
(defn view
|
||||
[reply]
|
||||
[:f> f-view reply])
|
||||
@@ -6,16 +6,16 @@
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]))
|
||||
|
||||
(defn shadow
|
||||
[lines]
|
||||
[elevation?]
|
||||
(if platform/ios?
|
||||
{:shadow-radius 20
|
||||
:shadow-opacity (colors/theme-colors 0.1 0.7)
|
||||
:shadow-color colors/neutral-100
|
||||
:shadow-offset {:width 0 :height (colors/theme-colors -4 -8)}}
|
||||
{:elevation (if (> lines 1) 10 0)}))
|
||||
{:elevation (if elevation? 10 0)}))
|
||||
|
||||
(defn sheet-container
|
||||
[insets opacity lines]
|
||||
[insets opacity elevation?]
|
||||
(reanimated/apply-animations-to-style
|
||||
{:opacity opacity}
|
||||
(merge
|
||||
@@ -29,7 +29,7 @@
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
:z-index 3
|
||||
:padding-bottom (:bottom insets)}
|
||||
(shadow lines))))
|
||||
(shadow elevation?))))
|
||||
|
||||
(def bar-container
|
||||
{:height constants/bar-container-height
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
[oops.core :as oops]
|
||||
[react-native.platform :as platform]
|
||||
[react-native.reanimated :as reanimated]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]))
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[utils.re-frame :as rf]))
|
||||
|
||||
(defn bounded-val
|
||||
[val min-val max-val]
|
||||
@@ -60,17 +61,31 @@
|
||||
(if platform/ios? lines (dec lines))))
|
||||
|
||||
(defn calc-max-height
|
||||
[window-height kb-height insets images]
|
||||
[window-height kb-height insets images? reply? edit?]
|
||||
(let [margin-top (if platform/ios? (:top insets) (+ 10 (:top insets)))
|
||||
max-height (- window-height
|
||||
margin-top
|
||||
kb-height
|
||||
constants/bar-container-height
|
||||
constants/actions-container-height)]
|
||||
(if (seq images)
|
||||
(- max-height constants/images-container-height)
|
||||
max-height)))
|
||||
constants/actions-container-height)
|
||||
max-height (if images? (- max-height constants/images-container-height) max-height)
|
||||
max-height (if reply? (- max-height constants/reply-container-height) max-height)
|
||||
max-height (if edit? (- max-height constants/edit-container-height) max-height)]
|
||||
max-height))
|
||||
|
||||
(defn empty-input?
|
||||
[input-text images]
|
||||
(and (nil? input-text) (empty? images)))
|
||||
[text images reply?]
|
||||
(and (empty? text) (empty? images) (not reply?)))
|
||||
|
||||
(defn android-elevation?
|
||||
[lines images reply? edit?]
|
||||
(or (> lines 1) (seq images) reply? edit?))
|
||||
|
||||
(defn cancel-edit-message
|
||||
[{:keys [text-value]}
|
||||
{:keys [height saved-height last-height]}]
|
||||
(reanimated/animate height constants/input-height)
|
||||
(reanimated/set-shared-value saved-height constants/input-height)
|
||||
(reanimated/set-shared-value last-height constants/input-height)
|
||||
(reset! text-value "")
|
||||
(rf/dispatch [:chat.ui/set-input-content-height constants/input-height]))
|
||||
|
||||
@@ -9,7 +9,9 @@
|
||||
[utils.i18n :as i18n]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.style :as style]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.images.view :as images]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.reply.view :as reply]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.edit.view :as edit]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.utils :as utils]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.actions.view :as actions]
|
||||
@@ -29,7 +31,10 @@
|
||||
:keyboard-frame-listener (atom nil)
|
||||
:keyboard-hide-listener (atom nil)
|
||||
:emoji-kb-extra-height (atom nil)
|
||||
:saved-emoji-kb-extra-height (atom nil)}
|
||||
:saved-emoji-kb-extra-height (atom nil)
|
||||
:replying? (atom nil)
|
||||
:sending-images? (atom nil)
|
||||
:editing? (atom nil)}
|
||||
state {:text-value (reagent/atom "")
|
||||
:cursor-position (reagent/atom 0)
|
||||
:saved-cursor-position (reagent/atom 0)
|
||||
@@ -43,6 +48,8 @@
|
||||
[:f>
|
||||
(fn []
|
||||
(let [images (rf/sub [:chats/sending-image])
|
||||
reply (rf/sub [:chats/reply-message])
|
||||
edit (rf/sub [:chats/edit-message])
|
||||
{:keys [input-text input-content-height]
|
||||
:as chat-input} (rf/sub [:chats/current-chat-input])
|
||||
content-height (reagent/atom (or input-content-height
|
||||
@@ -53,7 +60,9 @@
|
||||
max-height (utils/calc-max-height window-height
|
||||
kb-height
|
||||
insets
|
||||
images)
|
||||
(seq images)
|
||||
reply
|
||||
edit)
|
||||
lines (utils/calc-lines @content-height)
|
||||
max-lines (utils/calc-lines max-height)
|
||||
initial-height (if (> lines 1)
|
||||
@@ -64,7 +73,8 @@
|
||||
:container-opacity (reanimated/use-shared-value
|
||||
(if (utils/empty-input?
|
||||
input-text
|
||||
images)
|
||||
images
|
||||
reply)
|
||||
0.7
|
||||
1))
|
||||
:height (reanimated/use-shared-value
|
||||
@@ -83,20 +93,30 @@
|
||||
:window-height window-height
|
||||
:lines lines
|
||||
:max-lines max-lines}
|
||||
show-bottom-gradient? (utils/show-bottom-gradient? state dimensions)]
|
||||
show-bottom-gradient? (utils/show-bottom-gradient? state dimensions)
|
||||
android-elevation? (utils/android-elevation? lines
|
||||
images
|
||||
reply
|
||||
edit)]
|
||||
(effects/initialize props
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
chat-input
|
||||
keyboard-height
|
||||
(seq images))
|
||||
(seq images)
|
||||
reply
|
||||
edit)
|
||||
[gesture/gesture-detector
|
||||
{:gesture (drag-gesture/drag-gesture props state animations dimensions keyboard-shown)}
|
||||
[reanimated/view
|
||||
{:style (style/sheet-container insets (:container-opacity animations) lines)
|
||||
{:style (style/sheet-container insets
|
||||
(:container-opacity animations)
|
||||
android-elevation?)
|
||||
:on-layout #(handler/layout % state blur-height)}
|
||||
[sub-view/bar]
|
||||
[reply/view reply]
|
||||
[edit/view edit #(utils/cancel-edit-message state animations)]
|
||||
[reanimated/touchable-opacity
|
||||
{:active-opacity 1
|
||||
:on-press (when @(:input-ref props) #(.focus ^js @(:input-ref props)))
|
||||
@@ -106,12 +126,12 @@
|
||||
{:ref #(reset! (:input-ref props) %)
|
||||
:default-value @(:text-value state)
|
||||
:on-focus #(handler/focus props state animations dimensions)
|
||||
:on-blur #(handler/blur state animations dimensions images)
|
||||
:on-blur #(handler/blur state animations dimensions images reply)
|
||||
:on-content-size-change #(handler/content-size-change %
|
||||
state
|
||||
animations
|
||||
dimensions
|
||||
keyboard-shown)
|
||||
(or keyboard-shown edit))
|
||||
:on-scroll #(handler/scroll % state animations dimensions)
|
||||
:on-change-text #(handler/change-text % props state)
|
||||
:on-selection-change #(handler/selection-change % state)
|
||||
|
||||
@@ -150,22 +150,27 @@
|
||||
{:position :absolute
|
||||
:bottom (+ (:bottom insets) composer.constants/composer-default-height 6)}]])))
|
||||
|
||||
(defn use-keyboard-visibility
|
||||
[]
|
||||
(let [show-listener (atom nil)
|
||||
hide-listener (atom nil)
|
||||
shown? (atom nil)]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(reset! show-listener
|
||||
(.addListener rn/keyboard "keyboardWillShow" #(reset! shown? true)))
|
||||
(reset! hide-listener
|
||||
(.addListener rn/keyboard "keyboardWillHide" #(reset! shown? false)))
|
||||
(fn []
|
||||
(.remove ^js @show-listener)
|
||||
(.remove ^js @hide-listener))))
|
||||
{:shown? shown?}))
|
||||
|
||||
(defn- f-messages-list
|
||||
[chat insets]
|
||||
(let [{keyboard-shown? :shown?} (use-keyboard-visibility)]
|
||||
[messages-list-content chat insets keyboard-shown?]))
|
||||
|
||||
(defn messages-list
|
||||
[chat insets]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [keyboard-show-listener (atom nil)
|
||||
keyboard-hide-listener (atom nil)
|
||||
keyboard-shown (atom false)]
|
||||
(rn/use-effect
|
||||
(fn []
|
||||
(reset! keyboard-show-listener (.addListener rn/keyboard
|
||||
"keyboardWillShow"
|
||||
#(reset! keyboard-shown true)))
|
||||
(reset! keyboard-hide-listener (.addListener rn/keyboard
|
||||
"keyboardWillHide"
|
||||
#(reset! keyboard-shown false)))
|
||||
(fn []
|
||||
(.remove ^js @keyboard-show-listener)
|
||||
(.remove ^js @keyboard-hide-listener))))
|
||||
[messages-list-content chat insets keyboard-shown]))])
|
||||
[:f> f-messages-list chat insets])
|
||||
|
||||
@@ -4,11 +4,14 @@
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[reagent.core :as reagent]
|
||||
[status-im2.config :as config]
|
||||
[status-im2.constants :as constants]
|
||||
[status-im2.contexts.chat.bottom-sheet-composer.view :as bottom-sheet-composer]
|
||||
[status-im2.contexts.chat.messages.composer.view :as composer]
|
||||
[status-im2.contexts.chat.messages.contact-requests.bottom-drawer :as
|
||||
contact-requests.bottom-drawer]
|
||||
[status-im2.contexts.chat.messages.list.view :as messages.list]
|
||||
[status-im2.contexts.chat.messages.list.new-temp-view :as messages.list.new]
|
||||
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
|
||||
[status-im2.navigation.state :as navigation.state]
|
||||
[utils.debounce :as debounce]
|
||||
@@ -75,10 +78,15 @@
|
||||
:keyboardVerticalOffset (- (:bottom insets))}
|
||||
[page-nav]
|
||||
[pin.banner/banner chat-id]
|
||||
[messages.list/messages-list chat insets]
|
||||
(if config/new-composer-enabled?
|
||||
[messages.list.new/messages-list chat insets]
|
||||
[messages.list/messages-list chat insets])
|
||||
(if-not able-to-send-message?
|
||||
[contact-requests.bottom-drawer/view chat-id contact-request-state group-chat]
|
||||
[:f> composer/f-composer chat-id insets])]))
|
||||
(if config/new-composer-enabled?
|
||||
[bottom-sheet-composer/bottom-sheet-composer insets]
|
||||
[:f> composer/f-composer chat-id insets]))]))
|
||||
|
||||
|
||||
(defn chat
|
||||
[]
|
||||
|
||||
Reference in New Issue
Block a user