feat: autocomplete mentions new ui (#14142)

* feat: autocomplete mentions new ui
This commit is contained in:
Omar Basem 2022-10-13 21:59:19 +04:00 committed by GitHub
parent 7368478033
commit 5492d502fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 107 additions and 83 deletions

View File

@ -6,9 +6,10 @@
[quo.platform :as platform]
[quo.components.text :as text]
[quo.design-system.colors :as colors]
[quo2.foundations.colors :as quo2.colors]
[status-im.ui.screens.chat.components.style :as styles]
[status-im.utils.fx :as fx]
[status-im.utils.handlers :refer [<sub]]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.ui.screens.chat.components.reply :as reply]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.chat.constants :as chat.constants]
@ -331,47 +332,46 @@
[idx item])
@(re-frame/subscribe [:chat/input-with-mentions]))]
^{:key (str idx "_" type "_" text)}
[rn/text (when (= type :mention) {:style {:color "#0DA4C9"}})
text])
[rn/text (when (= type :mention) {:style {:color quo2.colors/primary-50}}) text])
(get @input-texts chat-id))]))
(defn mention-item
[[public-key {:keys [alias name nickname] :as user}] _ _ text-input-ref]
(let [ens-name? (not= alias name)]
[list-item/list-item
(cond-> {:icon [photos/member-photo public-key]
:size :small
:text-size :small
:title
[text/text
{:weight :medium
:ellipsize-mode :tail
:number-of-lines 1
:size :small}
(if nickname
nickname
name)
(when nickname
[text/text
{:weight :regular
:color :secondary
:ellipsize-mode :tail
:size :small}
" "
(when ens-name?
"@")
name])]
:title-text-weight :medium
:on-press
(fn []
(re-frame/dispatch [:chat.ui/select-mention text-input-ref user]))}
[rn/touchable-opacity
{:on-press #(re-frame/dispatch [:chat.ui/select-mention text-input-ref user])}
ens-name?
(assoc :subtitle alias))]))
[list-item/list-item
(cond-> {:icon [photos/member-photo public-key]
:size :small
:text-size :small
:title
[text/text
{:weight :medium
:ellipsize-mode :tail
:number-of-lines 1
:size :small}
(if nickname
nickname
name)
(when nickname
[text/text
{:weight :regular
:color :secondary
:ellipsize-mode :tail
:size :small}
" "
(when ens-name?
"@")
name])]
:title-text-weight :medium}
ens-name?
(assoc :subtitle alias))]]))
(def chat-toolbar-height (reagent/atom nil))
(defn autocomplete-mentions [text-input-ref bottom]
(defn autocomplete-mentions-old [text-input-ref bottom]
(let [suggestions @(re-frame/subscribe [:chat/mention-suggestions])]
(when (seq suggestions)
(let [height (+ 16 (* 52 (min 4.5 (count suggestions))))]
@ -389,6 +389,22 @@
:render-data text-input-ref
:render-fn mention-item}]]]))))
(defn autocomplete-mentions [suggestions]
[:f>
(fn []
(let [animation (reanimated/use-shared-value 0)]
(quo.react/effect! #(do
(reanimated/set-shared-value animation (reanimated/with-timing (if (seq suggestions) 0 200)))))
[reanimated/view {:style (reanimated/apply-animations-to-style
{:transform [{:translateY animation}]}
{:bottom 0 :position :absolute :z-index 5 :max-height 180})}
[list/flat-list
{:keyboardShouldPersistTaps :always
:data suggestions
:key-fn first
:render-fn mention-item
:content-container-style {:padding-bottom 12}}]]))])
(defn on-chat-toolbar-layout [^js ev]
(reset! chat-toolbar-height (-> ev .-nativeEvent .-layout .-height)))
@ -475,6 +491,21 @@
(swap! context assoc :state :min)
min-y)))
(defn calculate-y-with-mentions [y max-y max-height chat-id suggestions reply]
(let [input-text (:input-text (get (<sub [:chat/inputs]) chat-id))
num-lines (count (string/split input-text "\n"))
text-height (* num-lines 22)
mentions-height (min 132 (+ 16 (* 46 (- (count suggestions) 1))))
should-translate (if (< (- max-height text-height) mentions-height) true false)
min-value (if-not reply mentions-height (+ mentions-height 44))
; translate value when mentions list appear while at bottom of expanded input sheet
mentions-translate-value (if should-translate (min min-value (- mentions-height (- max-height text-height))) mentions-height)]
(when (or (< y max-y) should-translate) mentions-translate-value)))
(defn get-y-value [context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply]
(let [y (calculate-y context keyboard-shown min-y max-y added-value)]
y (+ y (when (seq suggestions) (calculate-y-with-mentions y max-y max-height chat-id suggestions reply)))))
(defn get-bottom-sheet-gesture [context translate-y text-input-ref keyboard-shown min-y max-y shared-height max-height bg-opacity]
(-> (gesture/gesture-pan)
(gesture/on-start
@ -564,18 +595,17 @@
[:f>
(fn []
(let [reply (<sub [:chats/reply-message])
suggestions (<sub [:chat/mention-suggestions])
{window-height :height} (rn/use-window-dimensions)
{:keys [keyboard-shown keyboard-height]} (rn/use-keyboard)
max-y (- window-height (if (> keyboard-height 0) keyboard-height 360) (:top insets)) ; 360 - default height
max-height (- max-y 56 (:bottom insets)) ; 56 - top-bar height
added-value (if reply 38 0) ; increased height of input box needed when reply
min-y (+ min-y added-value)
y (calculate-y context keyboard-shown min-y max-y added-value)
added-value (if (and (not (seq suggestions)) reply) 38 0) ; increased height of input box needed when reply
min-y (+ min-y (when reply 38))
y (get-y-value context keyboard-shown min-y max-y added-value max-height chat-id suggestions reply)
translate-y (reanimated/use-shared-value 0)
shared-height (reanimated/use-shared-value min-y)
bg-opacity (reanimated/use-shared-value 0)
input-content-change (get-input-content-change context translate-y shared-height max-height
bg-opacity keyboard-shown min-y max-y)
bottom-sheet-gesture (get-bottom-sheet-gesture context translate-y (:text-input-ref refs) keyboard-shown
@ -607,19 +637,21 @@
:refs refs
:set-active-panel #()}]]]]
;CONTROLS
[rn/view {:style (styles/new-bottom-sheet-controls insets)}
[quo2.button/button {:icon true :type :outline :size 32} :main-icons2/image]
[rn/view {:width 12}]
[quo2.button/button {:icon true :type :outline :size 32} :main-icons2/reaction]
[rn/view {:flex 1}]
;;SEND button
[rn/view {:ref send-ref :style (when-not (seq (get @input-texts chat-id)) {:width 0 :right -100})}
[quo2.button/button {:icon true :size 32 :accessibility-label :send-message-button
:on-press #(do (swap! context assoc :clear true)
(clear-input chat-id refs)
(re-frame/dispatch [:chat.ui/send-current-message]))}
:main-icons2/arrow-up]]]
(when-not (seq suggestions)
[rn/view {:style (styles/new-bottom-sheet-controls insets)}
[quo2.button/button {:icon true :type :outline :size 32} :main-icons2/image]
[rn/view {:width 12}]
[quo2.button/button {:icon true :type :outline :size 32} :main-icons2/reaction]
[rn/view {:flex 1}]
;;SEND button
[rn/view {:ref send-ref :style (when-not (seq (get @input-texts chat-id)) {:width 0 :right -100})}
[quo2.button/button {:icon true :size 32 :accessibility-label :send-message-button
:on-press #(do (swap! context assoc :clear true)
(clear-input chat-id refs)
(>evt [:chat.ui/send-current-message]))}
:main-icons2/arrow-up]]])
;black background
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity bg-opacity}
(styles/new-bottom-sheet-background window-height))}]]))])))])
(styles/new-bottom-sheet-background window-height))}]
[autocomplete-mentions suggestions]]))])))])

