diff --git a/.carve_ignore b/.carve_ignore index 3057dce433..9f72912b66 100644 --- a/.carve_ignore +++ b/.carve_ignore @@ -200,7 +200,7 @@ status-im.utils.platform/isMacOs? status-im.utils.platform/isNix? status-im.utils.platform/isWin? status-im.utils.platform/android-version>= -status-im.utils.debounce/clear-all +utils.debounce/clear-all status-im.transport.db/create-chat status-im.utils.priority-map/priority-map status-im.utils.priority-map/priority-map-by diff --git a/src/quo2/components/navigation/page_nav.cljs b/src/quo2/components/navigation/page_nav.cljs index 4f0b5423e2..0097894ff0 100644 --- a/src/quo2/components/navigation/page_nav.cljs +++ b/src/quo2/components/navigation/page_nav.cljs @@ -3,7 +3,9 @@ [quo2.foundations.colors :as colors] [quo2.components.icon :as icons] [quo2.components.markdown.text :as text] - [clojure.string :as string])) + [clojure.string :as string] + [quo2.components.buttons.button :as button] + [quo2.components.avatars.user-avatar :as user-avatar])) (def ^:private centrify-style {:display :flex @@ -12,12 +14,10 @@ (def ^:private align-left (assoc centrify-style :align-items :flex-start)) -(def ^:private icon-styles (assoc centrify-style :width 32 :height 32 :border-radius 10)) - (defn- big? [size] (= size :big)) (defn- icon-props [color size] - (merge {:size 20 + (merge {:size 20 :container-style {:width (if (big? size) 20 16) @@ -28,32 +28,27 @@ {:color color} {:no-color true}))) -(defn render-left-section [{:keys [on-press icon - icon-color icon-background-color]} - put-middle-section-on-left?] +(defn left-section-view [{:keys [on-press icon accessibility-label type] :or {type :grey}} + put-middle-section-on-left?] [rn/view {:style (merge - icon-styles - {:background-color icon-background-color - :width 32 - :height 32} + {:accessibility-label accessibility-label} (when put-middle-section-on-left? {:margin-right 5}))} - [rn/touchable-opacity {:on-press on-press} - [icons/icon icon (icon-props icon-color :big)]]]) + [button/button {:on-press on-press :icon true :type type :size 32} + icon]]) (defn- mid-section-comp [{:keys [description-img description-user-icon horizontal-description? text-secondary-color align-mid? text-color icon main-text type description]}] - [rn/view {:style (assoc - centrify-style - :flex-direction :row - :margin-horizontal 2)} + [rn/view {:style (assoc centrify-style + :flex-direction :row + :margin-horizontal 2)} (when (or (and (not horizontal-description?) align-mid? (not= :text-with-description type)) (and (or description-img description-user-icon) (not icon))) (if description-img - [rn/view {:margin-right 8} + [rn/view {:margin-right 8} [description-img]] [rn/image {:source {:uri description-user-icon} :style {:width 32 @@ -77,75 +72,69 @@ horizontal-description? (assoc :margin-left 4 :margin-top 2))} description])]]) -(defn- render-mid-section +(defn- mid-section-view [{:keys [horizontal-description? one-icon-align-left? type left-align? - main-text right-icon main-text-icon-color left-icon] :as props}] - (let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95) - text-secondary-color (if (colors/dark?) colors/neutral-40 colors/neutral-50) + main-text right-icon main-text-icon-color left-icon on-press avatar] :as props}] + (let [text-color (if (colors/dark?) colors/neutral-5 colors/neutral-95) + text-secondary-color (if (colors/dark?) colors/neutral-40 colors/neutral-50) component-instance [mid-section-comp (assoc props :text-secondary-color text-secondary-color)]] - [rn/view {:style (merge - (if left-align? - align-left - centrify-style) - {:flex 1 - :margin-left 4 - :text-align-vertical :center})} - (case type - :text-only [text/text {:size :paragraph-1 - :weight :semi-bold - :style {:color text-color}} - main-text] - :text-with-two-icons [rn/view {:style (assoc centrify-style :flex-direction :row)} - [icons/icon left-icon - (icon-props main-text-icon-color :big)] - [text/text {:size :paragraph-1 - :weight :semi-bold - :style {:padding-horizontal 4 - :color text-color}} - main-text] - [icons/icon right-icon - (icon-props main-text-icon-color :big)]] - :text-with-one-icon [rn/view {:style {:flex-direction :row}} - (if one-icon-align-left? - [rn/view {:style {:flex-direction :row - :align-items :center}} - (when horizontal-description? - [icons/icon left-icon - (icon-props main-text-icon-color :big)]) - component-instance] - [rn/view {:style {:flex-direction :row - :align-items :center}} - component-instance - (when horizontal-description? - [icons/icon left-icon - (icon-props main-text-icon-color :big)])])] - :text-with-description component-instance)])) + [rn/touchable-opacity {:on-press on-press} + [rn/view {:style (merge + (if left-align? + align-left + centrify-style) + {:flex 1 + :margin-left 4 + :text-align-vertical :center})} + (case type + :text-only [text/text {:size :paragraph-1 + :weight :semi-bold + :style {:color text-color}} + main-text] + :user-avatar [rn/view {:style (assoc centrify-style :flex-direction :row)} + [user-avatar/user-avatar avatar] + [text/text {:size :paragraph-1 + :weight :semi-bold + :style {:padding-horizontal 4 + :color text-color}} + main-text]] + :text-with-two-icons [rn/view {:style (assoc centrify-style :flex-direction :row)} + [icons/icon left-icon + (icon-props main-text-icon-color :big)] + [text/text {:size :paragraph-1 + :weight :semi-bold + :style {:padding-horizontal 4 + :color text-color}} + main-text] + [icons/icon right-icon + (icon-props main-text-icon-color :big)]] + :text-with-one-icon [rn/view {:style {:flex-direction :row}} + (if one-icon-align-left? + [rn/view {:style {:flex-direction :row + :align-items :center}} + (when horizontal-description? + [icons/icon left-icon + (icon-props main-text-icon-color :big)]) + component-instance] + [rn/view {:style {:flex-direction :row + :align-items :center}} + component-instance + (when horizontal-description? + [icons/icon left-icon + (icon-props main-text-icon-color :big)])])] + :text-with-description component-instance)]])) -(defn- right-section-icon - [{:keys [background-color icon icon-color push-to-the-left?] :or {push-to-the-left? false}}] - [rn/view {:style (assoc - icon-styles - :background-color background-color - :width 32 - :height 32 - :margin-right (if push-to-the-left? 8 0))} - [icons/icon icon (icon-props icon-color :big)]]) - -(defn- render-right-section [right-section-buttons] - [rn/view {:style (assoc - centrify-style - :flex-direction :row - :flex 1 - :justify-content :flex-end)} +(defn- right-section-view [right-section-buttons] + [rn/view {:style (assoc centrify-style + :flex-direction :row + :flex 1 + :justify-content :flex-end)} (let [last-icon-index (-> right-section-buttons count dec)] - (map-indexed (fn [index {:keys [icon background-color icon-color on-press]}] + (map-indexed (fn [index {:keys [icon on-press type] :or {type :grey}}] ^{:key index} - [rn/touchable-opacity {:on-press on-press} - [right-section-icon - {:icon icon - :background-color background-color - :icon-color icon-color - :push-to-the-left? (not= index last-icon-index)}]]) + [rn/view {:style {:margin-right (if (not= index last-icon-index) 8 0)}} + [button/button {:on-press on-press :icon true :type type :size 32} + icon]]) right-section-buttons))]) (defn page-nav @@ -157,7 +146,7 @@ :page-nav-color color :page-nav-background-uri image-uri :mid-section - {:type one-of :text-only :text-with-two-icons :text-with-one-icon :text-with-description + {:type one-of :text-only :text-with-two-icons :text-with-one-icon :text-with-description :user-avatar :icon icon :main-text string :left-icon icon @@ -170,13 +159,15 @@ :main-text-icon-color color } :left-section - {:on-press event + {:type button-type + :on-press event :icon icon :icon-color color :icon-background-color color } :right-section-buttons vector of - {:on-press event + {:type button-type + :on-press event :icon icon :icon-color color :icon-background-color color @@ -199,27 +190,29 @@ :one-icon-align-left? one-icon-align-left? :right-icon (:right-icon mid-section) :icon (:icon mid-section) - :left-icon (:left-icon mid-section)}] + :left-icon (:left-icon mid-section) + :avatar (:avatar mid-section)}] [rn/view {:style (cond-> {:display :flex :flex-direction :row ;; iPhone 11 Pro's height in Figma divided by Component height 56/1125 :align-items :center :padding-horizontal 20 + :height 56 :justify-content :space-between} page-nav-background-uri (assoc :background-color page-nav-color) page-nav-color (assoc :background page-nav-background-uri))} [rn/view {:style {:flex 1 :flex-direction :row :align-items :center}} - (render-left-section left-section put-middle-section-on-left?) + [left-section-view left-section put-middle-section-on-left?] (when put-middle-section-on-left? - [render-mid-section (assoc mid-section-props - :left-align? true - :description (:description mid-section) - :description-color (:description-color mid-section) - :description-icon (:description-icon mid-section) - :align-mid? align-mid? - :description-user-icon (:description-user-icon mid-section))])] + [mid-section-view (assoc mid-section-props + :left-align? true + :description (:description mid-section) + :description-color (:description-color mid-section) + :description-icon (:description-icon mid-section) + :align-mid? align-mid? + :description-user-icon (:description-user-icon mid-section))])] (when-not put-middle-section-on-left? - [render-mid-section mid-section-props]) - (render-right-section right-section-buttons)])) + [mid-section-view mid-section-props]) + [right-section-view right-section-buttons]])) diff --git a/src/react_native/core.cljs b/src/react_native/core.cljs index 346da6c7b9..925f5aa533 100644 --- a/src/react_native/core.cljs +++ b/src/react_native/core.cljs @@ -3,7 +3,8 @@ ["react-native" :as react-native] ["@react-native-community/blur" :as blur] [react-native.flat-list :as flat-list] - [react-native.section-list :as section-list])) + [react-native.section-list :as section-list] + [react-native.platform :as platform])) (def app-state ^js (.-AppState ^js react-native)) (def blur-view (reagent/adapt-react-class (.-BlurView blur))) @@ -55,3 +56,17 @@ (js->clj (.get (.-Dimensions ^js react-native) "window") :keywordize-keys true)) (def status-bar (.-StatusBar ^js react-native)) + +(defn hw-back-add-listener [callback] + (.addEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback)) + +(defn hw-back-remove-listener [callback] + (.removeEventListener (.-BackHandler ^js react-native) "hardwareBackPress" callback)) + +(def keyboard-avoiding-view-class (reagent/adapt-react-class (.-KeyboardAvoidingView react-native))) + +(defn keyboard-avoiding-view [props & children] + (into [keyboard-avoiding-view-class + (merge (when platform/ios? {:behavior :padding}) + props)] + children)) diff --git a/src/status_im/browser/core.cljs b/src/status_im/browser/core.cljs index c99f4d799e..9ce5697981 100644 --- a/src/status_im/browser/core.cljs +++ b/src/status_im/browser/core.cljs @@ -22,7 +22,7 @@ [status-im.bottom-sheet.core :as bottom-sheet] [status-im.browser.webview-ref :as webview-ref] ["eth-phishing-detect" :as eth-phishing-detect] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.browser.eip3085 :as eip3085] [status-im.browser.eip3326 :as eip3326])) diff --git a/src/status_im/ui/screens/add_new/new_chat/views.cljs b/src/status_im/ui/screens/add_new/new_chat/views.cljs index 925cbbd489..091636b6ab 100644 --- a/src/status_im/ui/screens/add_new/new_chat/views.cljs +++ b/src/status_im/ui/screens/add_new/new_chat/views.cljs @@ -11,7 +11,7 @@ [status-im.ui.components.list.views :as list] [status-im.ui.components.react :as react] [status-im.ui.components.topbar :as topbar] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.utils.utils :as utils] [reagent.core :as reagent] [quo.react-native :as rn] diff --git a/src/status_im/ui/screens/browser/eip3326/sheet.cljs b/src/status_im/ui/screens/browser/eip3326/sheet.cljs index a215ec97f8..5cb88848a8 100644 --- a/src/status_im/ui/screens/browser/eip3326/sheet.cljs +++ b/src/status_im/ui/screens/browser/eip3326/sheet.cljs @@ -5,7 +5,7 @@ [status-im.ui.components.icons.icons :as icons] [status-im.ui.components.react :as react] [status-im.ui.screens.browser.styles :as styles] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.network.core :as network] [quo.design-system.colors :as colors] [quo.core :as quo]) diff --git a/src/status_im/ui/screens/browser/views.cljs b/src/status_im/ui/screens/browser/views.cljs index 486ade4f36..77bd7fa6ab 100644 --- a/src/status_im/ui/screens/browser/views.cljs +++ b/src/status_im/ui/screens/browser/views.cljs @@ -15,7 +15,7 @@ [status-im.ui.screens.browser.permissions.views :as permissions.views] [status-im.ui.screens.browser.site-blocked.views :as site-blocked.views] [status-im.ui.screens.browser.styles :as styles] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.utils.http :as http] [status-im.utils.js-resources :as js-res] [status-im.ui.components.permissions :as components.permissions] diff --git a/src/status_im/ui/screens/chat/group.cljs b/src/status_im/ui/screens/chat/group.cljs index 8b441fa156..c00b54e86a 100644 --- a/src/status_im/ui/screens/chat/group.cljs +++ b/src/status_im/ui/screens/chat/group.cljs @@ -8,7 +8,7 @@ [status-im.i18n.i18n :as i18n] [status-im.ui.components.list-selection :as list-selection] [quo.design-system.colors :as colors] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.utils.platform :as platform]) (:require-macros [status-im.utils.views :refer [defview letsubs]])) diff --git a/src/status_im/ui/screens/chat/stickers/views.cljs b/src/status_im/ui/screens/chat/stickers/views.cljs index 3a6715b69d..5dfebee103 100644 --- a/src/status_im/ui/screens/chat/stickers/views.cljs +++ b/src/status_im/ui/screens/chat/stickers/views.cljs @@ -8,7 +8,7 @@ [status-im.i18n.i18n :as i18n] [quo.core :as quo] [status-im.ui.screens.chat.stickers.styles :as styles] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.ui.components.fast-image :as fast-image])) (def icon-size 28) diff --git a/src/status_im/ui/screens/chat/views.cljs b/src/status_im/ui/screens/chat/views.cljs index 6fb32948a1..4b3e369d6b 100644 --- a/src/status_im/ui/screens/chat/views.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -35,7 +35,7 @@ [status-im.utils.platform :as platform] [status-im.utils.utils :as utils] [status-im.ui.screens.chat.sheets :as sheets] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im2.navigation.state :as navigation.state] [status-im.react-native.resources :as resources])) diff --git a/src/status_im/ui/screens/communities/create.cljs b/src/status_im/ui/screens/communities/create.cljs index f3a50ecb98..c7122a9585 100644 --- a/src/status_im/ui/screens/communities/create.cljs +++ b/src/status_im/ui/screens/communities/create.cljs @@ -11,7 +11,7 @@ [status-im.ui.components.react :as react] [status-im.ui.screens.communities.membership :as memberships] [status-im.ui.components.icons.icons :as icons] - [status-im.utils.debounce :as debounce])) + [utils.debounce :as debounce])) (def max-name-length 30) (def max-description-length 140) diff --git a/src/status_im/ui/screens/communities/create_category.cljs b/src/status_im/ui/screens/communities/create_category.cljs index 937ecc6cd1..bb071ad7fa 100644 --- a/src/status_im/ui/screens/communities/create_category.cljs +++ b/src/status_im/ui/screens/communities/create_category.cljs @@ -4,7 +4,7 @@ [status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.react :as react] [quo.core :as quo] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.i18n.i18n :as i18n] [clojure.string :as str] [status-im.ui.components.list.views :as list] diff --git a/src/status_im/ui/screens/communities/create_channel.cljs b/src/status_im/ui/screens/communities/create_channel.cljs index bcb2889d45..5a03580844 100644 --- a/src/status_im/ui/screens/communities/create_channel.cljs +++ b/src/status_im/ui/screens/communities/create_channel.cljs @@ -5,7 +5,7 @@ [status-im.i18n.i18n :as i18n] [status-im.ui.components.toolbar :as toolbar] [status-im.communities.core :as communities] - [status-im.utils.debounce :as debounce] + [utils.debounce :as debounce] [status-im.utils.handlers :refer [>evt evt evt]] - [status-im.ui.components.icons.icons :as icons] - [status-im.ui2.screens.chat.messages.pinned-message :as pinned-message] - [re-frame.db] - [quo2.components.navigation.floating-shell-button :as floating-shell-button] - [status-im.ui2.screens.chat.messages.message :as message])) - -(defn topbar-content [] - (let [window-width (evt [:close-chat]) - (>evt [:navigate-back]))} - [icons/icon :main-icons/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]]) - -(defn search-button [] - [quo2.button/button {:type :grey - :size 32 - :width 32 - :accessibility-label "search-button"} - [icons/icon :main-icons/search {:color (colors/theme-colors colors/neutral-100 colors/white)}]]) - -(defn navigate-back-handler [] - (when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat)) - (react/hw-back-remove-listener navigate-back-handler) - (>evt [:close-chat]) - (>evt [:navigate-back]))) - -(defn chat-render [] - (let [{:keys [chat-id show-input?] :as chat} - ;;we want to react only on these fields, do not use full chat map here - (interceptor get-coeffect]] [taoensso.timbre :as log] - [status-im.utils.debounce :as debounce])) + [utils.debounce :as debounce])) (defn- pretty-print-event [ctx] (let [[first _] (get-coeffect ctx :event)] diff --git a/src/status_im2/contexts/chat/messages/view.cljs b/src/status_im2/contexts/chat/messages/view.cljs new file mode 100644 index 0000000000..9afb638f66 --- /dev/null +++ b/src/status_im2/contexts/chat/messages/view.cljs @@ -0,0 +1,86 @@ +(ns status-im2.contexts.chat.messages.view + (:require [reagent.core :as reagent] + [re-frame.db] + [i18n.i18n :as i18n] + [react-native.core :as rn] + [utils.re-frame :as rf] + [utils.debounce :as debounce] + [quo2.core :as quo] + + [status-im2.navigation.state :as navigation.state] + + ;;TODO move to status-im2 + [status-im.ui2.screens.chat.composer.view :as composer] + [status-im.ui2.screens.chat.messages.view :as messages] + [status-im.ui2.screens.chat.messages.pinned-message :as pinned-message] + [status-im.ui2.screens.chat.messages.message :as message])) + +(defn navigate-back-handler [] + (when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat)) + (rn/hw-back-remove-listener navigate-back-handler) + (rf/dispatch [:close-chat]) + (rf/dispatch [:navigate-back]))) + +(defn page-nav [] + (let [{:keys [group-chat chat-id chat-name emoji]} (rf/sub [:chats/current-chat]) + display-name (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) + online? (rf/sub [:visibility-status-updates/online? chat-id]) + contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id])) + photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path chat-id]))] + [quo/page-nav + {:align-mid? true + + :mid-section + (if group-chat + {:type :text-only + :main-text (str emoji " " chat-name)} + {:type :user-avatar + :avatar {:full-name display-name + :online? online? + :profile-picture photo-path + :size :medium} + :main-text display-name + :on-press #(debounce/dispatch-and-chill [:chat.ui/show-profile chat-id] 1000)}) + + :left-section + {:on-press #(do + (rf/dispatch [:close-chat]) + (rf/dispatch [:navigate-back])) + :icon :i/arrow-left + :accessibility-label :back-button} + + :right-section-buttons + [{:on-press #() ;; TODO not implemented + :icon :i/options + :accessibility-label :options-button}]}])) + +(defn chat-render [] + (let [;;we want to react only on these fields, do not use full chat map here + {:keys [chat-id show-input?] :as chat} (rf/sub [:chats/current-chat-chat-view]) + mutual-contact-requests-enabled? (rf/sub [:mutual-contact-requests/enabled?])] + [rn/keyboard-avoiding-view {:style {:flex 1}} + [page-nav] + [pinned-message/pin-limit-popover chat-id message/pinned-messages-list] + [message/pinned-banner chat-id] + ;;MESSAGES LIST + [messages/messages-view + {:chat chat + :mutual-contact-requests-enabled? mutual-contact-requests-enabled? + :show-input? show-input? + :bottom-space 15}] + ;;INPUT COMPOSER + (when show-input? + [composer/composer chat-id]) + [quo/floating-shell-button + {:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to]) + :label (i18n/label :t/jump-to)}} + {:position :absolute + :bottom 117}]])) + +(defn chat [] + (reagent/create-class + {:component-did-mount (fn [] + (rn/hw-back-remove-listener navigate-back-handler) + (rn/hw-back-add-listener navigate-back-handler)) + :component-will-unmount (fn [] (rn/hw-back-remove-listener navigate-back-handler)) + :reagent-render chat-render})) diff --git a/src/status_im2/navigation/screens.cljs b/src/status_im2/navigation/screens.cljs index a73ba82f38..c1d1415b74 100644 --- a/src/status_im2/navigation/screens.cljs +++ b/src/status_im2/navigation/screens.cljs @@ -4,9 +4,9 @@ [status-im2.contexts.communities.overview.view :as communities.overview] [status-im2.contexts.shell.view :as shell] [status-im2.contexts.quo-preview.main :as quo.preview] + [status-im2.contexts.chat.messages.view :as chat] - ;; TODO remove when not used anymore\ - [status-im.ui2.screens.chat.view :as chat] + ;; TODO remove when not used anymore [status-im.ui.screens.screens :as old-screens])) (def components diff --git a/src/status_im/utils/debounce.cljs b/src/utils/debounce.cljs similarity index 93% rename from src/status_im/utils/debounce.cljs rename to src/utils/debounce.cljs index f66081b57a..eb9389b904 100644 --- a/src/status_im/utils/debounce.cljs +++ b/src/utils/debounce.cljs @@ -1,4 +1,4 @@ -(ns status-im.utils.debounce +(ns utils.debounce (:require [re-frame.core :as re-frame])) (def timeout (atom {})) @@ -27,4 +27,4 @@ (when-not (get @chill event-key) (swap! chill assoc event-key true) (js/setTimeout #(swap! chill assoc event-key false) time) - (re-frame/dispatch event)))) \ No newline at end of file + (re-frame/dispatch event))))