move messages screen to status-im2 (#14530)

* move messages screen to status-im2
This commit is contained in:
flexsurfer 2022-12-13 13:27:13 +01:00 committed by GitHub
parent 11d02c1057
commit c7a371c104
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 535 additions and 340 deletions

View File

@ -1,6 +1,6 @@
(ns status-im.ui.screens.chat.components.messages-skeleton
(:require [status-im.ui.components.react :as react]
[react-native.core :as rn]
(ns quo2.components.loaders.skeleton
(:require [react-native.core :as rn]
[react-native.masked-view :as masked-view]
[reagent.core :as reagent]
[react-native.reanimated :as reanimated]
[quo2.foundations.colors :as colors]))
@ -34,7 +34,7 @@
{:width window-width
:height "100%"})]
(reanimated/animate-shared-value-with-repeat translate-x window-width 1000 :linear (- 1) false)
[react/masked-view
[masked-view/masked-view
{:style {:height message-skeleton-height}
:maskElement (reagent/as-element
[rn/view {:style {:height message-skeleton-height
@ -67,7 +67,7 @@
:end {:x 1 :y 0}
:style animated-gradient-style}]]]))])
(defn messages-skeleton [parent-height]
(defn skeleton [parent-height]
(let [number-of-skeletons (int (Math/floor (/ parent-height message-skeleton-height)))]
[rn/view {:style {:background-color (colors/theme-colors
colors/white

View File

@ -40,7 +40,8 @@
quo2.components.tags.status-tags
quo2.components.navigation.page-nav
quo2.components.selectors.disclaimer
quo2.components.selectors.selectors))
quo2.components.selectors.selectors
quo2.components.loaders.skeleton))
(def button quo2.components.buttons.button/button)
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
@ -68,6 +69,8 @@
(def page-nav quo2.components.navigation.page-nav/page-nav)
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
(def checkbox quo2.components.selectors.selectors/checkbox)
(def skeleton quo2.components.loaders.skeleton/skeleton)
;;;; AVATAR
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
@ -88,10 +91,7 @@
(def discover-card quo2.components.community.discover-card/discover-card)
(def token-gating quo2.components.community.token-gating/token-gating)
;;;; DIVIDERS
(def divider-label quo2.components.dividers.divider-label/divider-label)
(def new-messages quo2.components.dividers.new-messages/new-messages)

View File

@ -5,5 +5,9 @@
(def os (when platform (.-OS ^js platform)))
(def version (when platform (.-Version ^js platform)))
(def android? (= os "android"))
(def ios? (= os "ios"))
(def low-device? (and android? (< version 29)))

View File

@ -1,7 +1,6 @@
(ns status-im.chat.models.delete-message
(:require [re-frame.core :as re-frame]
[status-im.chat.models.message-list :as message-list]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.utils.datetime :as datetime]
[status-im.utils.fx :as fx]
@ -81,7 +80,7 @@
:on-error #(log/error "failed to delete message " {:message-id message-id :error %})
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}
:dispatch (and (get-in db [:pin-messages chat-id message-id])
[::models.pin-message/send-pin-message {:chat-id chat-id :message-id message-id :pinned false}]))))
[:pin-message/send-pin-message {:chat-id chat-id :message-id message-id :pinned false}]))))
(defn- filter-pending-send-messages
"traverse all messages find not yet synced deleted? messages"

View File

@ -7,7 +7,6 @@
[status-im.chat.models.message-list :as message-list]
[taoensso.timbre :as log]
[status-im.ethereum.json-rpc :as json-rpc]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.notifications-center.core :as notification-center]))
(defn cursor->clock-value
@ -176,5 +175,5 @@
{:db (assoc-in db [:pagination-info chat-id :messages-initialized?] now)
:utils/dispatch-later [{:ms 50 :dispatch [:chat.ui/mark-all-read-pressed chat-id]}
(when-not (get-in cofx [:db :chats chat-id :public?])
{:ms 100 :dispatch [::models.pin-message/load-pin-messages chat-id]})]}
{:ms 100 :dispatch [:pin-message/load-pin-messages chat-id]})]}
(load-more-messages chat-id true))))

View File

@ -2,7 +2,7 @@
status-im.transport.message.core
(:require [status-im.activity-center.core :as activity-center]
[status-im.chat.models.message :as models.message]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im2.contexts.chat.messages.pin.events :as messages.pin]
[status-im.chat.models :as models.chat]
[status-im.chat.models.reactions :as models.reactions]
[status-im2.setup.config :as config]
@ -117,7 +117,7 @@
(js-delete response-js "pinMessages")
(fx/merge cofx
(process-next response-js sync-handler)
(models.pin-message/receive-signal (map data-store.messages/<-rpc pin-messages))))
(messages.pin/receive-signal (map data-store.messages/<-rpc pin-messages))))
(seq removed-chats)
(let [removed-chats-clj (types/js->clj removed-chats)]

View File

@ -7,7 +7,8 @@
[status-im.ui.screens.keycard.views :as keycard]
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[status-im.ui.screens.multiaccounts.key-storage.views :as key-storage]
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]))
[status-im.ui.screens.multiaccounts.recover.views :as recover.views]
[status-im2.contexts.chat.messages.pin.list.view :as pin.list]))
(defn bottom-sheet []
(let [{:keys [show? view options]} @(re-frame/subscribe [:bottom-sheet])
@ -41,7 +42,10 @@
(merge recover.views/bottom-sheet)
(= view :migrate-account-password)
(merge key-storage/migrate-account-password))]
(merge key-storage/migrate-account-password)
(= view :pinned-messages-list)
(merge {:content pin.list/pinned-messages-list}))]
[quo/bottom-sheet opts
(when content
[content (when options options)])]))

View File