View File

@ -143,7 +143,8 @@
:bottom bottom
:background-color (colors/get-color :ui-background)
:border-top-width 1
:border-top-color (colors/get-color :ui-01)})
:border-top-color (colors/get-color :ui-01)
:z-index 3})
(defn new-input-bottom-sheet [window-height]
(merge {:border-top-left-radius 20
@ -155,7 +156,7 @@
:height window-height
:flex 1
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
:z-index 1000}
:z-index 2}
(if platform/ios?
{:shadow-radius 16
:shadow-opacity 1
@ -176,7 +177,7 @@
{:flex-direction :row
:padding-horizontal 20
:elevation 2
:z-index 2000
:z-index 2
:position :absolute
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
;these 3 props play together, we need this magic to hide message text in the safe area
@ -192,4 +193,4 @@
:bottom 0
:height window-height
:background-color quo2.colors/neutral-95-opa-70
:z-index 500})
:z-index 1})

View File

@ -12,6 +12,9 @@
[status-im.react-native.resources :as resources]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.fast-image :as fast-image]
[status-im.utils.handlers :refer [>evt]]
[quo2.foundations.colors :as quo2.colors]
[quo2.foundations.typography :as typography]
[status-im.ui.components.icons.icons :as icons]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.bottom-sheets.context-drawer :as message-context-drawer]
@ -131,13 +134,14 @@
destination])
"mention"
(conj acc [react/text-class
{:style {:color (cond
(= content-type constants/content-type-system-text) colors/black
: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]])
(conj acc
[react/view {:style {:background-color quo2.colors/primary-50-opa-10 :border-radius 6 :padding-horizontal 3}}
[react/text-class
{:style (merge {:color (if (= content-type constants/content-type-system-text) colors/black (:text-04 @colors/theme))}
(if (= content-type constants/content-type-system-text) typography/font-regular typography/font-medium))
:on-press (when-not (= content-type constants/content-type-system-text)
#(>evt [:chat.ui/show-profile literal]))}
[mention-element literal]]])
"status-tag"
(conj acc [react/text-class
{:style {:color colors/blue
@ -334,7 +338,7 @@
content]
content)
[link-preview/link-preview-wrapper (:links (:content message)) false false]]]
; delivery status
; delivery status
[react/view (style/delivery-status)
[message-delivery-status message]]]))
@ -706,7 +710,7 @@
[message-content-wrapper message
[unknown-content-type message]])
(defn chat-message [{:keys [display-photo? pinned pinned-by] :as message}]
(defn chat-message [{:keys [display-photo? pinned pinned-by mentioned] :as message}]
(let [reactions @(re-frame/subscribe [:chats/message-reactions (:message-id message) (:chat-id message)])
own-reactions (reduce (fn [acc {:keys [emoji-id own]}]
(if own (conj acc emoji-id) acc))
@ -733,7 +737,7 @@
(into #{} (js->clj own-reactions))
#(on-emoji-press %))}]))
on-long-press (atom nil)]
[:<>
[react/view {:style (merge (when mentioned {:background-color quo2.colors/primary-50-opa-5 :border-radius 16 :margin-bottom 4}) {:margin-horizontal 8})}
[->message message {:ref on-long-press
:modal false
:on-long-press on-open-drawer}]

View File

@ -127,7 +127,7 @@
(defn message-author-userpic []
(merge
{:width (+ 16 photos/default-size)} ;; 16 is for the padding
{:padding-left 8
{:padding-left 0
:padding-right 8}))
(def delivery-text
@ -171,21 +171,8 @@
:flex-direction :row-reverse})
(defn message-view
[{:keys [content-type mentioned pinned]}]
[{:keys [content-type]}]
(merge
{:border-radius 10}
(cond
pinned {:background-color colors/pin-background}
(= content-type constants/content-type-system-text) nil
mentioned {:background-color colors/mentioned-background
:border-color colors/mentioned-border
:border-width 1}
(= 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})))

View File

@ -419,7 +419,7 @@
:keyboard-should-persist-taps :handled
:onMomentumScrollBegin state/start-scrolling
:onMomentumScrollEnd state/stop-scrolling
;;TODO https://github.com/facebook/react-native/issues/30034
;;TODO https://github.com/facebook/react-native/issues/30034
:inverted (when platform/ios? true)
:style (when platform/android? {:scaleY -1})})]))
@ -502,7 +502,7 @@
:onMomentumScrollEnd state/stop-scrolling
:scrollEventThrottle 16
:on-scroll on-scroll
;;TODO https://github.com/facebook/react-native/issues/30034
;;TODO https://github.com/facebook/react-native/issues/30034
:inverted (when platform/ios? true)
:style (when platform/android? {:scaleY -1})})]
(when @show-floating-scroll-down-button
@ -602,7 +602,7 @@
[accessory/view {:y position-y
:on-update-inset on-update}
[invitation-bar chat-id]])
[components/autocomplete-mentions text-input-ref max-bottom-space]
[components/autocomplete-mentions-old text-input-ref max-bottom-space]
(when show-input?
;; NOTE: this only accepts two children
[accessory/view {:y position-y