Photo Selector (1) (#14426)

* feat: photo-selector (1)
This commit is contained in:
Omar Basem 2022-11-24 15:29:54 +04:00 committed by GitHub
parent e61889f16c
commit 14c243803f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 238 additions and 35 deletions

View File

@ -10,6 +10,8 @@
:position :absolute
:right 22
:border-radius 6
:justify-content :center
:align-items :center
:background-color (colors/theme-colors colors/primary-50 colors/primary-60)}
style)}
[rn/text {:style (merge typography/font-medium typography/label {:color colors/white :text-align :center})} count]]))

View File

@ -380,7 +380,7 @@
contact-request @(re-frame/subscribe [:chats/sending-contact-request])]
[rn/view {:style (styles/toolbar)
:on-layout on-chat-toolbar-layout}
;;EXTENSIONS and IMAGE buttons
;; EXTENSIONS and IMAGE buttons
[actions extensions image show-send actions-ref active-panel set-active-panel contact-request]
[rn/view {:style (styles/input-container contact-request)}
[send-image]
@ -389,14 +389,14 @@
:sending-image sending-image
:refs refs
:set-active-panel set-active-panel}]
;;SEND button
;; SEND button
[rn/view {:ref send-ref :style (when-not show-send {:width 0 :right -100})}
(when send
[send-button #(do (clear-input chat-id refs)
(re-frame/dispatch [:chat.ui/send-current-message]))
contact-request])]
;;STICKERS and AUDIO buttons
;; STICKERS and AUDIO buttons
(when-not @(re-frame/subscribe [:chats/edit-message])
[rn/view {:style (merge {:flex-direction :row} (when show-send {:width 0 :right -100}))
:ref sticker-ref}
@ -411,4 +411,4 @@
:accessibility-label :show-audio-message-icon
:active active-panel
:input-focus #(input-focus text-input-ref)
:set-active set-active-panel}])])]]]))))
:set-active set-active-panel}])])]]]))))

View File