@ -4,8 +4,8 @@
[re-frame.core :as re-frame]
[status-im.i18n.i18n :as i18n]
[status-im.utils.datetime :as datetime]
[status-im.ui.screens.chat.components.messages-skeleton :as messages-skeleton]
[status-im.ui.screens.chat.styles.input.gap :as style]))
[status-im.ui.screens.chat.styles.input.gap :as style]
[quo2.core :as quo2]))
(defn on-press
[chat-id gap-ids]
@ -29,7 +29,7 @@
:style {:height (if in-progress? window-height 48)}}
[react/view {:style style/label-container}
(if in-progress?
[messages-skeleton/messages-skeleton window-height]
[quo2/skeleton window-height]
[react/nested-text
{:style (style/gap-text (and connected? use-status-nodes?))}
(i18n/label (if first-gap? :t/load-more-messages :t/fetch-messages))

View File

@ -25,7 +25,6 @@
[status-im.ui.screens.communities.icon :as communities.icon]
[status-im.ui.components.animation :as animation]
[status-im.chat.models.images :as images]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.ui.components.fast-image :as fast-image])
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
@ -428,8 +427,8 @@
(if (and (not pinned) (> (count pinned-messages) 2))
(do
(js/setTimeout (fn [] (re-frame/dispatch [:dismiss-keyboard])) 500)
(re-frame/dispatch [::models.pin-message/show-pin-limit-modal chat-id]))
(re-frame/dispatch [::models.pin-message/send-pin-message (assoc message :pinned (not pinned))]))))
(re-frame/dispatch [:pin-message/show-pin-limit-modal chat-id]))
(re-frame/dispatch [:pin-message/send-pin-message (assoc message :pinned (not pinned))]))))
(defn on-long-press-fn [on-long-press {:keys [pinned message-pin-enabled outgoing edit-enabled show-input?] :as message} content]
(on-long-press

View File

@ -5,7 +5,6 @@
[status-im.ui.components.react :as react]
[quo.core :as quo]
[reagent.core :as reagent]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.ui.components.list.views :as list]
[status-im.utils.handlers :refer [<sub]]
[status-im.ui.screens.chat.message.message :as message]))
@ -76,10 +75,10 @@
(i18n/label :t/cancel)]
[quo/button
{:on-press #(do
(re-frame/dispatch [::models.pin-message/send-pin-message {:chat-id (message :chat-id)
(re-frame/dispatch [:pin-message/send-pin-message {:chat-id (message :chat-id)
:message-id @selected-unpin
:pinned false}])
(re-frame/dispatch [::models.pin-message/send-pin-message (assoc message :pinned true)])
(re-frame/dispatch [:pin-message/send-pin-message (assoc message :pinned true)])
(re-frame/dispatch [:hide-popover])
(reset! selected-unpin nil))
:type :secondary

View File

@ -8,8 +8,7 @@
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.chat.styles.message.sheets :as sheets.styles]
[quo.core :as quo]
[status-im.chat.models.pin-message :as models.pin-message]))
[quo.core :as quo]))
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide])
@ -28,7 +27,7 @@
:chevron true
:on-press #(do
(hide-sheet-and-dispatch [:chat.ui/show-profile chat-id])
(re-frame/dispatch [::models.pin-message/load-pin-messages chat-id]))}]
(re-frame/dispatch [:pin-message/load-pin-messages chat-id]))}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/mark-all-read)
@ -89,7 +88,7 @@
:accessibility-label :view-community-channel-details
:on-press #(do
(hide-sheet-and-dispatch [:navigate-to :community-channel-details {:chat-id chat-id}])
(re-frame/dispatch [::models.pin-message/load-pin-messages chat-id]))}]
(re-frame/dispatch [:pin-message/load-pin-messages chat-id]))}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/mark-all-read)
@ -118,7 +117,7 @@
:chevron true
:on-press #(do
(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])
(re-frame/dispatch [::models.pin-message/load-pin-messages chat-id]))}]
(re-frame/dispatch [:pin-message/load-pin-messages chat-id]))}]
[quo/list-item
{:theme :accent
:title (i18n/label :t/mark-all-read)

View File

@ -7,7 +7,6 @@
[i18n.i18n :as i18n]
[status-im.chat.models :as chat.models]
[status-im2.common.contact-list-item.view :as contact-list-item]
[status-im.ui2.screens.chat.messages.message :as message]
[quo.components.safe-area :as safe-area]
[reagent.core :as reagent]
[status-im2.common.home.actions.view :as actions]
@ -109,8 +108,7 @@
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity {:style (style/action-container color)
:on-press (fn []
(rf/dispatch [:bottom-sheet/show-sheet
{:content #(message/pinned-messages-list chat-id)}]))}
(rf/dispatch [:bottom-sheet/show-sheet :pinned-messages-list chat-id]))}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]

View File

@ -6,7 +6,6 @@
[quo2.components.icon :as icons]
[quo2.components.markdown.text :as text]
[quo2.components.messages.system-message :as system-message]
[quo2.core :as quo2]
[quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]
[re-frame.core :as re-frame]
@ -14,15 +13,12 @@
[status-im.chat.models.delete-message]
[status-im.chat.models.delete-message-for-me]
[status-im.chat.models.images :as images]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.chat.models.reactions :as models.reactions]
[status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.react-native.resources :as resources]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.fast-image :as fast-image]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.screens.chat.image.preview.views :as preview]
[status-im.ui.screens.chat.message.audio :as message.audio]
@ -419,8 +415,8 @@
(if (and (not pinned) (> (count pinned-messages) 2))
(do
(js/setTimeout (fn [] (re-frame/dispatch [:dismiss-keyboard])) 500)
(re-frame/dispatch [::models.pin-message/show-pin-limit-modal chat-id]))
(re-frame/dispatch [::models.pin-message/send-pin-message (assoc message :pinned (not pinned))]))))
(re-frame/dispatch [:pin-message/show-pin-limit-modal chat-id]))
(re-frame/dispatch [:pin-message/send-pin-message (assoc message :pinned (not pinned))]))))
(defn on-long-press-fn [on-long-press {:keys [pinned message-pin-enabled outgoing edit-enabled show-input? community? can-delete-message-for-everyone?] :as message} content]
(on-long-press
@ -779,61 +775,9 @@
:timestamp-str (time/timestamp->time whisper-timestamp)
:edit-enabled edit-enabled)])
(def list-key-fn #(or (:message-id %) (:value %)))
(defn pinned-messages-list [chat-id]
(let [pinned-messages (vec (vals (rf/sub [:chats/pinned chat-id])))
current-chat (rf/sub [:chats/current-chat])
community (rf/sub [:communities/community (:community-id current-chat)])]
[rn/view {:accessibility-label :pinned-messages-list}
[quo2/text {:size :heading-1
:weight :semi-bold
:style {:margin-horizontal 20}}
(i18n/label :t/pinned-messages)]
(when community
[rn/view {:style {:flex-direction :row
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:border-radius 20
:align-items :center
:align-self :flex-start
:margin-horizontal 20
:padding 4
:margin-top 8}}
[chat-icon/chat-icon-view-toolbar chat-id (:group-chat current-chat) (:chat-name current-chat) (:color current-chat) (:emoji current-chat) 22]
[rn/text {:style {:margin-left 6 :margin-right 4 :color (colors/theme-colors colors/neutral-100 colors/white)}} (:name community)]
[icons/icon
:i/chevron-right
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:width 12
:height 12}]
[rn/text {:style {:margin-left 4
:margin-right 8
:color (colors/theme-colors colors/neutral-100 colors/white)}} (str "# " (:chat-name current-chat))]])
(if (> (count pinned-messages) 0)
[list/flat-list
{:data pinned-messages
:render-fn message-render-fn
:key-fn list-key-fn
:separator [rn/view {:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80) :height 1 :margin-top 8}]}]
[rn/view {:style {:justify-content :center
:align-items :center
:margin-top 20}}
[rn/view {:style {:width 120
:height 120
:justify-content :center
:align-items :center
:border-width 1}} [icons/icon :i/placeholder]]
[quo2/text {:weight :semi-bold
:style {:margin-top 20}}
(i18n/label :t/no-pinned-messages)]
[quo2/text {:size :paragraph-2}
(i18n/label (if community :t/no-pinned-messages-community-desc :t/no-pinned-messages-desc))]])]))
(defn pin-system-message [{:keys [from in-popover? timestamp-str chat-id] :as message} {:keys [modal close-modal]}]
(let [response-to (:response-to (:content message))]
[rn/touchable-opacity {:on-press (fn []
(rf/dispatch [:bottom-sheet/show-sheet
{:content #(pinned-messages-list chat-id)}]))
[rn/touchable-opacity {:on-press #(rf/dispatch [:bottom-sheet/show-sheet :pinned-messages-list chat-id])
:active-opacity 1
:style (merge {:flex-direction :row :margin-vertical 8} (style/message-wrapper message))}
[rn/view {:style {:width photos.style/default-size
@ -870,36 +814,3 @@
[rn/view (style/message-view message)
[rn/view (style/message-view-content)
[render-parsed-text message (:parsed-text content)]]]]]))
(defn pinned-banner [chat-id]
(let [pinned-messages (rf/sub [:chats/pinned chat-id])
latest-pin-text (get-in (last (vals pinned-messages)) [:content :text])
pins-count (count (seq pinned-messages))]
(when (> pins-count 0)
[rn/touchable-opacity
{:accessibility-label :pinned-banner
:style {:height 50
:background-color colors/primary-50-opa-20
:flex-direction :row
:align-items :center
:padding-horizontal 20
:padding-vertical 10}
:active-opacity 1
:on-press (fn []
(re-frame/dispatch [:bottom-sheet/show-sheet
{:content #(pinned-messages-list chat-id)}]))}
[pin-icon (colors/theme-colors colors/neutral-100 colors/white) 20]
[rn/text {:number-of-lines 1
:style (merge typography/paragraph-2 {:margin-left 10
:margin-right 50
:color (colors/theme-colors colors/neutral-100 colors/white)})} latest-pin-text]
[rn/view {:accessibility-label :pins-count
:style {:position :absolute
:right 22
:height 20
:width 20
:border-radius 8
:justify-content :center
:align-items :center
:background-color colors/neutral-80-opa-5}}
[rn/text {:style (merge typography/label typography/font-medium {:color (colors/theme-colors colors/neutral-100 colors/white)})} pins-count]]])))

View File

@ -1,51 +0,0 @@
(ns status-im.ui2.screens.chat.messages.pinned-message
(:require [status-im.i18n.i18n :as i18n]
[quo.react :as react]
[react-native.reanimated :as reanimated]
[quo.react-native :as rn]
[quo2.foundations.typography :as typography]
[quo2.foundations.colors :as colors]
[status-im.chat.models.pin-message :as models.pin-message]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.ui2.screens.chat.messages.style :as style]
[quo2.components.icon :as icons]))
(defn pin-limit-popover [chat-id pinned-messages-list]
[:f>
(fn []
(let [width (<sub [:dimensions/window-width])
show-pin-limit-modal? (<sub [:chats/pin-modal chat-id])
opacity-animation (reanimated/use-shared-value 0)
z-index-animation (reanimated/use-shared-value -1)]
(react/effect! #(do
(reanimated/set-shared-value opacity-animation (reanimated/with-timing (if show-pin-limit-modal? 1 0)))
(reanimated/set-shared-value z-index-animation (reanimated/with-timing (if show-pin-limit-modal? 10 -1)))))
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity opacity-animation
:z-index z-index-animation}
(style/pin-popover width))
:accessibility-label :pin-limit-popover}
[rn/view {:style (style/pin-alert-container)}
[rn/view {:style (style/pin-alert-circle)}
[rn/text {:style {:color colors/danger-50}} "!"]]]
[rn/view {:style {:margin-left 8}}
[rn/text {:style (merge typography/paragraph-1 typography/font-semi-bold {:color (colors/theme-colors colors/white colors/neutral-100)})} (i18n/label :t/cannot-pin-title)]
[rn/text {:style (merge typography/paragraph-2 typography/font-regular {:color (colors/theme-colors colors/white colors/neutral-100)})} (i18n/label :t/cannot-pin-desc)]
[rn/touchable-opacity
{:accessibility-label :view-pinned-messages
:active-opacity 1
:on-press (fn []
(>evt [::models.pin-message/hide-pin-limit-modal chat-id])
(>evt [:bottom-sheet/show-sheet
{:content #(pinned-messages-list chat-id)}]))
:style (style/view-pinned-messages)}
[rn/text {:style (merge typography/paragraph-2 typography/font-medium {:color colors/white})} (i18n/label :t/view-pinned-messages)]]]
[rn/touchable-opacity {:accessibility-label :close-pin-limit-popover
:active-opacity 1
:on-press #(>evt [::models.pin-message/hide-pin-limit-modal chat-id])
:style {:position :absolute
:top 16
:right 16}}
[icons/icon :i/close {:color (colors/theme-colors colors/white colors/neutral-100)
:height 8
:width 8}]]]))])

View File

@ -1,4 +1,4 @@
(ns status-im.ui2.screens.chat.messages.style
(ns status-im.ui2.screens.chat.pin-limit-popover.style
(:require [quo2.foundations.colors :as colors]))
(defn pin-popover [width]
@ -18,7 +18,7 @@
:justify-content :center
:align-items :center})
(defn pin-alert-circle []
(def pin-alert-circle
{:width 18
:height 18
:border-radius 9
@ -27,7 +27,7 @@
:justify-content :center
:align-items :center})
(defn view-pinned-messages []
(def view-pinned-messages
{:background-color colors/primary-60
:border-radius 8
:justify-content :center

View File

@ -0,0 +1,51 @@
(ns status-im.ui2.screens.chat.pin-limit-popover.view
(:require [i18n.i18n :as i18n]
[quo2.foundations.colors :as colors]
[react-native.reanimated :as reanimated]
[react-native.core :as rn]
[quo2.core :as quo]
[utils.re-frame :as rf]
[status-im.ui2.screens.chat.pin-limit-popover.style :as style]
;; TODO move to status-im2
[quo.react :as react]))
;; TODO (flexsurfer) this should be an in-app notification component in quo2 https://github.com/status-im/status-mobile/issues/14527
(defn pin-limit-popover [chat-id]
[:f>
(fn []
(let [width (rf/sub [:dimensions/window-width])
show-pin-limit-modal? (rf/sub [:chats/pin-modal chat-id])
opacity-animation (reanimated/use-shared-value 0)
z-index-animation (reanimated/use-shared-value -1)]
(react/effect! #(do
(reanimated/set-shared-value opacity-animation (reanimated/with-timing (if show-pin-limit-modal? 1 0)))
(reanimated/set-shared-value z-index-animation (reanimated/with-timing (if show-pin-limit-modal? 10 -1)))))
[reanimated/view {:style (reanimated/apply-animations-to-style
{:opacity opacity-animation
:z-index z-index-animation}
(style/pin-popover width))
:accessibility-label :pin-limit-popover}
[rn/view {:style (style/pin-alert-container)}
[rn/view {:style style/pin-alert-circle}
[rn/text {:style {:color colors/danger-50}} "!"]]]
[rn/view {:style {:margin-left 8}}
[quo/text {:weight :semi-bold :color (colors/theme-colors colors/white colors/neutral-100)} (i18n/label :t/cannot-pin-title)]
[quo/text {:size :paragraph-2 :color (colors/theme-colors colors/white colors/neutral-100)} (i18n/label :t/cannot-pin-desc)]
[rn/touchable-opacity
{:accessibility-label :view-pinned-messages
:active-opacity 1
:on-press (fn []
(rf/dispatch [:pin-message/hide-pin-limit-modal chat-id])
(rf/dispatch [:bottom-sheet/show-sheet :pinned-messages-list chat-id]))
:style style/view-pinned-messages}
[quo/text {:size :paragraph-2 :weight :medium :color colors/white} (i18n/label :t/view-pinned-messages)]]]
[rn/touchable-opacity {:accessibility-label :close-pin-limit-popover
:active-opacity 1
:on-press #(rf/dispatch [:pin-message/hide-pin-limit-modal chat-id])
:style {:position :absolute
:top 16
:right 16}}
[quo/icon :i/close {:color (colors/theme-colors colors/white colors/neutral-100)
:size 8}]]]))])

View File

@ -0,0 +1,32 @@
(ns status-im.ui2.screens.chat.pinned-banner.view
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[quo2.core :as quo]))
;; TODO (flexsurfer) this should be a banner component in quo2 https://github.com/status-im/status-mobile/issues/14528
(defn pinned-banner [{:keys [latest-pin-text pins-count on-press]}]
[rn/touchable-opacity
{:accessibility-label :pinned-banner
:style {:height 50
:background-color colors/primary-50-opa-20
:flex-direction :row
:align-items :center
:padding-horizontal 20
:padding-vertical 10}
:active-opacity 1
:on-press on-press}
[quo/icon :i/pin {:size 20}]
[quo/text {:number-of-lines 1
:size :paragraph-2
:style {:margin-left 10 :margin-right 50}}
latest-pin-text]
[rn/view {:accessibility-label :pins-count
:style {:position :absolute
:right 22
:height 20
:width 20
:border-radius 8
:justify-content :center
:align-items :center
:background-color colors/neutral-80-opa-5}}
[quo/text {:size :label :weight :medium} pins-count]]])

View File

@ -0,0 +1,194 @@
(ns status-im2.common.constants)
(def ^:const ms-in-bg-for-require-bioauth 5000)
(def ^:const content-type-text 1)
(def ^:const content-type-sticker 2)
(def ^:const content-type-status 3)
(def ^:const content-type-emoji 4)
(def ^:const content-type-command 5)
(def ^:const content-type-system-text 6)
(def ^:const content-type-image 7)
(def ^:const content-type-audio 8)
(def ^:const content-type-community 9)
(def ^:const content-type-gap 10)
(def ^:const content-type-contact-request 11) ;; TODO: temp, will be removed
(def ^:const contact-request-state-none 0)
(def ^:const contact-request-state-mutual 1)
(def ^:const contact-request-state-sent 2)
(def ^:const contact-request-state-received 3)
(def ^:const contact-request-state-dismissed 4)
(def ^:const contact-verification-status-unknown 0)
(def ^:const contact-verification-status-pending 1)
(def ^:const contact-verification-status-accepted 2)
(def ^:const contact-verification-status-declined 3)
(def ^:const contact-verification-status-cancelled 4)
(def ^:const contact-verification-status-trusted 5)
(def ^:const contact-verification-status-untrustworthy 6)
(def ^:const emoji-reaction-love 1)
(def ^:const emoji-reaction-thumbs-up 2)
(def ^:const emoji-reaction-thumbs-down 3)
(def ^:const emoji-reaction-laugh 4)
(def ^:const emoji-reaction-sad 5)
(def ^:const emoji-reaction-angry 6)
(def ^:const one-to-one-chat-type 1)
(def ^:const public-chat-type 2)
(def ^:const private-group-chat-type 3)
(def ^:const profile-chat-type 4)
(def ^:const timeline-chat-type 5)
(def ^:const community-chat-type 6)
(def ^:const contact-request-message-state-none 0)
(def ^:const contact-request-message-state-pending 1)
(def ^:const contact-request-message-state-accepted 2)
(def ^:const contact-request-message-state-declined 3)
(def request-to-join-pending-state 1)
(def reactions {emoji-reaction-love :i/love
emoji-reaction-thumbs-up :i/thumbs-up
emoji-reaction-thumbs-down :i/thumbs-down
emoji-reaction-laugh :i/laugh
emoji-reaction-sad :i/sad
emoji-reaction-angry :i/angry})
(def ^:const invitation-state-unknown 0)
(def ^:const invitation-state-requested 1)
(def ^:const invitation-state-rejected 2)
(def ^:const invitation-state-approved 3)
(def ^:const invitation-state-granted 4)
(def ^:const invitation-state-removed 5)
(def ^:const message-type-one-to-one 1)
(def ^:const message-type-public-group 2)
(def ^:const message-type-private-group 3)
(def ^:const message-type-private-group-system-message 4)
(def ^:const message-type-community-chat 5)
(def ^:const message-type-gap 6)
(def ^:const command-state-request-address-for-transaction 1)
(def ^:const command-state-request-address-for-transaction-declined 2)
(def ^:const command-state-request-address-for-transaction-accepted 3)
(def ^:const command-state-request-transaction 4)
(def ^:const command-state-request-transaction-declined 5)
(def ^:const command-state-transaction-pending 6)
(def ^:const command-state-transaction-sent 7)
(def ^:const profile-pictures-show-to-contacts-only 1)
(def ^:const profile-pictures-show-to-everyone 2)
(def ^:const profile-pictures-show-to-none 3)
(def ^:const profile-pictures-visibility-contacts-only 1)
(def ^:const profile-pictures-visibility-everyone 2)
(def ^:const profile-pictures-visibility-none 3)
(def ^:const min-password-length 6)
(def ^:const max-group-chat-participants 20)
(def ^:const default-number-of-messages 20)
(def ^:const default-number-of-pin-messages 3)
(def ^:const mailserver-password "status-offline-inbox")
(def ^:const send-transaction-failed-parse-response 1)
(def ^:const send-transaction-failed-parse-params 2)
(def ^:const send-transaction-no-account-selected 3)
(def ^:const send-transaction-invalid-tx-sender 4)
(def ^:const send-transaction-err-decrypt 5)
(def ^:const web3-send-transaction "eth_sendTransaction")
(def ^:const web3-personal-sign "personal_sign")
(def ^:const web3-eth-sign "eth_sign")
(def ^:const web3-sign-typed-data "eth_signTypedData")
(def ^:const web3-sign-typed-data-v3 "eth_signTypedData_v3")
(def ^:const web3-sign-typed-data-v4 "eth_signTypedData_v4")
(def ^:const web3-keycard-sign-typed-data "keycard_signTypedData")
(def ^:const status-create-address "status_createaddress")
(def ^:const community-no-membership-access 1)
(def ^:const community-invitation-only-access 2)
(def ^:const community-on-request-access 3)
;; Community rules for joining
(def ^:const community-rule-ens-only "ens-only")
(def ^:const community-channel-access-no-membership 1)
(def ^:const community-channel-access-invitation-only 2)
(def ^:const community-channel-access-on-request 3)
; BIP44 Wallet Root Key, the extended key from which any wallet can be derived
(def ^:const path-wallet-root "m/44'/60'/0'/0")
; EIP1581 Root Key, the extended key from which any whisper key/encryption key can be derived
(def ^:const path-eip1581 "m/43'/60'/1581'")
; BIP44-0 Wallet key, the default wallet key
(def ^:const path-default-wallet (str path-wallet-root "/0"))
; EIP1581 Chat Key 0, the default whisper key
(def ^:const path-whisper (str path-eip1581 "/0'/0"))
(def ^:const path-default-wallet-keyword (keyword path-default-wallet))
(def ^:const path-whisper-keyword (keyword path-whisper))
(def ^:const path-wallet-root-keyword (keyword path-wallet-root))
(def ^:const path-eip1581-keyword (keyword path-eip1581))
(def ^:const method-id-transfer "0xa9059cbb")
(def ^:const method-id-approve "0x095ea7b3")
(def ^:const method-id-approve-and-call "0xcae9ca51")
(def regx-emoji #"^((?:[\u261D\u26F9\u270A-\u270D]|\uD83C[\uDF85\uDFC2-\uDFC4\uDFC7\uDFCA-\uDFCC]|\uD83D[\uDC42\uDC43\uDC46-\uDC50\uDC66-\uDC69\uDC6E\uDC70-\uDC78\uDC7C\uDC81-\uDC83\uDC85-\uDC87\uDCAA\uDD74\uDD75\uDD7A\uDD90\uDD95\uDD96\uDE45-\uDE47\uDE4B-\uDE4F\uDEA3\uDEB4-\uDEB6\uDEC0\uDECC]|\uD83E[\uDD18-\uDD1C\uDD1E\uDD1F\uDD26\uDD30-\uDD39\uDD3D\uDD3E\uDDD1-\uDDDD])(?:\uD83C[\uDFFB-\uDFFF])?|(?:[\u231A\u231B\u23E9-\u23EC\u23F0\u23F3\u25FD\u25FE\u2614\u2615\u2648-\u2653\u267F\u2693\u26A1\u26AA\u26AB\u26BD\u26BE\u26C4\u26C5\u26CE\u26D4\u26EA\u26F2\u26F3\u26F5\u26FA\u26FD\u2705\u270A\u270B\u2728\u274C\u274E\u2753-\u2755\u2757\u2795-\u2797\u27B0\u27BF\u2B1B\u2B1C\u2B50\u2B55]|\uD83C[\uDC04\uDCCF\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE1A\uDE2F\uDE32-\uDE36\uDE38-\uDE3A\uDE50\uDE51\uDF00-\uDF20\uDF2D-\uDF35\uDF37-\uDF7C\uDF7E-\uDF93\uDFA0-\uDFCA\uDFCF-\uDFD3\uDFE0-\uDFF0\uDFF4\uDFF8-\uDFFF]|\uD83D[\uDC00-\uDC3E\uDC40\uDC42-\uDCFC\uDCFF-\uDD3D\uDD4B-\uDD4E\uDD50-\uDD67\uDD7A\uDD95\uDD96\uDDA4\uDDFB-\uDE4F\uDE80-\uDEC5\uDECC\uDED0-\uDED2\uDEEB\uDEEC\uDEF4-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])|(?:[#\*0-9\xA9\xAE\u203C\u2049\u2122\u2139\u2194-\u2199\u21A9\u21AA\u231A\u231B\u2328\u23CF\u23E9-\u23F3\u23F8-\u23FA\u24C2\u25AA\u25AB\u25B6\u25C0\u25FB-\u25FE\u2600-\u2604\u260E\u2611\u2614\u2615\u2618\u261D\u2620\u2622\u2623\u2626\u262A\u262E\u262F\u2638-\u263A\u2640\u2642\u2648-\u2653\u2660\u2663\u2665\u2666\u2668\u267B\u267F\u2692-\u2697\u2699\u269B\u269C\u26A0\u26A1\u26AA\u26AB\u26B0\u26B1\u26BD\u26BE\u26C4\u26C5\u26C8\u26CE\u26CF\u26D1\u26D3\u26D4\u26E9\u26EA\u26F0-\u26F5\u26F7-\u26FA\u26FD\u2702\u2705\u2708-\u270D\u270F\u2712\u2714\u2716\u271D\u2721\u2728\u2733\u2734\u2744\u2747\u274C\u274E\u2753-\u2755\u2757\u2763\u2764\u2795-\u2797\u27A1\u27B0\u27BF\u2934\u2935\u2B05-\u2B07\u2B1B\u2B1C\u2B50\u2B55\u3030\u303D\u3297\u3299]|\uD83C[\uDC04\uDCCF\uDD70\uDD71\uDD7E\uDD7F\uDD8E\uDD91-\uDD9A\uDDE6-\uDDFF\uDE01\uDE02\uDE1A\uDE2F\uDE32-\uDE3A\uDE50\uDE51\uDF00-\uDF21\uDF24-\uDF93\uDF96\uDF97\uDF99-\uDF9B\uDF9E-\uDFF0\uDFF3-\uDFF5\uDFF7-\uDFFF]|\uD83D[\uDC00-\uDCFD\uDCFF-\uDD3D\uDD49-\uDD4E\uDD50-\uDD67\uDD6F\uDD70\uDD73-\uDD7A\uDD87\uDD8A-\uDD8D\uDD90\uDD95\uDD96\uDDA4\uDDA5\uDDA8\uDDB1\uDDB2\uDDBC\uDDC2-\uDDC4\uDDD1-\uDDD3\uDDDC-\uDDDE\uDDE1\uDDE3\uDDE8\uDDEF\uDDF3\uDDFA-\uDE4F\uDE80-\uDEC5\uDECB-\uDED2\uDEE0-\uDEE5\uDEE9\uDEEB\uDEEC\uDEF0\uDEF3-\uDEF8]|\uD83E[\uDD10-\uDD3A\uDD3C-\uDD3E\uDD40-\uDD45\uDD47-\uDD4C\uDD50-\uDD6B\uDD80-\uDD97\uDDC0\uDDD0-\uDDE6])\uFE0F|[\t-\r \xA0\u1680\u2000-\u200A\u2028\u2029\u202F\u205F\u3000\uFEFF])+$")
(def regx-bold #"\*[^*]+\*")
(def regx-italic #"~[^~]+~")
(def regx-backquote #"`[^`]+`")
(def regx-universal-link #"((^https?://join.status.im/)|(^status-im://))[\x00-\x7F]+$")
(def regx-community-universal-link #"((^https?://join.status.im/)|(^status-im://))c/([\x00-\x7F]+)$")
(def regx-deep-link #"((^ethereum:.*)|(^status-im://[\x00-\x7F]+$))")
(def ^:const dapp-permission-contact-code "contact-code")
(def ^:const dapp-permission-web3 "web3")
(def ^:const dapp-permission-qr-code "qr-code")
(def ^:const api-response "api-response")
(def ^:const api-request "api-request")
(def ^:const history-state-changed "history-state-changed")
(def ^:const web3-send-async-read-only "web3-send-async-read-only")
(def ^:const web3-send-async-callback "web3-send-async-callback")
(def ^:const scan-qr-code "scan-qr-code")
(def ^:const faq "https://status.im/faq/")
(def ^:const faq-keycard (str faq "#keycard"))
(def ^:const keycard-integration-link "https://status.im/keycard-integration")
(def ^:const status-community-id "0x039b2da47552aa117a96ea8f1d4d108ba66637c7517a3c94a57b99dbb8a002eda2")
(def ^:const timeline-chat-id "@timeline70bd746ddcc12beb96b2c9d572d0784ab137ffc774f5383e50585a932080b57cca0484b259e61cecbaa33a4c98a300a")
(def ^:const two-mins (* 2 60))
(def ^:const one-day (* 60 60 24))
(def ^:const three-days (* one-day 3))
(def ^:const one-week (* one-day 7))
(def ^:const one-month (* one-day 31))
(def ^:const privacy-policy-link "https://status.im/privacy-policy/")
(def ^:const terms-of-service-link "https://status.im/terms-of-use")
(def ^:const docs-link "https://status.im/docs/")
(def ^:const principles-link "https://our.status.im/our-principles/")
(def ^:const visibility-status-unknown 0)
(def ^:const visibility-status-automatic 1)
(def ^:const visibility-status-dnd 2)
(def ^:const visibility-status-always-online 3)
(def ^:const visibility-status-inactive 4)
(def ^:const wallet-connect-version-1 1)
(def ^:const wallet-connect-version-2 2)
(def ^:const sticker-pack-status-installed 1)
(def ^:const sticker-pack-status-pending 2)
(def ^:const sticker-pack-status-owned 3)
(def ^:const community-member-role-all 1)
(def ^:const community-member-role-manage-users 2)
(def ^:const community-member-role-moderator 3)

View File

@ -5,9 +5,8 @@
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
;;TODO move to status-im2
[status-im.constants :as constants]
[status-im.chat.models :as chat.models]
[status-im.chat.models.pin-message :as models.pin-message]))
[status-im2.common.constants :as constants]
[status-im.chat.models :as chat.models]))
(defn- entry [{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
{:pre [(keyword? icon)
@ -29,7 +28,7 @@
(defn show-profile-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/show-profile chat-id])
(rf/dispatch [::models.pin-message/load-pin-messages chat-id]))
(rf/dispatch [:pin-message/load-pin-messages chat-id]))
(defn mark-all-read-action [chat-id]
(hide-sheet-and-dispatch [:chat/mark-all-as-read chat-id]))

View File

@ -1,32 +1,26 @@
(ns status-im.ui2.screens.chat.messages.view
(ns status-im2.contexts.chat.messages.list.view
(:require [reagent.core :as reagent]
[quo.react-native :as rn]
[quo2.foundations.colors :as colors]
[status-im.constants :as constants]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.ui.components.list.views :as list]
[react-native.core :as rn]
[quo2.core :as quo]
[utils.re-frame :as rf]
[react-native.platform :as platform]
[oops.core :as oops]
[react-native.background-timer :as background-timer]
[status-im2.common.constants :as constants]
;;TODO move to status-im2
[status-im.ui2.screens.chat.messages.message :as message]
[status-im.ui.screens.chat.group :as chat.group]
[status-im.ui.screens.chat.message.datemark :as message-datemark]
[status-im.ui.screens.chat.message.gap :as gap]
[status-im.ui.screens.chat.components.messages-skeleton :as messages-skeleton]
[status-im.utils.utils :as utils]
[status-im.utils.platform :as platform]
[status-im.ui.screens.chat.state :as state]
[status-im.ui.components.icons.icons :as icons]))
[quo.react-native :as quo.react]))
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
(defonce show-floating-scroll-down-button (reagent/atom false))
(defonce messages-list-ref (atom nil))
(def messages-view-height (reagent/atom 0))
(defn on-messages-view-layout [^js ev]
(reset! messages-view-height (-> ev .-nativeEvent .-layout .-height)))
(def list-key-fn #(or (:message-id %) (:value %)))
(def list-ref #(reset! messages-list-ref %))
(defonce list-key-fn #(or (:message-id %) (:value %)))
(defonce list-ref #(reset! messages-list-ref %))
(defn scroll-to-bottom []
(some-> ^js @messages-list-ref (.scrollToOffset #js {:y 0 :animated true})))
@ -43,73 +37,31 @@
:justify-content :center
:border-radius (/ 24 2)
:background-color (colors/theme-colors colors/neutral-80-opa-70 colors/white-opa-70)}}
;;TODO icon from quo2 should be used instead!
[icons/icon
:main-icons/arrow-down {:color (colors/theme-colors colors/white colors/neutral-100)
:width 12
:height 12}]]])
[quo/icon :i/arrow-down {:color (colors/theme-colors colors/white colors/neutral-100)
:size 12}]]])
(defn on-scroll [^js ev]
(let [y (-> ev .-nativeEvent .-contentOffset .-y)
layout-height (-> ev .-nativeEvent .-layoutMeasurement .-height)
(defonce ^:const threshold-percentage-to-show-floating-scroll-down-button 75)
(defonce show-floating-scroll-down-button (reagent/atom false))
(defn on-scroll [evt]
(let [y (oops/oget evt "nativeEvent.contentOffset.y")
layout-height (oops/oget evt "nativeEvent.layoutMeasurement.height")
threshold-height (* (/ layout-height 100) threshold-percentage-to-show-floating-scroll-down-button)
reached-threshold? (> y threshold-height)]
(when (not= reached-threshold? @show-floating-scroll-down-button)
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets))
(quo.react/configure-next (:ease-in-ease-out quo.react/layout-animation-presets))
(reset! show-floating-scroll-down-button reached-threshold?))))
(defn chat-intro-header-container
[]
;;not implemented
[rn/view])
(defn list-footer [{:keys [chat-id] :as chat}]
(let [loading-messages? (<sub [:chats/loading-messages? chat-id])
no-messages? (<sub [:chats/chat-no-messages? chat-id])
all-loaded? (<sub [:chats/all-loaded? chat-id])]
[rn/view {:style (when platform/android? {:scaleY -1})}
(if (or loading-messages? (not chat-id) (not all-loaded?))
[messages-skeleton/messages-skeleton @messages-view-height]
[chat-intro-header-container chat no-messages?])]))
(defn list-header [{:keys [chat-id chat-type invitation-admin]}]
(when (= chat-type constants/private-group-chat-type)
[rn/view {:style (when platform/android? {:scaleY -1})}
[chat.group/group-chat-footer chat-id invitation-admin]]))
(defn render-fn [{:keys [outgoing type] :as message}
idx
_
{:keys [group-chat public? community? current-public-key
chat-id show-input? message-pin-enabled edit-enabled in-pinned-view? can-delete-message-for-everyone?]}]
[rn/view {:style (when (and platform/android? (not in-pinned-view?)) {:scaleY -1})}
(if (= type :datemark)
[message-datemark/chat-datemark (:value message)]
(if (= type :gap)
[gap/gap message idx messages-list-ref false chat-id]
; message content
[message/chat-message
(assoc message
:incoming-group (and group-chat (not outgoing))
:group-chat group-chat
:public? public?
:community? community?
:current-public-key current-public-key
:show-input? show-input?
:message-pin-enabled message-pin-enabled
:edit-enabled edit-enabled
:can-delete-message-for-everyone? can-delete-message-for-everyone?)]))])
(defn on-viewable-items-changed [^js e]
(defn on-viewable-items-changed [evt]
(when @messages-list-ref
(reset! state/first-not-visible-item
(when-let [^js last-visible-element (aget (.-viewableItems e) (dec (.-length ^js (.-viewableItems e))))]
(let [index (.-index last-visible-element)
(when-let [last-visible-element (aget (oops/oget evt "viewableItems") (dec (oops/oget evt "viewableItems.length")))]
(let [index (oops/oget last-visible-element "index")
;; Get first not visible element, if it's a datemark/gap
;; we might unnecessarely add messages on receiving as
;; they do not have a clock value, but most of the times
;; it will be a message
first-not-visible (aget (.-data ^js (.-props ^js @messages-list-ref)) (inc index))]
first-not-visible (aget (oops/oget @messages-list-ref "props.data") (inc index))]
(when (and first-not-visible
(= :message (:type first-not-visible)))
first-not-visible))))))
@ -119,13 +71,13 @@
;;load and render 20 messages more, but we can't prevent this , because otherwise :on-end-reached will work wrong
(defn list-on-end-reached []
(if @state/scrolling
(>evt [:chat.ui/load-more-messages-for-current-chat])
(utils/set-timeout #(>evt [:chat.ui/load-more-messages-for-current-chat])
(rf/dispatch [:chat.ui/load-more-messages-for-current-chat])
(background-timer/set-timeout #(rf/dispatch [:chat.ui/load-more-messages-for-current-chat])
(if platform/low-device? 700 200))))
(defn get-render-data [{:keys [group-chat chat-id public? community-id admins space-keeper show-input? edit-enabled in-pinned-view?]}]
(let [current-public-key (<sub [:multiaccount/public-key])
{:keys [can-delete-message-for-everyone?] :as community} (<sub [:communities/community community-id])
(let [current-public-key (rf/sub [:multiaccount/public-key])
{:keys [can-delete-message-for-everyone?] :as community} (rf/sub [:communities/community community-id])
group-admin? (get admins current-public-key)
community-admin? (when community (community :admin))
message-pin-enabled (and (not public?)
@ -145,31 +97,72 @@
:in-pinned-view? in-pinned-view?
:can-delete-message-for-everyone? can-delete-message-for-everyone?}))
(defn messages-view [{:keys [chat
(defonce messages-view-height (reagent/atom 0))
(defn on-messages-view-layout [evt]
(reset! messages-view-height (oops/oget evt "nativeEvent.layout.height")))
(defn list-footer [{:keys [chat-id]}]
(let [loading-messages? (rf/sub [:chats/loading-messages? chat-id])
all-loaded? (rf/sub [:chats/all-loaded? chat-id])]
(when (or loading-messages? (not chat-id) (not all-loaded?))
[rn/view {:style (when platform/android? {:scaleY -1})}
[quo/skeleton @messages-view-height]])))
(defn list-header [{:keys [chat-id chat-type invitation-admin]}]
(when (= chat-type constants/private-group-chat-type)
[rn/view {:style (when platform/android? {:scaleY -1})}
[chat.group/group-chat-footer chat-id invitation-admin]]))
(defn render-fn [{:keys [outgoing type] :as message}
idx
_
{:keys [group-chat public? community? current-public-key
chat-id show-input? message-pin-enabled edit-enabled in-pinned-view? can-delete-message-for-everyone?]}]
[rn/view {:style (when (and platform/android? (not in-pinned-view?)) {:scaleY -1})}
(if (= type :datemark)
;; TODO (flexsurfer) implement and use date divider component https://github.com/status-im/status-mobile/issues/14523
[message-datemark/chat-datemark (:value message)]
(if (= type :gap)
;; TODO (flexsurfer) new gap functionality is not implemented yet
[gap/gap message idx messages-list-ref false chat-id]
; message content
[message/chat-message
(assoc message
:incoming-group (and group-chat (not outgoing))
:group-chat group-chat
:public? public?
:community? community?
:current-public-key current-public-key
:show-input? show-input?
:message-pin-enabled message-pin-enabled
:edit-enabled edit-enabled
:can-delete-message-for-everyone? can-delete-message-for-everyone?)]))])
(defn messages-list [{:keys [chat
bottom-space
pan-responder
mutual-contact-requests-enabled?
show-input?]}]
(let [{:keys [group-chat chat-type chat-id public? community-id admins]} chat
messages (<sub [:chats/raw-chat-messages-stream chat-id])
messages (rf/sub [:chats/raw-chat-messages-stream chat-id])
one-to-one? (= chat-type constants/one-to-one-chat-type)
contact-added? (when one-to-one? (<sub [:contacts/contact-added? chat-id]))
contact-added? (when one-to-one? (rf/sub [:contacts/contact-added? chat-id]))
should-send-contact-request?
(and
mutual-contact-requests-enabled?
one-to-one?
(not contact-added?))]
[:<>
;;do not use anonymous functions for handlers
[list/flat-list
;;DO NOT use anonymous functions for handlers
[rn/flat-list
(merge
pan-responder
{:key-fn list-key-fn
:ref list-ref
:header [list-header chat]
:footer [list-footer chat]
:data (when-not should-send-contact-request?
messages)
:data (when-not should-send-contact-request? messages)
:render-data (get-render-data {:group-chat group-chat
:chat-id chat-id
:public? public?

View File

@ -0,0 +1,14 @@
(ns status-im2.contexts.chat.messages.pin.banner.view
(:require [status-im.ui2.screens.chat.pinned-banner.view :as pinned-banner]
[utils.re-frame :as rf]))
(defn banner [chat-id]
(let [pinned-messages (rf/sub [:chats/pinned chat-id])
latest-pin-text (get-in (last (vals pinned-messages)) [:content :text])
pins-count (count (seq pinned-messages))]
(when (> pins-count 0)
;; TODO (flexsurfer) this should be banner component in quo2
[pinned-banner/pinned-banner
{:latest-pin-text latest-pin-text
:pins-count pins-count
:on-press #(rf/dispatch [:bottom-sheet/show-sheet :pinned-messages-list chat-id])}])))

View File

@ -1,4 +1,4 @@
(ns status-im.chat.models.pin-message
(ns status-im2.contexts.chat.messages.pin.events
(:require [status-im.chat.models.message-list :as message-list]
[status-im.constants :as constants]
[status-im.data-store.pin-messages :as data-store.pin-messages]
@ -8,20 +8,19 @@
[re-frame.core :as re-frame]))
(fx/defn handle-failed-loading-pin-messages
{:events [::failed-loading-pin-messages]}
{:events [:pin-message/failed-loading-pin-messages]}
[{:keys [db]} current-chat-id _ err]
(log/error "failed loading pin messages" current-chat-id err)
(when current-chat-id
{:db (assoc-in db [:pagination-info current-chat-id :loading-pin-messages?] false)}))
(fx/defn pin-messages-loaded
{:events [::pin-messages-loaded]}
{:events [:pin-message/pin-messages-loaded]}
[{db :db} chat-id {:keys [cursor pinned-messages]}]
(let [all-messages (reduce (fn [acc {:keys [message-id] :as message}]
(assoc acc message-id message))
{}
pinned-messages)
messages-id-list (map :message-id pinned-messages)]
pinned-messages)]
{:db (-> db
(assoc-in [:pagination-info chat-id :loading-pin-messages?] false)
(assoc-in [:pin-messages chat-id] all-messages)
@ -30,7 +29,7 @@
(empty? cursor)))}))
(fx/defn receive-signal
[{:keys [db] :as cofx} pin-messages]
[{:keys [db]} pin-messages]
(let [{:keys [chat-id]} (first pin-messages)]
(when (= chat-id (db :current-chat-id))
(let [{:keys [chat-id]} (first pin-messages)
@ -55,23 +54,9 @@
(assoc-in [:pin-message-lists chat-id]
(message-list/add-many nil (vals all-messages))))}))))
(fx/defn load-more-pin-messages
[{:keys [db]} chat-id first-request]
(let [not-all-loaded? (not (get-in db [:pagination-info chat-id :all-loaded?]))
not-loading-pin-messages? (not (get-in db [:pagination-info chat-id :loading-pin-messages?]))]
(when not-loading-pin-messages?
(fx/merge
{:db (assoc-in db [:pagination-info chat-id :loading-pin-messages?] true)}
(data-store.pin-messages/pinned-message-by-chat-id-rpc
chat-id
nil
constants/default-number-of-pin-messages
#(re-frame/dispatch [::pin-messages-loaded chat-id %])
#(re-frame/dispatch [::failed-loading-pin-messages chat-id %]))))))
(fx/defn send-pin-message
"Pin message, rebuild pinned messages list"
{:events [::send-pin-message]}
{:events [:pin-message/send-pin-message]}
[{:keys [db] :as cofx} {:keys [chat-id message-id pinned] :as pin-message}]
(let [current-public-key (get-in db [:multiaccount :public-key])
message (merge pin-message {:pinned-by current-public-key})
@ -97,19 +82,25 @@
:ens-name preferred-name}])))))
(fx/defn load-pin-messages
{:events [::load-pin-messages]}
[{:keys [db] :as cofx} chat-id]
(load-more-pin-messages cofx chat-id true))
{:events [:pin-message/load-pin-messages]}
[{:keys [db]} chat-id]
(let [not-loading-pin-messages? (not (get-in db [:pagination-info chat-id :loading-pin-messages?]))]
(when not-loading-pin-messages?
(fx/merge
{:db (assoc-in db [:pagination-info chat-id :loading-pin-messages?] true)}
(data-store.pin-messages/pinned-message-by-chat-id-rpc
chat-id
nil
constants/default-number-of-pin-messages
#(re-frame/dispatch [:pin-message/pin-messages-loaded chat-id %])
#(re-frame/dispatch [:pin-message/failed-loading-pin-messages chat-id %]))))))
(fx/defn show-pin-limit-modal
{:events [::show-pin-limit-modal]}
[{:keys [db] :as cofx} chat-id]
(fx/merge
{:db (assoc-in db [:pin-modal chat-id] true)}))
{:events [:pin-message/show-pin-limit-modal]}
[{:keys [db]} chat-id]
{:db (assoc-in db [:pin-modal chat-id] true)})
(fx/defn hide-pin-limit-modal
{:events [::hide-pin-limit-modal]}
[{:keys [db] :as cofx} chat-id]
(fx/merge
{:db (assoc-in db [:pin-modal chat-id] false)}))
{:events [:pin-message/hide-pin-limit-modal]}
[{:keys [db]} chat-id]
{:db (assoc-in db [:pin-modal chat-id] false)})

View File

@ -0,0 +1,59 @@
(ns status-im2.contexts.chat.messages.pin.list.view
(:require [utils.re-frame :as rf]
[react-native.core :as rn]
[quo2.core :as quo]
[i18n.i18n :as i18n]
[quo2.foundations.colors :as colors]
;; TODO move to status-im2
[status-im.ui2.screens.chat.messages.message :as old-message]))
(def list-key-fn #(or (:message-id %) (:value %)))
(defn pinned-messages-list [chat-id]
(let [pinned-messages (vec (vals (rf/sub [:chats/pinned chat-id])))
current-chat (rf/sub [:chats/current-chat])
community (rf/sub [:communities/community (:community-id current-chat)])]
[rn/view {:accessibility-label :pinned-messages-list}
;; TODO (flexsurfer) this should be a component in quo2 https://github.com/status-im/status-mobile/issues/14529
[:<>
[quo/text {:size :heading-1
:weight :semi-bold
:style {:margin-horizontal 20}}
(i18n/label :t/pinned-messages)]
(when community
[rn/view {:style {:flex-direction :row
:background-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:border-radius 20
:align-items :center
:align-self :flex-start
:margin-horizontal 20
:padding 4
:margin-top 8}}
[rn/text {:style {:margin-left 6 :margin-right 4}} (:name community)]
[quo/icon
:i/chevron-right
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:size 12}]
[rn/text {:style {:margin-left 4
:margin-right 8}}
(str "# " (:chat-name current-chat))]])]
(if (> (count pinned-messages) 0)
[rn/flat-list
{:data pinned-messages
:render-fn old-message/message-render-fn
:key-fn list-key-fn
:separator quo/separator}]
[rn/view {:style {:justify-content :center
:align-items :center
:margin-top 20}}
[rn/view {:style {:width 120
:height 120
:justify-content :center
:align-items :center
:border-width 1}} [quo/icon :i/placeholder]]
[quo/text {:weight :semi-bold
:style {:margin-top 20}}
(i18n/label :t/no-pinned-messages)]
[quo/text {:size :paragraph-2}
(i18n/label (if community :t/no-pinned-messages-community-desc :t/no-pinned-messages-desc))]])]))

View File

@ -6,14 +6,14 @@
[utils.re-frame :as rf]
[utils.debounce :as debounce]
[quo2.core :as quo]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im2.navigation.state :as navigation.state]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
;;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]))
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]
[status-im.ui2.screens.chat.composer.view :as composer]))
(defn navigate-back-handler []
(when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat))
@ -62,10 +62,11 @@
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]
;; TODO (flexsurfer) this should be in-app notification component in quo2 https://github.com/status-im/status-mobile/issues/14527
[pin-limit-popover/pin-limit-popover chat-id]
[pin.banner/banner chat-id]
;;MESSAGES LIST
[messages/messages-view
[messages.list/messages-list
{:chat chat
:mutual-contact-requests-enabled? mutual-contact-requests-enabled?
:show-input? show-input?

View File

@ -14,7 +14,7 @@
[react-native.platform :as platform]
[status-im2.contexts.communities.requests.actions.view :as requests.actions]
[status-im2.contexts.communities.home.actions.view :as home.actions]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im.react-native.resources :as resources]
[status-im.utils.utils :as utils]))

View File

@ -2,7 +2,7 @@
(:require [react-native.core :as rn]
[status-im2.contexts.quo-preview.preview :as preview]
[reagent.core :as reagent]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[quo2.foundations.colors :as colors]
[quo.design-system.colors :as quo.colors]
[quo2.components.community.community-card-view :as community-card-view]

View File

@ -1,11 +1,11 @@
(ns status-im2.contexts.quo-preview.posts-and-attachments.messages-skeleton
(:require [quo.react-native :as rn]
[quo2.foundations.colors :as colors]
[status-im.ui.screens.chat.components.messages-skeleton :as messages-skeleton]))
[quo2.core :as quo]))
(defn preview-messages-skeleton []
[rn/view {:background-color (colors/theme-colors
colors/white
colors/neutral-90)
:flex 1}
[messages-skeleton/messages-skeleton]])
[quo/skeleton]])

View File

@ -10,7 +10,7 @@
(defn content-container [{:keys [content-type data new-notifications? color-50]}]
[rn/view {:style (style/content-container new-notifications?)}
;; TODO - Use status-im.constants for content type
;; TODO - Use status-im2.common.constants for content type
(case content-type
:text [quo/text style/last-message-text-props data]
:photo [quo/preview-list {:type :photo

View File

@ -2,7 +2,7 @@
(:require [utils.re-frame :as rf]
[re-frame.core :as re-frame]
[status-im2.navigation.events :as navigation]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im2.contexts.shell.animation :as animation]
[status-im2.contexts.shell.constants :as shell.constants]))

View File

@ -2,7 +2,7 @@
(:require [re-frame.core :as re-frame]
[status-im.utils.datetime :as datetime]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im.activity-center.notification-types :as types]
[clojure.string :as string]))

View File

@ -1,7 +1,7 @@
(ns status-im2.subs.chat.chats
(:require [re-frame.core :as re-frame]
[clojure.string :as string]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[quo.design-system.colors :as colors]
[status-im.chat.models :as chat.models]
[status-im.communities.core :as communities]

View File

@ -3,7 +3,7 @@
[status-im.chat.db :as chat.db]
[status-im.chat.models.message-list :as models.message-list]
[status-im.chat.models.reactions :as models.reactions]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im.utils.datetime :as datetime]))
(re-frame/reg-sub

View File

@ -3,7 +3,7 @@
[clojure.string :as string]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[status-im.constants :as constants]))
[status-im2.common.constants :as constants]))
(re-frame/reg-sub
:communities

View File

@ -1,7 +1,7 @@
(ns status-im2.subs.general
(:require [re-frame.core :as re-frame]
[status-im.utils.build :as build]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im.multiaccounts.model :as multiaccounts.model]
[status-im.ethereum.core :as ethereum]
[status-im.ethereum.tokens :as tokens]

View File

@ -1,6 +1,6 @@
(ns status-im2.subs.onboarding
(:require [re-frame.core :as re-frame]
[status-im.constants :as constants]
[status-im2.common.constants :as constants]
[status-im.multiaccounts.recover.core :as recover]))
(re-frame/reg-sub

View File

@ -1,6 +1,6 @@
(ns status-im2.subs.shell
(:require [re-frame.core :as re-frame]
[status-im.constants :as status-constants]
[status-im2.common.constants :as status-constants]
[status-im.react-native.resources :as resources]))
(defn get-card-content [chat]

View File

@ -1,6 +1,6 @@
(ns status-im2.subs.stickers
(:require [re-frame.core :as re-frame]
[status-im.constants :as constants]))
[status-im2.common.constants :as constants]))
(re-frame/reg-sub
:stickers/installed-packs