@ -115,7 +115,8 @@
[status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send]
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]
[status-im.ui2.screens.chat.group-details.view :as group-details]))
[status-im.ui2.screens.chat.group-details.view :as group-details]
[status-im.ui2.screens.chat.photo-selector.view :as photo-selector]))
(defn right-button-options [id icon]
{:id id
@ -211,6 +212,10 @@
:options {:topBar {:visible false}}
:component pin-messages/pinned-messages}
{:name :photo-selector
:options {:topBar {:visible false}}
:component photo-selector/photo-selector}
{:name :group-chat-profile
;;TODO animated-header
:options {:topBar {:visible false}}

View File

@ -12,7 +12,11 @@
[oops.core :refer [oget]]
[quo.react]
[clojure.string :as string]
[status-im.ui2.screens.chat.composer.mentions :as mentions]))
[status-im.ui2.screens.chat.composer.mentions :as mentions]
[status-im.ui.components.permissions :as permissions]
[status-im.ui2.screens.chat.photo-selector.view :as photo-selector]
[status-im.utils.utils :as utils]
[i18n.i18n :as i18n]))
(defn calculate-y [context keyboard-shown min-y max-y added-value]
(if keyboard-shown
@ -28,12 +32,12 @@
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))
(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)))
@ -115,33 +119,33 @@
(defn composer [chat-id]
[safe-area/consumer
(fn [insets]
(let [min-y 112
context (atom {:y min-y ;current y value
:min-y min-y ;minimum y value
:dy 0 ;used for gesture
:pdy 0 ;used for gesture
:state :min ;:min, :custom-chat-available, :custom-chat-unavailable, :max
:clear false})
(let [min-y 112
context (atom {:y min-y ;current y value
:min-y min-y ;minimum y value
:dy 0 ;used for gesture
:pdy 0 ;used for gesture
:state :min ;:min, :custom-chat-available, :custom-chat-unavailable, :max
:clear false})
keyboard-was-shown (atom false)
text-input-ref (quo.react/create-ref)
send-ref (quo.react/create-ref)
refs {:send-ref send-ref
:text-input-ref text-input-ref}]
text-input-ref (quo.react/create-ref)
send-ref (quo.react/create-ref)
refs {:send-ref send-ref
:text-input-ref text-input-ref}]
(fn []
[:f>
(fn []
(let [reply (<sub [:chats/reply-message])
suggestions (<sub [:chat/mention-suggestions])
(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 (Math/abs (- max-y 56 (:bottom insets))) ; 56 - top-bar height
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)
max-y (- window-height (if (> keyboard-height 0) keyboard-height 360) (:top insets)) ; 360 - default height
max-height (Math/abs (- max-y 56 (:bottom insets))) ; 56 - top-bar height
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)
@ -176,7 +180,16 @@
;CONTROLS
(when-not (seq suggestions)
[rn/view {:style (styles/bottom-sheet-controls insets)}
[quo2.button/button {:icon true :type :outline :size 32} :i/image]
[quo2.button/button {:on-press (fn []
(permissions/request-permissions
{:permissions [:read-external-storage :write-external-storage]
:on-allowed #(re-frame/dispatch [:bottom-sheet/show-sheet
{:content [photo-selector/photo-selector]}])
:on-denied (fn []
(utils/set-timeout
#(utils/show-popup (i18n/label :t/error)
(i18n/label :t/external-storage-denied)) 50))}))
:icon true :type :outline :size 32} :i/image]
[rn/view {:width 12}]
[quo2.button/button {:icon true :type :outline :size 32} :i/reaction]
[rn/view {:flex 1}]

View File

@ -0,0 +1,73 @@
(ns status-im.ui2.screens.chat.photo-selector.style
(:require [quo2.foundations.colors :as colors]))
(defn remove-photo-container []
{:width 14
:height 14
:border-radius 7
:background-color colors/neutral-50
:position :absolute
:top -7
:right -7
:justify-content :center
:align-items :center})
(defn gradient-container [safe-area]
{:width "100%"
:height (+ (:bottom safe-area) 161)
:position :absolute
:bottom 0})
(defn buttons-container [safe-area]
{:flex-direction :row
:justify-content :space-between
:padding-horizontal 20
:bottom (+ (:bottom safe-area) 33)})
(defn clear-container []
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:position :absolute
:align-self :flex-end
:padding-horizontal 12
:padding-vertical 5
:right 20
:border-radius 10})
(defn camera-button-container []
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:width 32
:height 32
:border-radius 10
:justify-content :center
:align-items :center
:margin-left 20
:margin-bottom 24})
(defn chevron-container []
{:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:width 14
:height 14
:border-radius 7
:justify-content :center
:align-items :center
:margin-left 7
:margin-top 4})
(defn image [window-width index]
{:width (- (/ window-width 3) 0.67)
:height (/ window-width 3)
:margin-left (when (not= (mod index 3) 0) 1)
:margin-bottom 1})
(defn overlay [window-width]
{:position :absolute
:width (- (/ window-width 3) 0.67)
:height (/ window-width 3)
:background-color (colors/theme-colors colors/white-opa-40 colors/neutral-80-opa-40)})
(defn image-count []
{:width 24
:height 24
:border-radius 8
:top 8
:right 8})

View File

@ -0,0 +1,108 @@
(ns status-im.ui2.screens.chat.photo-selector.view
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[quo.components.safe-area :as safe-area]
[quo2.core :as quo2]
[i18n.i18n :as i18n]
[utils.re-frame :as rf]
[reagent.core :as reagent]
[quo2.components.notifications.info-count :as info-count]
[react-native.linear-gradient :as linear-gradient]
[status-im.ui2.screens.chat.photo-selector.style :as style]
[status-im.utils.core :as utils]))
(def selected (reagent/atom []))
(defn small-image [item]
[rn/view
[rn/image {:source {:uri item}
:style {:width 56
:height 56
:border-radius 8
:margin-bottom 20}}]
[rn/touchable-opacity
{:on-press (fn [] (reset! selected (vec (remove #(= % item) @selected))))
:style (style/remove-photo-container)}
[quo2/icon :i/close {:color colors/white :size 12}]]])
(defn bottom-gradient []
[:f>
(fn []
(let [safe-area (safe-area/use-safe-area)]
(when (pos? (count @selected))
[linear-gradient/linear-gradient
{:colors [:black :transparent]
:start {:x 0 :y 1}
:end {:x 0 :y 0}
:style (style/gradient-container safe-area)}
[rn/flat-list {:key-fn (fn [item] item)
:render-fn small-image
:data @selected
:horizontal true
:content-container-style {:padding-horizontal 20 :margin-top 12}
:separator [rn/view {:style {:width 12}}]}]
[rn/view {:style (style/buttons-container safe-area)}
[quo2/button {:type :grey
:style {:flex 0.48}
:on-press #(js/alert "Add text: to be implemented")}
(i18n/label :t/add-text)]
[quo2/button {:style {:flex 0.48}
:before :send
:on-press #(do
(rf/dispatch [:chat.ui/send-current-message])
(reset! selected [])
(rf/dispatch [:bottom-sheet/hide]))}
(str (i18n/label :t/send) " " (when (> (count @selected) 1) (count @selected)))]]])))])
(defn clear-button []
(when (pos? (count @selected))
[rn/touchable-opacity {:on-press #(reset! selected [])
:style (style/clear-container)}
[quo2/text {:weight :medium} (i18n/label :t/clear)]]))
(defn image [item index window-width]
[rn/touchable-opacity
{:active-opacity 1
:on-press (fn []
(if (some #{item} @selected)
(do
(reset! selected (vec (remove #(= % item) @selected)))
(rf/dispatch [:chat.ui/image-unselected item]))
(do
(swap! selected conj item)
(rf/dispatch [:chat.ui/camera-roll-pick item]))))}
[rn/image {:source {:uri item}
:style (style/image window-width index)}]
(when (some #{item} @selected)
[rn/view {:style (style/overlay window-width)}])
(when (some #{item} @selected)
[info-count/info-count (+ (utils/first-index #(= item %) @selected) 1) (style/image-count)])])
(defn photo-selector []
(rf/dispatch [:chat.ui/camera-roll-get-photos 20])
[:f>
(fn []
(let [{window-height :height
window-width :width} (rn/use-window-dimensions)
safe-area (safe-area/use-safe-area)
camera-roll-photos (rf/sub [:camera-roll-photos])]
[rn/view {:style {:height (- window-height (:top safe-area))}}
[rn/touchable-opacity
{:on-press #(js/alert "Camera: not implemented")
:style (style/camera-button-container)}
[quo2/icon :i/camera {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[rn/view {:style {:flex-direction :row
:position :absolute
:align-self :center}}
[quo2/text {:weight :medium} (i18n/label :t/recent)]
[rn/view {:style (style/chevron-container)}
[quo2/icon :i/chevron-down {:color (colors/theme-colors colors/neutral-100 colors/white)}]]]
[clear-button]
[rn/flat-list {:key-fn (fn [item] item)
:render-fn (fn [item index] (image item index window-width))
:data camera-roll-photos
:num-columns 3
:content-container-style {:width "100%"
:padding-bottom (+ (:bottom safe-area) 100)}
:style {:border-radius 20}}]
[bottom-gradient]]))])

View File

@ -1868,5 +1868,7 @@
"biu": "BIU",
"bold": "Bold",
"italic": "Italic",
"strikethrough": "Strikethrough"
"strikethrough": "Strikethrough",
"add-text": "Add text",
"send": "Send"
}