parent
32d85d5059
commit
bab0fc7ac0
|
@ -1,99 +0,0 @@
|
||||||
(ns quo2.components.navigation.top-nav
|
|
||||||
(:require [react-native.core :as rn]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo2.components.counter.counter :as counter]
|
|
||||||
[quo2.components.buttons.button :as quo2.button]
|
|
||||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
|
||||||
[react-native.hole-view :as hole-view]))
|
|
||||||
|
|
||||||
(defn- get-button-common-props [type]
|
|
||||||
(let [default? (= type :default)
|
|
||||||
dark? (colors/dark?)]
|
|
||||||
{:icon true
|
|
||||||
:size 32
|
|
||||||
:style {:margin-left 12}
|
|
||||||
:type (if default?
|
|
||||||
(if dark? :grey :dark-grey)
|
|
||||||
type)
|
|
||||||
:override-background-color (when (and dark? default?)
|
|
||||||
colors/neutral-90)}))
|
|
||||||
|
|
||||||
(defn- base-button [icon on-press accessibility-label button-common-props]
|
|
||||||
[quo2.button/button
|
|
||||||
(merge
|
|
||||||
{:on-press on-press
|
|
||||||
:accessibility-label accessibility-label}
|
|
||||||
button-common-props)
|
|
||||||
icon])
|
|
||||||
|
|
||||||
(defn top-nav
|
|
||||||
"[top-nav opts]
|
|
||||||
opts
|
|
||||||
{:type :default/:blurred/:shell
|
|
||||||
:new-notifications? true/false
|
|
||||||
:notification-indicator :unread-dot/:counter
|
|
||||||
:open-profile fn
|
|
||||||
:open-search fn
|
|
||||||
:open-scanner fn
|
|
||||||
:show-qr fn
|
|
||||||
:open-activity-center fn
|
|
||||||
:style override-style
|
|
||||||
:avatar user-avatar
|
|
||||||
:counter-label number}
|
|
||||||
"
|
|
||||||
[{:keys [type new-notifications? notification-indicator open-profile open-search
|
|
||||||
open-scanner show-qr open-activity-center style avatar counter-label]}]
|
|
||||||
(let [button-common-props (get-button-common-props type)]
|
|
||||||
[rn/view {:style (merge
|
|
||||||
{:height 56}
|
|
||||||
style)}
|
|
||||||
;; Left Section
|
|
||||||
[rn/touchable-without-feedback {:on-press open-profile}
|
|
||||||
[rn/view {:style {:position :absolute
|
|
||||||
:left 20
|
|
||||||
:top 12}}
|
|
||||||
[user-avatar/user-avatar
|
|
||||||
(merge
|
|
||||||
{:ring? true
|
|
||||||
:status-indicator? true
|
|
||||||
:size :small}
|
|
||||||
avatar)]]]
|
|
||||||
;; Right Section
|
|
||||||
[rn/view {:style {:position :absolute
|
|
||||||
:right 20
|
|
||||||
:top 12
|
|
||||||
:flex-direction :row}}
|
|
||||||
;; TODO component shouldn't know anything about parent system, we should pass buttons as parameters
|
|
||||||
[base-button :i/search open-search :open-search-button button-common-props]
|
|
||||||
[base-button :i/scan open-scanner :open-scanner-button button-common-props]
|
|
||||||
[base-button :i/qr-code show-qr :show-qr-button button-common-props]
|
|
||||||
[rn/view ;; Keep view instead of "[:<>" to make sure relative
|
|
||||||
;; position is calculated from this view instead of its parent
|
|
||||||
[hole-view/hole-view {:key new-notifications? ;; Key is required to force removal of holes
|
|
||||||
:holes (cond
|
|
||||||
(not new-notifications?) ;; No new notifications, remove holes
|
|
||||||
[]
|
|
||||||
|
|
||||||
(= notification-indicator :unread-dot)
|
|
||||||
[{:x 37 :y -3 :width 10 :height 10 :borderRadius 5}]
|
|
||||||
|
|
||||||
:else
|
|
||||||
[{:x 33 :y -7 :width 18 :height 18 :borderRadius 7}])}
|
|
||||||
[base-button :i/activity-center open-activity-center
|
|
||||||
:open-activity-center-button button-common-props]]
|
|
||||||
(when new-notifications?
|
|
||||||
(if (= notification-indicator :counter)
|
|
||||||
[counter/counter {:outline false
|
|
||||||
:override-text-color colors/white
|
|
||||||
:override-bg-color colors/primary-50
|
|
||||||
:style {:position :absolute
|
|
||||||
:left 34
|
|
||||||
:top -6}}
|
|
||||||
counter-label]
|
|
||||||
[rn/view {:style {:width 8
|
|
||||||
:height 8
|
|
||||||
:border-radius 4
|
|
||||||
:top -2
|
|
||||||
:left 38
|
|
||||||
:position :absolute
|
|
||||||
:background-color colors/primary-50}}]))]]]))
|
|
|
@ -12,26 +12,29 @@
|
||||||
|
|
||||||
(def default-tab-size 32)
|
(def default-tab-size 32)
|
||||||
|
|
||||||
|
(defn indicator []
|
||||||
|
[rn/view {:position :absolute
|
||||||
|
:z-index 1
|
||||||
|
:right -2
|
||||||
|
:top -2
|
||||||
|
:width 10
|
||||||
|
:height 10
|
||||||
|
:border-radius 5
|
||||||
|
:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
|
||||||
|
[notification-dot]])
|
||||||
|
|
||||||
(defn tabs [{:keys [default-active on-change style]}]
|
(defn tabs [{:keys [default-active on-change style]}]
|
||||||
(let [active-tab-id (reagent/atom default-active)]
|
(let [active-tab-id (reagent/atom default-active)]
|
||||||
(fn [{:keys [data size] :or {size default-tab-size}}]
|
(fn [{:keys [data size] :or {size default-tab-size}}]
|
||||||
[rn/view (merge {:flex-direction :row} style)
|
[rn/view (merge {:flex-direction :row} style)
|
||||||
(doall
|
(doall
|
||||||
(for [{:keys [label id new-info accessibility-label]} data]
|
(for [{:keys [label id notification-dot? accessibility-label]} data]
|
||||||
^{:key id}
|
^{:key id}
|
||||||
[rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}}
|
[rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}}
|
||||||
(when new-info
|
(when notification-dot?
|
||||||
[rn/view {:position :absolute
|
[indicator])
|
||||||
:z-index 1
|
|
||||||
:right -2
|
|
||||||
:top -2
|
|
||||||
:width 10
|
|
||||||
:height 10
|
|
||||||
:border-radius 5
|
|
||||||
:justify-content :center
|
|
||||||
:align-items :center
|
|
||||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
|
|
||||||
[notification-dot]])
|
|
||||||
[tab/tab
|
[tab/tab
|
||||||
{:id id
|
{:id id
|
||||||
:size size
|
:size size
|
||||||
|
|
|
@ -35,11 +35,11 @@
|
||||||
quo2.components.tags.context-tags
|
quo2.components.tags.context-tags
|
||||||
quo2.components.tabs.tabs
|
quo2.components.tabs.tabs
|
||||||
quo2.components.tabs.account-selector
|
quo2.components.tabs.account-selector
|
||||||
quo2.components.navigation.top-nav
|
|
||||||
quo2.components.navigation.floating-shell-button
|
quo2.components.navigation.floating-shell-button
|
||||||
quo2.components.tags.status-tags
|
quo2.components.tags.status-tags
|
||||||
quo2.components.navigation.page-nav
|
quo2.components.navigation.page-nav
|
||||||
quo2.components.selectors.disclaimer))
|
quo2.components.selectors.disclaimer
|
||||||
|
quo2.components.selectors.selectors))
|
||||||
|
|
||||||
(def button quo2.components.buttons.button/button)
|
(def button quo2.components.buttons.button/button)
|
||||||
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
|
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
|
||||||
|
@ -61,12 +61,11 @@
|
||||||
(def tabs quo2.components.tabs.tabs/tabs)
|
(def tabs quo2.components.tabs.tabs/tabs)
|
||||||
(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs)
|
(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs)
|
||||||
(def account-selector quo2.components.tabs.account-selector/account-selector)
|
(def account-selector quo2.components.tabs.account-selector/account-selector)
|
||||||
(def top-nav quo2.components.navigation.top-nav/top-nav)
|
|
||||||
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
(def floating-shell-button quo2.components.navigation.floating-shell-button/floating-shell-button)
|
||||||
(def status-tag quo2.components.tags.status-tags/status-tag)
|
(def status-tag quo2.components.tags.status-tags/status-tag)
|
||||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||||
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
|
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
|
||||||
|
(def checkbox quo2.components.selectors.selectors/checkbox)
|
||||||
;;;; AVATAR
|
;;;; AVATAR
|
||||||
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
||||||
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
|
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
|
||||||
|
|
|
@ -392,6 +392,7 @@
|
||||||
(get-node-config)
|
(get-node-config)
|
||||||
(communities/fetch)
|
(communities/fetch)
|
||||||
(logging/set-log-level (:log-level multiaccount))
|
(logging/set-log-level (:log-level multiaccount))
|
||||||
|
(notifications-center/get-activity-center-notifications)
|
||||||
(notifications-center/get-activity-center-notifications-count))))
|
(notifications-center/get-activity-center-notifications-count))))
|
||||||
|
|
||||||
(re-frame/reg-fx
|
(re-frame/reg-fx
|
||||||
|
|
|
@ -17,8 +17,7 @@
|
||||||
[quo2.components.markdown.text :as quo2.text]
|
[quo2.components.markdown.text :as quo2.text]
|
||||||
[quo2.components.tabs.tabs :as quo2.tabs]
|
[quo2.components.tabs.tabs :as quo2.tabs]
|
||||||
[status-im.ui.screens.wallet.accounts.common :as common]
|
[status-im.ui.screens.wallet.accounts.common :as common]
|
||||||
[status-im.ui.screens.wallet.account.views :as account.views]
|
[status-im.ui.screens.wallet.account.views :as account.views])
|
||||||
[quo.components.safe-area :as safe-area])
|
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
(:require-macros [status-im.utils.views :as views]))
|
||||||
|
|
||||||
(views/defview account-card [{:keys [name color address type wallet] :as account} keycard? card-width]
|
(views/defview account-card [{:keys [name color address type wallet] :as account} keycard? card-width]
|
||||||
|
@ -266,32 +265,29 @@
|
||||||
;mainnet? @(re-frame/subscribe [:mainnet?])
|
;mainnet? @(re-frame/subscribe [:mainnet?])
|
||||||
selected-account-atom (reagent/atom nil)]
|
selected-account-atom (reagent/atom nil)]
|
||||||
(fn []
|
(fn []
|
||||||
[safe-area/consumer
|
[react/view {:style {:flex 1
|
||||||
(fn [insets]
|
:background-color (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/neutral-95)}}
|
||||||
[react/view {:style {:flex 1
|
[react/view {:padding-horizontal 20}
|
||||||
:padding-top (:top insets)
|
[react/view {:flex-direction :row :height 56 :align-items :center :justify-content :flex-end}
|
||||||
:background-color (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/neutral-95)}}
|
[quo2.button/button {:icon true
|
||||||
[react/view {:padding-horizontal 20}
|
:size 32
|
||||||
[react/view {:flex-direction :row :height 56 :align-items :center :justify-content :flex-end}
|
:type :grey
|
||||||
[quo2.button/button {:icon true
|
:accessibility-label :accounts-qr-code
|
||||||
:size 32
|
:on-press #(re-frame/dispatch
|
||||||
:type :grey
|
[::qr-scanner/scan-code
|
||||||
:accessibility-label :accounts-qr-code
|
{:handler :wallet.send/qr-scanner-result}])}
|
||||||
:on-press #(re-frame/dispatch
|
:i/placeholder]
|
||||||
[::qr-scanner/scan-code
|
[react/view {:width 12}]
|
||||||
{:handler :wallet.send/qr-scanner-result}])}
|
[quo2.button/button {:icon true
|
||||||
:i/placeholder]
|
:size 32
|
||||||
[react/view {:width 12}]
|
:type :grey
|
||||||
[quo2.button/button {:icon true
|
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
||||||
:size 32
|
{:content (sheets/accounts-options mnemonic)}])
|
||||||
:type :grey
|
:accessibility-label :accounts-more-options}
|
||||||
:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet
|
:i/placeholder]]
|
||||||
{:content (sheets/accounts-options mnemonic)}])
|
[total-value]
|
||||||
:accessibility-label :accounts-more-options}
|
[accounts selected-account-atom]]
|
||||||
:i/placeholder]]
|
[account.views/account-new @selected-account-atom]])))
|
||||||
[total-value]
|
|
||||||
[accounts selected-account-atom]]
|
|
||||||
[account.views/account-new @selected-account-atom]])])))
|
|
||||||
|
|
||||||
(defn accounts-overview-old []
|
(defn accounts-overview-old []
|
||||||
(let [mnemonic @(re-frame/subscribe [:mnemonic])
|
(let [mnemonic @(re-frame/subscribe [:mnemonic])
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.components.contact-item.test)
|
|
||||||
|
|
||||||
;; TODO: tests to be added when RNTL is integrated into our project
|
|
|
@ -1,59 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.components.contact-item.view
|
|
||||||
(:require [quo2.foundations.typography :as typography]
|
|
||||||
[quo2.components.icon :as icons]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
|
||||||
[quo.react-native :as rn]
|
|
||||||
[status-im.utils.utils :as utils]
|
|
||||||
[quo.platform :as platform]
|
|
||||||
[quo2.components.markdown.text :as text]
|
|
||||||
[status-im.ui2.screens.chat.components.message-home-item.style :as style]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im.ui2.screens.chat.actions :as actions]))
|
|
||||||
|
|
||||||
(defn open-chat [chat-id]
|
|
||||||
(rf/dispatch [:dismiss-keyboard])
|
|
||||||
(if platform/android?
|
|
||||||
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
|
|
||||||
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))
|
|
||||||
(rf/dispatch [:search/home-filter-changed nil])
|
|
||||||
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
|
|
||||||
|
|
||||||
(defn contact-item [item]
|
|
||||||
(let [{:keys [public-key ens-verified added? images]} item
|
|
||||||
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
|
|
||||||
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))
|
|
||||||
current-pk (rf/sub [:multiaccount/public-key])]
|
|
||||||
[rn/touchable-opacity (merge {:style (style/container)
|
|
||||||
:on-press #(open-chat public-key)
|
|
||||||
:on-long-press #(when-not (= current-pk public-key)
|
|
||||||
(rf/dispatch [:bottom-sheet/show-sheet
|
|
||||||
{:content (fn [] [actions/actions item])}]))})
|
|
||||||
[user-avatar/user-avatar {:full-name display-name
|
|
||||||
:profile-picture photo-path
|
|
||||||
:status-indicator? true
|
|
||||||
:online? true
|
|
||||||
:size :small
|
|
||||||
:ring? false}]
|
|
||||||
[rn/view {:style {:margin-left 8}}
|
|
||||||
[rn/view {:style {:flex-direction :row}}
|
|
||||||
[text/text {:style (merge typography/paragraph-1 typography/font-semi-bold
|
|
||||||
{:color (colors/theme-colors colors/neutral-100 colors/white)})}
|
|
||||||
display-name]
|
|
||||||
(if ens-verified
|
|
||||||
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
|
||||||
[icons/icon :i/verified {:no-color true :size 12 :color (colors/theme-colors colors/success-50 colors/success-60)}]]
|
|
||||||
(when added?
|
|
||||||
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
|
||||||
[icons/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
|
|
||||||
[text/text {:size :paragraph-1
|
|
||||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
|
||||||
(utils/get-shortened-address public-key)]]
|
|
||||||
(when-not (= current-pk public-key)
|
|
||||||
[rn/touchable-opacity {:style {:position :absolute
|
|
||||||
:right 20}
|
|
||||||
:active-opacity 1
|
|
||||||
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
|
|
||||||
{:content (fn [] [actions/actions item])}])}
|
|
||||||
[icons/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]])]))
|
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.components.message-home-item.style
|
|
||||||
(:require [quo2.foundations.colors :as colors]
|
|
||||||
[quo2.foundations.typography :as typography]))
|
|
||||||
|
|
||||||
(defn container []
|
|
||||||
{:margin-top 8
|
|
||||||
:margin-horizontal 8
|
|
||||||
:padding-vertical 8
|
|
||||||
:padding-horizontal 12
|
|
||||||
:border-radius 12
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center})
|
|
||||||
|
|
||||||
(defn group-chat-icon [color]
|
|
||||||
{:width 32
|
|
||||||
:height 32
|
|
||||||
:background-color color
|
|
||||||
:justify-content :center
|
|
||||||
:align-items :center
|
|
||||||
:border-radius 16})
|
|
||||||
|
|
||||||
(defn count-container []
|
|
||||||
{:width 8
|
|
||||||
:height 8
|
|
||||||
:border-radius 4
|
|
||||||
:position :absolute
|
|
||||||
:right 26
|
|
||||||
:top 16
|
|
||||||
:background-color (colors/theme-colors colors/neutral-40 colors/neutral-60)})
|
|
||||||
|
|
||||||
(defn timestamp []
|
|
||||||
(merge typography/font-regular typography/label
|
|
||||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
|
||||||
:margin-top 3
|
|
||||||
:margin-left 8}))
|
|
|
@ -1,3 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.components.message-home-item.test)
|
|
||||||
|
|
||||||
;; TODO: tests to be added when RNTL is integrated into our project
|
|
|
@ -1,132 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.components.message-home-item.view
|
|
||||||
(:require [clojure.string :as string]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im.utils.datetime :as time]
|
|
||||||
[quo2.foundations.typography :as typography]
|
|
||||||
[quo2.components.icon :as icons]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo.react-native :as rn]
|
|
||||||
[quo.platform :as platform]
|
|
||||||
[quo2.core :as quo2]
|
|
||||||
[quo2.components.markdown.text :as text]
|
|
||||||
[status-im.ui2.screens.chat.actions :as actions]
|
|
||||||
[status-im.ui2.screens.chat.components.message-home-item.style :as style]))
|
|
||||||
|
|
||||||
(def max-subheader-length 50)
|
|
||||||
|
|
||||||
(defn truncate-literal [literal]
|
|
||||||
(when literal
|
|
||||||
(let [size (min max-subheader-length (.-length literal))]
|
|
||||||
{:components (.substring literal 0 size)
|
|
||||||
:length size})))
|
|
||||||
|
|
||||||
(defn add-parsed-to-subheader [acc {:keys [type destination literal children]}]
|
|
||||||
(let [result (case type
|
|
||||||
"paragraph"
|
|
||||||
(reduce
|
|
||||||
(fn [{:keys [_ length] :as acc-paragraph} parsed-child]
|
|
||||||
(if (>= length max-subheader-length)
|
|
||||||
(reduced acc-paragraph)
|
|
||||||
(add-parsed-to-subheader acc-paragraph parsed-child)))
|
|
||||||
{:components [rn/text]
|
|
||||||
:length 0}
|
|
||||||
children)
|
|
||||||
|
|
||||||
"mention"
|
|
||||||
{:components [rn/text (rf/sub [:contacts/contact-name-by-identity literal])]
|
|
||||||
:length 4} ;; we can't predict name length so take the smallest possible
|
|
||||||
|
|
||||||
"status-tag"
|
|
||||||
(truncate-literal (str "#" literal))
|
|
||||||
|
|
||||||
"link"
|
|
||||||
(truncate-literal destination)
|
|
||||||
|
|
||||||
(truncate-literal literal))]
|
|
||||||
{:components (conj (:components acc) (:components result))
|
|
||||||
:length (+ (:length acc) (:length result))}))
|
|
||||||
|
|
||||||
(defn render-subheader
|
|
||||||
"Render the preview of a last message to a maximum of max-subheader-length characters"
|
|
||||||
[parsed-text]
|
|
||||||
(let [result
|
|
||||||
(reduce
|
|
||||||
(fn [{:keys [_ length] :as acc-text} new-text-chunk]
|
|
||||||
(if (>= length max-subheader-length)
|
|
||||||
(reduced acc-text)
|
|
||||||
(add-parsed-to-subheader acc-text new-text-chunk)))
|
|
||||||
{:components [rn/text {:style (merge typography/paragraph-2 typography/font-regular
|
|
||||||
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
|
||||||
:width "90%"})
|
|
||||||
:number-of-lines 1
|
|
||||||
:ellipsize-mode :tail
|
|
||||||
:accessibility-label :chat-message-text}]
|
|
||||||
:length 0}
|
|
||||||
parsed-text)]
|
|
||||||
(:components result)))
|
|
||||||
|
|
||||||
(defn verified-or-contact-icon [{:keys [ens-verified added?]}]
|
|
||||||
(if ens-verified
|
|
||||||
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
|
||||||
[icons/icon :i/verified {:no-color true
|
|
||||||
:size 12
|
|
||||||
:color (colors/theme-colors colors/success-50 colors/success-60)}]]
|
|
||||||
(when added?
|
|
||||||
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
|
||||||
[icons/icon :i/contact {:no-color true
|
|
||||||
:size 12
|
|
||||||
:color (colors/theme-colors colors/primary-50 colors/primary-60)}]])))
|
|
||||||
|
|
||||||
(defn display-name-view [display-name contact timestamp]
|
|
||||||
[rn/view {:style {:flex-direction :row}}
|
|
||||||
[text/text {:weight :semi-bold
|
|
||||||
:accessibility-label :chat-name-text
|
|
||||||
:size :paragraph-1}
|
|
||||||
display-name]
|
|
||||||
[verified-or-contact-icon contact]
|
|
||||||
[text/text {:style (style/timestamp)}
|
|
||||||
(time/to-short-str timestamp)]])
|
|
||||||
|
|
||||||
(defn display-pic-view [group-chat color display-name photo-path]
|
|
||||||
(if group-chat
|
|
||||||
[quo2/group-avatar {:color color
|
|
||||||
:size :medium}]
|
|
||||||
[quo2/user-avatar {:full-name display-name
|
|
||||||
:profile-picture photo-path
|
|
||||||
:size :small}]))
|
|
||||||
|
|
||||||
(defn messages-home-item [item]
|
|
||||||
(let [{:keys [chat-id
|
|
||||||
color
|
|
||||||
group-chat
|
|
||||||
last-message
|
|
||||||
timestamp
|
|
||||||
name
|
|
||||||
unviewed-mentions-count
|
|
||||||
unviewed-messages-count]} item
|
|
||||||
display-name (if-not group-chat (first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) name)
|
|
||||||
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]))]
|
|
||||||
[rn/touchable-opacity (merge {:style (style/container)
|
|
||||||
:on-press (fn []
|
|
||||||
(rf/dispatch [:dismiss-keyboard])
|
|
||||||
(if platform/android?
|
|
||||||
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
|
|
||||||
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))
|
|
||||||
(rf/dispatch [:search/home-filter-changed nil])
|
|
||||||
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
|
|
||||||
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
|
|
||||||
{:content (fn [] [actions/actions item false])}])})
|
|
||||||
[display-pic-view group-chat color display-name photo-path]
|
|
||||||
[rn/view {:style {:margin-left 8}}
|
|
||||||
[display-name-view display-name contact timestamp]
|
|
||||||
(if (string/blank? (get-in last-message [:content :parsed-text]))
|
|
||||||
[text/text {:size :paragraph-2
|
|
||||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
|
||||||
(get-in last-message [:content :text])]
|
|
||||||
[render-subheader (get-in last-message [:content :parsed-text])])]
|
|
||||||
(if (> unviewed-mentions-count 0)
|
|
||||||
[quo2/info-count unviewed-mentions-count {:top 16}]
|
|
||||||
(when (> unviewed-messages-count 0)
|
|
||||||
[rn/view {:style (style/count-container)}]))]))
|
|
||||||
|
|
|
@ -5,24 +5,24 @@
|
||||||
[quo2.core :as quo2]
|
[quo2.core :as quo2]
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[i18n.i18n :as i18n]
|
[i18n.i18n :as i18n]
|
||||||
[status-im.ui2.screens.chat.components.contact-item.view :as contact-item]))
|
[status-im2.common.contact-list-item.view :as contact-item]))
|
||||||
|
|
||||||
(defn back-button []
|
(defn back-button []
|
||||||
[quo2/button {:type :grey
|
[quo2/button {:type :grey
|
||||||
:size 32
|
:size 32
|
||||||
:width 32
|
|
||||||
:style {:margin-left 20}
|
:style {:margin-left 20}
|
||||||
:accessibility-label :back-button
|
:accessibility-label :back-button
|
||||||
:on-press #(rf/dispatch [:navigate-back])}
|
:on-press #(rf/dispatch [:navigate-back])
|
||||||
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
:icon true}
|
||||||
|
:i/arrow-left])
|
||||||
|
|
||||||
(defn options-button []
|
(defn options-button []
|
||||||
[quo2/button {:type :grey
|
[quo2/button {:type :grey
|
||||||
:size 32
|
:size 32
|
||||||
:width 32
|
|
||||||
:style {:margin-right 20}
|
:style {:margin-right 20}
|
||||||
:accessibility-label :options-button}
|
:accessibility-label :options-button
|
||||||
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
:icon true}
|
||||||
|
:i/options])
|
||||||
|
|
||||||
(defn count-container [count]
|
(defn count-container [count]
|
||||||
[rn/view {:style (style/count-container)}
|
[rn/view {:style (style/count-container)}
|
||||||
|
@ -31,8 +31,8 @@
|
||||||
:style {:text-align :center}} count]])
|
:style {:text-align :center}} count]])
|
||||||
|
|
||||||
(defn prepare-members [members]
|
(defn prepare-members [members]
|
||||||
(let [admins (filter :admin? members)
|
(let [admins (filter :admin? members)
|
||||||
online (filter #(and (not (:admin? %)) (:online? %)) members)
|
online (filter #(and (not (:admin? %)) (:online? %)) members)
|
||||||
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
|
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
|
||||||
(vals (cond-> {}
|
(vals (cond-> {}
|
||||||
(seq admins) (assoc :owner {:title "Owner" :data admins})
|
(seq admins) (assoc :owner {:title "Owner" :data admins})
|
||||||
|
@ -47,11 +47,11 @@
|
||||||
|
|
||||||
(defn group-details []
|
(defn group-details []
|
||||||
(let [{:keys [admins chat-id chat-name color public?]} (rf/sub [:chats/current-chat])
|
(let [{:keys [admins chat-id chat-name color public?]} (rf/sub [:chats/current-chat])
|
||||||
members (rf/sub [:contacts/current-chat-contacts])
|
members (rf/sub [:contacts/current-chat-contacts])
|
||||||
sectioned-members (prepare-members members)
|
sectioned-members (prepare-members members)
|
||||||
pinned-messages (rf/sub [:chats/pinned chat-id])
|
pinned-messages (rf/sub [:chats/pinned chat-id])
|
||||||
current-pk (rf/sub [:multiaccount/public-key])
|
current-pk (rf/sub [:multiaccount/public-key])
|
||||||
admin? (get admins current-pk)]
|
admin? (get admins current-pk)]
|
||||||
[rn/view {:style {:flex 1
|
[rn/view {:style {:flex 1
|
||||||
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
|
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
|
||||||
[quo2/header {:left-component [back-button]
|
[quo2/header {:left-component [back-button]
|
||||||
|
|
|
@ -1,380 +0,0 @@
|
||||||
(ns status-im.ui2.screens.chat.home
|
|
||||||
(:require [re-frame.core :as re-frame]
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[status-im.i18n.i18n :as i18n]
|
|
||||||
[status-im.react-native.resources :as resources]
|
|
||||||
[status-im.ui.components.connectivity.view :as connectivity]
|
|
||||||
[status-im.ui.components.icons.icons :as icons]
|
|
||||||
[status-im.ui.components.list.views :as list]
|
|
||||||
[status-im.ui.components.react :as react]
|
|
||||||
[status-im.ui.screens.home.styles :as styles]
|
|
||||||
[quo.design-system.colors :as quo.colors]
|
|
||||||
[quo.core :as quo]
|
|
||||||
[status-im.add-new.core :as new-chat]
|
|
||||||
[status-im.ui.components.search-input.view :as search-input]
|
|
||||||
[status-im.add-new.db :as db]
|
|
||||||
[status-im.utils.debounce :as debounce]
|
|
||||||
[status-im.utils.utils :as utils]
|
|
||||||
[status-im.ui.components.topbar :as topbar]
|
|
||||||
[status-im.ui.components.invite.views :as invite]
|
|
||||||
[status-im.utils.handlers :refer [<sub >evt]]
|
|
||||||
[quo2.components.markdown.text :as quo2.text]
|
|
||||||
[status-im.qr-scanner.core :as qr-scanner]
|
|
||||||
[status-im.ui.components.chat-icon.styles :as chat-icon.styles]
|
|
||||||
[react-native.core :as rn]
|
|
||||||
[quo.react-native :as quo.rn]
|
|
||||||
[quo.react]
|
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo2.foundations.typography :as typography]
|
|
||||||
[quo2.components.buttons.button :as quo2.button]
|
|
||||||
[quo2.components.tabs.tabs :as quo2.tabs]
|
|
||||||
[quo2.components.community.discover-card :as discover-card]
|
|
||||||
[status-im.ui.components.chat-icon.screen :as chat-icon]
|
|
||||||
[quo2.components.icon :as quo2.icons]
|
|
||||||
[quo.components.safe-area :as safe-area]
|
|
||||||
[quo2.components.notifications.info-count :refer [info-count]]
|
|
||||||
[status-im.ui2.screens.chat.components.received-cr-item :as received-cr-item]
|
|
||||||
[status-im.ui2.screens.chat.components.message-home-item.view :refer [messages-home-item]]
|
|
||||||
[status-im.ui2.screens.chat.components.contact-item.view :refer [contact-item]]
|
|
||||||
[clojure.string :as str]
|
|
||||||
[status-im2.common.plus-button.view :as components.plus-button]
|
|
||||||
[status-im2.setup.config :as config])
|
|
||||||
(:require-macros [status-im.utils.views :as views]))
|
|
||||||
|
|
||||||
(defn home-tooltip-view []
|
|
||||||
[rn/view (styles/chat-tooltip)
|
|
||||||
[rn/view {:style {:width 66 :position :absolute :top -6 :background-color quo.colors/white
|
|
||||||
:align-items :center}}
|
|
||||||
[rn/image {:source (resources/get-image :empty-chats-header)
|
|
||||||
:style {:width 50 :height 50}}]]
|
|
||||||
[rn/touchable-highlight
|
|
||||||
{:style {:position :absolute :right 0 :top 0
|
|
||||||
:width 44 :height 44 :align-items :center :justify-content :center}
|
|
||||||
:on-press #(re-frame/dispatch [:multiaccounts.ui/hide-home-tooltip])
|
|
||||||
:accessibility-label :hide-home-button}
|
|
||||||
[icons/icon :main-icons/close-circle {:color quo.colors/gray}]]
|
|
||||||
[react/i18n-text {:style styles/no-chats-text :key :chat-and-transact}]
|
|
||||||
[rn/view {:align-items :center
|
|
||||||
:margin-top 8
|
|
||||||
:margin-bottom 12}
|
|
||||||
[invite/button]]])
|
|
||||||
|
|
||||||
(defn welcome-blank-chats []
|
|
||||||
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
|
|
||||||
[icons/icon :main-icons/placeholder20 {:width 120 :height 120}]
|
|
||||||
[rn/text {:style (merge typography/font-semi-bold typography/paragraph-1)} (i18n/label :t/no-messages)]
|
|
||||||
[rn/text {:style (merge typography/font-regular typography/paragraph-2)} (i18n/label :t/blank-messages-text)]])
|
|
||||||
|
|
||||||
(defn welcome-blank-page []
|
|
||||||
[rn/view {:style {:flex 1
|
|
||||||
:flex-direction :row
|
|
||||||
:align-items :center
|
|
||||||
:justify-content :center}}
|
|
||||||
[react/i18n-text {:style styles/welcome-blank-text :key :welcome-blank-message}]])
|
|
||||||
|
|
||||||
(defonce search-active? (reagent/atom false))
|
|
||||||
|
|
||||||
(defn search-input-wrapper [search-filter chats-empty]
|
|
||||||
[rn/view {:padding-horizontal 16
|
|
||||||
:padding-vertical 10}
|
|
||||||
[search-input/search-input
|
|
||||||
{:search-active? search-active?
|
|
||||||
:search-filter search-filter
|
|
||||||
:on-cancel #(re-frame/dispatch [:search/home-filter-changed nil])
|
|
||||||
:on-blur (fn []
|
|
||||||
(when chats-empty
|
|
||||||
(re-frame/dispatch [:search/home-filter-changed nil]))
|
|
||||||
(re-frame/dispatch [::new-chat/clear-new-identity]))
|
|
||||||
:on-focus (fn [search-filter]
|
|
||||||
(when-not search-filter
|
|
||||||
(re-frame/dispatch [:search/home-filter-changed ""])
|
|
||||||
(re-frame/dispatch [::new-chat/clear-new-identity])))
|
|
||||||
:on-change (fn [text]
|
|
||||||
(re-frame/dispatch [:search/home-filter-changed text])
|
|
||||||
(re-frame/dispatch [:set-in [:contacts/new-identity :state] :searching])
|
|
||||||
(debounce/debounce-and-dispatch [:new-chat/set-new-identity text] 300))}]])
|
|
||||||
|
|
||||||
(defn start-suggestion [search-value]
|
|
||||||
(let [{:keys [state ens-name public-key]}
|
|
||||||
@(re-frame/subscribe [:contacts/new-identity])
|
|
||||||
valid-private? (= state :valid)
|
|
||||||
valid-public? (db/valid-topic? search-value)]
|
|
||||||
(when (or valid-public? valid-private?)
|
|
||||||
[rn/view
|
|
||||||
[quo/list-header (i18n/label :t/search-no-chat-found)]
|
|
||||||
(when valid-private?
|
|
||||||
[quo/list-item {:theme :accent
|
|
||||||
:icon :main-icons/private-chat
|
|
||||||
:title (or ens-name (utils/get-shortened-address public-key))
|
|
||||||
:subtitle (i18n/label :t/join-new-private-chat)
|
|
||||||
:on-press (fn []
|
|
||||||
(debounce/dispatch-and-chill [:contact.ui/contact-code-submitted false] 3000)
|
|
||||||
(re-frame/dispatch [:search/home-filter-changed nil]))}])
|
|
||||||
(when valid-public?
|
|
||||||
[quo/list-item {:theme :accent
|
|
||||||
:icon :main-icons/public-chat
|
|
||||||
:title (str "#" search-value)
|
|
||||||
:subtitle (i18n/label :t/join-new-public-chat)
|
|
||||||
:on-press (fn []
|
|
||||||
(re-frame/dispatch [:chat.ui/start-public-chat search-value])
|
|
||||||
(re-frame/dispatch [:set :public-group-topic nil])
|
|
||||||
(re-frame/dispatch [:search/home-filter-changed nil]))}])])))
|
|
||||||
|
|
||||||
(defn chat-list-key-fn [item]
|
|
||||||
(or (:chat-id item) (:public-key item) (:id item)))
|
|
||||||
|
|
||||||
(defn get-item-layout [_ index]
|
|
||||||
#js {:length 64 :offset (* 64 index) :index index})
|
|
||||||
|
|
||||||
(def selected-tab (reagent/atom :recent))
|
|
||||||
|
|
||||||
(defn prepare-items [current-active-tab items]
|
|
||||||
(if (= current-active-tab :groups)
|
|
||||||
(filter #(-> % :group-chat (= true)) items)
|
|
||||||
(filter #(-> % (contains? :chat-id)) items)))
|
|
||||||
|
|
||||||
(defn prepare-contacts [contacts]
|
|
||||||
(let [data (atom {})]
|
|
||||||
(doseq [i (range (count contacts))]
|
|
||||||
(let [first-char (get (:alias (nth contacts i)) 0)]
|
|
||||||
(if-not (contains? @data first-char)
|
|
||||||
(swap! data #(assoc % first-char {:title first-char :data [(nth contacts i)]}))
|
|
||||||
(swap! data #(assoc-in % [first-char :data] (conj (:data (get @data first-char)) (nth contacts i)))))))
|
|
||||||
(swap! data #(sort @data))
|
|
||||||
(vals @data)))
|
|
||||||
|
|
||||||
(defn contacts-section-header [{:keys [title]}]
|
|
||||||
[rn/view {:style {:border-top-width 1 :border-top-color colors/neutral-20 :padding-vertical 8 :padding-horizontal 20 :margin-top 8}}
|
|
||||||
[rn/text {:style (merge typography/font-medium typography/paragraph-2 {:color colors/neutral-50})} title]])
|
|
||||||
|
|
||||||
(defn find-contact-requests [notifications]
|
|
||||||
(let [received-requests (atom [])
|
|
||||||
has-unread? (atom false)]
|
|
||||||
(doseq [i (range (count notifications))]
|
|
||||||
(doseq [j (range (count (:data (nth notifications i))))]
|
|
||||||
(when (= 1 (get-in (nth (:data (nth notifications i)) j) [:message :contact-request-state]))
|
|
||||||
(swap! received-requests conj (nth (:data (nth notifications i)) j)))
|
|
||||||
(when (= false (get-in (nth (:data (nth notifications i)) j) [:read]))
|
|
||||||
(reset! has-unread? true))))
|
|
||||||
{:received-requests @received-requests :has-unread? @has-unread?}))
|
|
||||||
|
|
||||||
(def selected-requests-tab (reagent/atom :received))
|
|
||||||
|
|
||||||
(defn contact-requests-sheet []
|
|
||||||
[:f>
|
|
||||||
(fn []
|
|
||||||
(let [{window-height :height} (rn/use-window-dimensions)
|
|
||||||
safe-area (safe-area/use-safe-area)
|
|
||||||
notifications (<sub [:activity.center/notifications-grouped-by-date])
|
|
||||||
{received-requests :received-requests} (find-contact-requests notifications)
|
|
||||||
sent-requests []]
|
|
||||||
[rn/view {:style {:margin-left 20
|
|
||||||
:height (- window-height (:top safe-area))}}
|
|
||||||
[rn/touchable-opacity
|
|
||||||
{:on-press #(>evt [:bottom-sheet/hide])
|
|
||||||
:style
|
|
||||||
{: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-bottom 24}}
|
|
||||||
[quo2.icons/icon :i/close {:color (colors/theme-colors "#000000" "#ffffff")}]]
|
|
||||||
[rn/text {:style (merge
|
|
||||||
typography/heading-1
|
|
||||||
typography/font-semi-bold
|
|
||||||
{:color (colors/theme-colors "#000000" "#ffffff")})}
|
|
||||||
(i18n/label :t/pending-requests)]
|
|
||||||
[quo2.tabs/tabs
|
|
||||||
{:style {:margin-top 12 :margin-bottom 20}
|
|
||||||
:size 32
|
|
||||||
:on-change #(reset! selected-requests-tab %)
|
|
||||||
:default-active :received
|
|
||||||
:data [{:id :received
|
|
||||||
:label (i18n/label :t/received)}
|
|
||||||
{:id :sent
|
|
||||||
:label (i18n/label :t/sent)}]}]
|
|
||||||
[list/flat-list
|
|
||||||
{:key-fn :chat-id
|
|
||||||
:data (if (= @selected-requests-tab :received) received-requests sent-requests)
|
|
||||||
:render-fn received-cr-item/received-cr-item}]]))])
|
|
||||||
|
|
||||||
(defn get-display-name [{:keys [chat-id message]}]
|
|
||||||
(let [name (first (<sub [:contacts/contact-two-names-by-identity chat-id]))
|
|
||||||
no-ens-name (str/blank? (get-in message [:content :ens-name]))]
|
|
||||||
(if no-ens-name
|
|
||||||
(first (str/split name " "))
|
|
||||||
name)))
|
|
||||||
|
|
||||||
(defn requests-summary [requests]
|
|
||||||
(case (count requests)
|
|
||||||
1
|
|
||||||
(get-display-name (first requests))
|
|
||||||
2
|
|
||||||
(str (get-display-name (first requests)) " " (i18n/label :t/and) " " (get-display-name (second requests)))
|
|
||||||
(str (get-display-name (first requests)) ", " (get-display-name (second requests)) " " (i18n/label :t/and) " " (- (count requests) 2) " " (i18n/label :t/more))))
|
|
||||||
|
|
||||||
(defn contact-requests [requests]
|
|
||||||
[rn/touchable-opacity
|
|
||||||
{:active-opacity 1
|
|
||||||
:on-press #(do
|
|
||||||
(>evt
|
|
||||||
[:bottom-sheet/show-sheet
|
|
||||||
{:content (fn [] [contact-requests-sheet])}])
|
|
||||||
(>evt [:mark-all-activity-center-notifications-as-read]))
|
|
||||||
:style {:flex-direction :row
|
|
||||||
:margin 8
|
|
||||||
:padding-horizontal 12
|
|
||||||
:padding-vertical 8
|
|
||||||
:align-items :center}}
|
|
||||||
[rn/view {:style {:justify-content :center
|
|
||||||
:align-items :center
|
|
||||||
:width 32
|
|
||||||
:height 32
|
|
||||||
:border-radius 16
|
|
||||||
:border-width 1
|
|
||||||
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80)}}
|
|
||||||
[quo2.icons/icon :i/pending-user {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]
|
|
||||||
[rn/view {:style {:margin-left 8}}
|
|
||||||
[rn/text {:style
|
|
||||||
(merge typography/paragraph-1 typography/font-semi-bold {:color (colors/theme-colors "#000000" "#ffffff")})} (i18n/label :t/pending-requests)]
|
|
||||||
[rn/text {:style (merge typography/paragraph-2 typography/font-regular {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)})} (requests-summary requests)]]
|
|
||||||
[info-count (count requests)]])
|
|
||||||
|
|
||||||
(defn chats []
|
|
||||||
(let [{:keys [items search-filter]} (<sub [:home-items])
|
|
||||||
current-active-tab @selected-tab
|
|
||||||
items (prepare-items current-active-tab items)
|
|
||||||
contacts (<sub [:contacts/active])
|
|
||||||
contacts (prepare-contacts contacts)
|
|
||||||
notifications (<sub [:activity.center/notifications-grouped-by-date])
|
|
||||||
{requests :received-requests new-info :has-unread?} (find-contact-requests notifications)]
|
|
||||||
[rn/view {:style {:flex 1}}
|
|
||||||
[discover-card/discover-card {:title (i18n/label :t/invite-friends-to-status)
|
|
||||||
:description (i18n/label :t/share-invite-link)}]
|
|
||||||
[quo2.tabs/tabs {:style {:margin-left 20
|
|
||||||
:margin-bottom 20
|
|
||||||
:margin-top 24}
|
|
||||||
:size 32
|
|
||||||
:on-change #(reset! selected-tab %)
|
|
||||||
:default-active @selected-tab
|
|
||||||
:data [{:id :recent
|
|
||||||
:label (i18n/label :t/recent)}
|
|
||||||
{:id :groups
|
|
||||||
:label (i18n/label :t/groups)}
|
|
||||||
{:id :contacts
|
|
||||||
:label (i18n/label :t/contacts)
|
|
||||||
:new-info new-info}]}]
|
|
||||||
(if (and (empty? items)
|
|
||||||
(empty? search-filter)
|
|
||||||
(not @search-active?))
|
|
||||||
[welcome-blank-chats]
|
|
||||||
(if (not= current-active-tab :contacts)
|
|
||||||
[list/flat-list
|
|
||||||
{:key-fn chat-list-key-fn
|
|
||||||
:getItemLayout get-item-layout
|
|
||||||
:on-end-reached #(re-frame/dispatch [:chat.ui/show-more-chats])
|
|
||||||
:keyboard-should-persist-taps :always
|
|
||||||
:data items
|
|
||||||
:render-fn messages-home-item}]
|
|
||||||
[rn/view {:style {:flex 1}} (when (> (count requests) 0)
|
|
||||||
[contact-requests requests])
|
|
||||||
[rn/section-list
|
|
||||||
{:key-fn :title
|
|
||||||
:sticky-section-headers-enabled false
|
|
||||||
:sections contacts
|
|
||||||
:render-section-header-fn contacts-section-header
|
|
||||||
:render-fn contact-item}]]))]))
|
|
||||||
|
|
||||||
(views/defview chats-list []
|
|
||||||
(views/letsubs [loading? [:chats/loading?]]
|
|
||||||
[:<>
|
|
||||||
[connectivity/loading-indicator]
|
|
||||||
(if loading?
|
|
||||||
[rn/view {:flex 1 :align-items :center :justify-content :center}
|
|
||||||
[rn/activity-indicator {:animating true}]]
|
|
||||||
[chats])]))
|
|
||||||
|
|
||||||
(views/defview plus-button []
|
|
||||||
(views/letsubs [logging-in? [:multiaccounts/login]]
|
|
||||||
[components.plus-button/plus-button
|
|
||||||
{:on-press (when-not logging-in?
|
|
||||||
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
|
|
||||||
:loading logging-in?
|
|
||||||
:accessibility-label :new-chat-button}]))
|
|
||||||
|
|
||||||
(views/defview notifications-button []
|
|
||||||
(views/letsubs [notif-count [:activity.center/notifications-count]]
|
|
||||||
[rn/view
|
|
||||||
[quo2.button/button {:type :grey
|
|
||||||
:size 32
|
|
||||||
:width 32
|
|
||||||
:style {:margin-left 12}
|
|
||||||
:accessibility-label :notifications-button
|
|
||||||
:on-press #(do
|
|
||||||
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
|
|
||||||
(if config/new-activity-center-enabled?
|
|
||||||
(re-frame/dispatch [:activity-center/open])
|
|
||||||
(re-frame/dispatch [:navigate-to :notifications-center])))}
|
|
||||||
[icons/icon :main-icons/notification2 {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
|
|
||||||
(when (pos? notif-count)
|
|
||||||
[rn/view {:style (merge (styles/counter-public-container) {:top 5 :right 5})
|
|
||||||
:pointer-events :none}
|
|
||||||
[rn/view {:style styles/counter-public
|
|
||||||
:accessibility-label :notifications-unread-badge}]])]))
|
|
||||||
|
|
||||||
(defn qr-button []
|
|
||||||
[quo2.button/button {:type :grey
|
|
||||||
:accessibility-label "qr-button"
|
|
||||||
:size 32
|
|
||||||
:width 32
|
|
||||||
:style {:margin-left 12}
|
|
||||||
:on-press #(do
|
|
||||||
(re-frame/dispatch [::qr-scanner/scan-code
|
|
||||||
{:handler ::qr-scanner/on-scan-success}]))}
|
|
||||||
[icons/icon :main-icons/qr2 {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
|
||||||
|
|
||||||
(defn scan-button []
|
|
||||||
[quo2.button/button {:type :grey
|
|
||||||
:size 32
|
|
||||||
:width 32
|
|
||||||
:accessibility-label "scan-button"
|
|
||||||
:on-press #(do
|
|
||||||
(re-frame/dispatch [::qr-scanner/scan-code
|
|
||||||
{:handler ::qr-scanner/on-scan-success}]))}
|
|
||||||
[icons/icon :main-icons/scan2 {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
|
||||||
|
|
||||||
(views/defview profile-button []
|
|
||||||
(views/letsubs [{:keys [public-key preferred-name emoji]} [:multiaccount]]
|
|
||||||
[rn/view
|
|
||||||
[chat-icon/emoji-chat-icon-view public-key false preferred-name emoji
|
|
||||||
{:size 28
|
|
||||||
:chat-icon chat-icon.styles/chat-icon-chat-list}]]))
|
|
||||||
|
|
||||||
(defn home []
|
|
||||||
[:f>
|
|
||||||
(fn []
|
|
||||||
(quo.react/effect! #(re-frame/dispatch [:get-activity-center-notifications]))
|
|
||||||
[quo.rn/keyboard-avoiding-view {:style {:flex 1
|
|
||||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
|
|
||||||
:ignore-offset true}
|
|
||||||
[topbar/topbar {:navigation :none
|
|
||||||
:use-insets true
|
|
||||||
:background (colors/theme-colors colors/neutral-5 colors/neutral-95)
|
|
||||||
:left-component [rn/view {:flex-direction :row :margin-left 20}
|
|
||||||
[profile-button]]
|
|
||||||
:right-component [rn/view {:flex-direction :row :margin-right 20}
|
|
||||||
[scan-button]
|
|
||||||
[qr-button]
|
|
||||||
[notifications-button]]
|
|
||||||
:border-bottom false}]
|
|
||||||
[rn/view {:flex-direction :row
|
|
||||||
:justify-content :space-between
|
|
||||||
:align-items :center
|
|
||||||
:margin-horizontal 20
|
|
||||||
:margin-top 15
|
|
||||||
:margin-bottom 20}
|
|
||||||
[quo2.text/text {:size :heading-1 :weight :semi-bold} (i18n/label :t/messages)]
|
|
||||||
[plus-button]]
|
|
||||||
[chats-list]])])
|
|
|
@ -38,10 +38,10 @@
|
||||||
[status-im.utils.security :as security]
|
[status-im.utils.security :as security]
|
||||||
[quo2.components.icon :as icons]
|
[quo2.components.icon :as icons]
|
||||||
[status-im.utils.datetime :as time]
|
[status-im.utils.datetime :as time]
|
||||||
[status-im.ui2.screens.chat.components.message-home-item.view :as message-home-item]
|
|
||||||
[quo2.components.avatars.user-avatar :as user-avatar]
|
[quo2.components.avatars.user-avatar :as user-avatar]
|
||||||
[quo2.components.markdown.text :as text]
|
[quo2.components.markdown.text :as text]
|
||||||
[status-im.utils.utils :as utils])
|
[status-im.utils.utils :as utils]
|
||||||
|
[status-im2.contexts.chat.home.chat-list-item.view :as home.chat-list-item])
|
||||||
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
(:require-macros [status-im.utils.views :refer [defview letsubs]]))
|
||||||
|
|
||||||
(defview mention-element [from]
|
(defview mention-element [from]
|
||||||
|
@ -286,7 +286,7 @@
|
||||||
:number-of-lines 1
|
:number-of-lines 1
|
||||||
:style {:width "45%"}}
|
:style {:width "45%"}}
|
||||||
display-name]
|
display-name]
|
||||||
[message-home-item/verified-or-contact-icon contact]
|
[home.chat-list-item/verified-or-contact-icon contact]
|
||||||
(when show-key?
|
(when show-key?
|
||||||
(let [props {:size :label
|
(let [props {:size :label
|
||||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}]
|
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}]
|
||||||
|
@ -329,12 +329,13 @@
|
||||||
:pointer-events :box-none}
|
:pointer-events :box-none}
|
||||||
[rn/view {:style {:width 40}}
|
[rn/view {:style {:width 40}}
|
||||||
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
||||||
[user-avatar/user-avatar {:full-name display-name
|
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/show-profile from])}
|
||||||
:profile-picture photo-path
|
[user-avatar/user-avatar {:full-name display-name
|
||||||
:status-indicator? true
|
:profile-picture photo-path
|
||||||
:online? true
|
:status-indicator? true
|
||||||
:size :small
|
:online? true
|
||||||
:ring? false}])]
|
:size :small
|
||||||
|
:ring? false}]])]
|
||||||
[rn/view {:style (style/message-author-wrapper)}
|
[rn/view {:style (style/message-author-wrapper)}
|
||||||
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
||||||
[display-name-view display-name contact timestamp true])
|
[display-name-view display-name contact timestamp true])
|
||||||
|
|
|
@ -1,56 +0,0 @@
|
||||||
(ns status-im.ui2.screens.common.alert.view
|
|
||||||
(:require
|
|
||||||
[reagent.core :as reagent]
|
|
||||||
[status-im.i18n.i18n :as i18n]
|
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[quo2.components.markdown.text :as quo2.text]
|
|
||||||
[react-native.core :as rn]
|
|
||||||
[quo2.core :as quo2]
|
|
||||||
[quo2.components.buttons.button :as quo2.button]
|
|
||||||
[status-im.ui2.screens.common.alert.style :as style]
|
|
||||||
[quo2.components.selectors.selectors :as selectors]))
|
|
||||||
|
|
||||||
(defn avatar [group-chat color display-name photo-path]
|
|
||||||
(if group-chat
|
|
||||||
[quo2/group-avatar {:color color
|
|
||||||
:size :small}]
|
|
||||||
[quo2/user-avatar {:full-name display-name
|
|
||||||
:profile-picture photo-path
|
|
||||||
:size :xxs
|
|
||||||
:status-indicator false}]))
|
|
||||||
|
|
||||||
(defn extra-action-view [extra-action extra-text extra-action-selected?]
|
|
||||||
(when extra-action
|
|
||||||
[rn/view {:style {:margin-top 16 :flex-direction :row}}
|
|
||||||
[selectors/checkbox {:on-change (fn [selected?] (reset! extra-action-selected? selected?))}]
|
|
||||||
[quo2.text/text {:style {:margin-left 10}} extra-text]]))
|
|
||||||
|
|
||||||
(defn alert [{:keys [title description context button-text on-press extra-action extra-text]}]
|
|
||||||
(let [extra-action-selected? (reagent/atom false)]
|
|
||||||
(fn []
|
|
||||||
(let [{:keys [group-chat chat-id public-key color name]} context
|
|
||||||
id (or chat-id public-key)
|
|
||||||
display-name (if-not group-chat (first (rf/sub [:contacts/contact-two-names-by-identity id])) name)
|
|
||||||
contact (when-not group-chat (rf/sub [:contacts/contact-by-address id]))
|
|
||||||
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path id]))]
|
|
||||||
[rn/view {:style {:margin-horizontal 20}}
|
|
||||||
[quo2.text/text {:weight :semi-bold
|
|
||||||
:size :heading-1} title]
|
|
||||||
[rn/view {:style (style/context-container)}
|
|
||||||
[avatar group-chat color display-name photo-path]
|
|
||||||
[quo2.text/text {:weight :medium
|
|
||||||
:size :paragraph-2
|
|
||||||
:style {:margin-left 4}} display-name]]
|
|
||||||
[quo2.text/text description]
|
|
||||||
[extra-action-view extra-action extra-text extra-action-selected?]
|
|
||||||
[rn/view {:style (style/buttons-container)}
|
|
||||||
[quo2.button/button {:type :grey
|
|
||||||
:style {:flex 0.48}
|
|
||||||
:on-press #(rf/dispatch [:bottom-sheet/hide])}
|
|
||||||
(i18n/label :t/close)]
|
|
||||||
[quo2.button/button {:type :danger
|
|
||||||
:style {:flex 0.48}
|
|
||||||
:on-press #(do
|
|
||||||
(when @extra-action-selected? (extra-action))
|
|
||||||
(on-press))}
|
|
||||||
button-text]]]))))
|
|
|
@ -1,4 +0,0 @@
|
||||||
(ns status-im.ui2.screens.common.core
|
|
||||||
(:require status-im.ui2.screens.common.alert.view))
|
|
||||||
|
|
||||||
(def alert status-im.ui2.screens.common.alert.view/alert)
|
|
|
@ -89,7 +89,6 @@
|
||||||
(when id
|
(when id
|
||||||
(clear-timeout id)))))
|
(clear-timeout id)))))
|
||||||
|
|
||||||
;;TODO (14/11/22 flexsurfer) haven't moved yet
|
|
||||||
(defn get-shortened-address
|
(defn get-shortened-address
|
||||||
"Takes first and last 4 digits from address including leading 0x
|
"Takes first and last 4 digits from address including leading 0x
|
||||||
and adds unicode ellipsis in between"
|
and adds unicode ellipsis in between"
|
||||||
|
@ -101,6 +100,7 @@
|
||||||
(when address
|
(when address
|
||||||
(get-shortened-address (eip55/address->checksum (ethereum/normalized-hex address)))))
|
(get-shortened-address (eip55/address->checksum (ethereum/normalized-hex address)))))
|
||||||
|
|
||||||
|
;;TODO (14/11/22 flexsurfer) haven't moved yet
|
||||||
(defn format-decimals [amount places]
|
(defn format-decimals [amount places]
|
||||||
(let [decimal-part (get (string/split (str amount) ".") 1)]
|
(let [decimal-part (get (string/split (str amount) ".") 1)]
|
||||||
(if (> (count decimal-part) places)
|
(if (> (count decimal-part) places)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im.ui2.screens.common.alert.style
|
(ns status-im2.common.confirmation-drawer.style
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
(defn context-container []
|
(defn context-container []
|
||||||
|
@ -12,7 +12,7 @@
|
||||||
:margin-left -4
|
:margin-left -4
|
||||||
:margin-bottom 16})
|
:margin-bottom 16})
|
||||||
|
|
||||||
(defn buttons-container []
|
(def buttons-container
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
||||||
:justify-content :space-between
|
:justify-content :space-between
|
||||||
:margin-top 20})
|
:margin-top 20})
|
|
@ -0,0 +1,52 @@
|
||||||
|
(ns status-im2.common.confirmation-drawer.view
|
||||||
|
(:require [reagent.core :as reagent]
|
||||||
|
[i18n.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[status-im2.common.confirmation-drawer.style :as style]))
|
||||||
|
|
||||||
|
(defn avatar [group-chat color display-name photo-path]
|
||||||
|
(if group-chat
|
||||||
|
[quo/group-avatar {:color color
|
||||||
|
:size :small}]
|
||||||
|
[quo/user-avatar {:full-name display-name
|
||||||
|
:profile-picture photo-path
|
||||||
|
:size :xxs
|
||||||
|
:status-indicator false}]))
|
||||||
|
|
||||||
|
(defn extra-action-view [extra-action extra-text extra-action-selected?]
|
||||||
|
(when extra-action
|
||||||
|
[rn/view {:style {:margin-top 16 :flex-direction :row}}
|
||||||
|
[quo/checkbox {:on-change (fn [selected?] (reset! extra-action-selected? selected?))}]
|
||||||
|
[quo/text {:style {:margin-left 10}} extra-text]]))
|
||||||
|
|
||||||
|
(defn confirmation-drawer [{:keys [title description context button-text on-press extra-action extra-text]}]
|
||||||
|
(let [extra-action-selected? (reagent/atom false)]
|
||||||
|
(fn []
|
||||||
|
(let [{:keys [group-chat chat-id public-key color name]} context
|
||||||
|
id (or chat-id public-key)
|
||||||
|
display-name (if-not group-chat (first (rf/sub [:contacts/contact-two-names-by-identity id])) name)
|
||||||
|
contact (when-not group-chat (rf/sub [:contacts/contact-by-address id]))
|
||||||
|
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path id]))]
|
||||||
|
[rn/view {:style {:margin-horizontal 20}}
|
||||||
|
[quo/text {:weight :semi-bold
|
||||||
|
:size :heading-1} title]
|
||||||
|
[rn/view {:style (style/context-container)}
|
||||||
|
[avatar group-chat color display-name photo-path]
|
||||||
|
[quo/text {:weight :medium
|
||||||
|
:size :paragraph-2
|
||||||
|
:style {:margin-left 4}} display-name]]
|
||||||
|
[quo/text description]
|
||||||
|
[extra-action-view extra-action extra-text extra-action-selected?]
|
||||||
|
[rn/view {:style style/buttons-container}
|
||||||
|
[quo/button {:type :grey
|
||||||
|
:style {:flex 0.48} ;;WUT? 0.48 , whats that ?
|
||||||
|
:on-press #(rf/dispatch [:bottom-sheet/hide])}
|
||||||
|
(i18n/label :t/close)]
|
||||||
|
[quo/button {:type :danger
|
||||||
|
:style {:flex 0.48}
|
||||||
|
:on-press #(do
|
||||||
|
(when @extra-action-selected? (extra-action))
|
||||||
|
(on-press))}
|
||||||
|
button-text]]]))))
|
|
@ -0,0 +1,10 @@
|
||||||
|
(ns status-im2.common.contact-list-item.style)
|
||||||
|
|
||||||
|
(def container
|
||||||
|
{:margin-top 8
|
||||||
|
:margin-horizontal 8
|
||||||
|
:padding-vertical 8
|
||||||
|
:padding-horizontal 12
|
||||||
|
:border-radius 12
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center})
|
|
@ -0,0 +1,49 @@
|
||||||
|
(ns status-im2.common.contact-list-item.view
|
||||||
|
(:require [utils.re-frame :as rf]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[status-im2.common.contact-list-item.style :as style]
|
||||||
|
[utils.address :as utils.address]
|
||||||
|
[status-im2.common.home.actions.view :as actions]))
|
||||||
|
|
||||||
|
(defn open-chat [chat-id]
|
||||||
|
(rf/dispatch [:dismiss-keyboard])
|
||||||
|
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
|
||||||
|
(rf/dispatch [:search/home-filter-changed nil])
|
||||||
|
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id]))
|
||||||
|
|
||||||
|
(defn contact-item [item]
|
||||||
|
(let [{:keys [public-key ens-verified added? images]} item
|
||||||
|
display-name (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))
|
||||||
|
photo-path (when (seq images) (rf/sub [:chats/photo-path public-key]))
|
||||||
|
current-pk (rf/sub [:multiaccount/public-key])]
|
||||||
|
[rn/touchable-opacity (merge {:style style/container
|
||||||
|
:on-press #(open-chat public-key)
|
||||||
|
:on-long-press #(when-not (= current-pk public-key)
|
||||||
|
(rf/dispatch [:bottom-sheet/show-sheet
|
||||||
|
{:content (fn [] [actions/actions item])}]))})
|
||||||
|
[quo/user-avatar {:full-name display-name
|
||||||
|
:profile-picture photo-path
|
||||||
|
:status-indicator? true
|
||||||
|
:online? true
|
||||||
|
:size :small
|
||||||
|
:ring? false}]
|
||||||
|
[rn/view {:style {:margin-left 8}}
|
||||||
|
[rn/view {:style {:flex-direction :row}}
|
||||||
|
[quo/text {:weight :semi-bold} display-name]
|
||||||
|
(if ens-verified
|
||||||
|
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
||||||
|
[quo/icon :i/verified {:no-color true :size 12 :color (colors/theme-colors colors/success-50 colors/success-60)}]]
|
||||||
|
(when added?
|
||||||
|
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
||||||
|
[quo/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
|
||||||
|
[quo/text {:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||||
|
(utils.address/get-shortened-address public-key)]]
|
||||||
|
(when-not (= current-pk public-key)
|
||||||
|
[rn/touchable-opacity {:style {:position :absolute
|
||||||
|
:right 20}
|
||||||
|
:active-opacity 1
|
||||||
|
:on-press #(rf/dispatch [:bottom-sheet/show-sheet
|
||||||
|
{:content (fn [] [actions/actions item])}])}
|
||||||
|
[quo/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]])]))
|
|
@ -1,12 +1,13 @@
|
||||||
(ns status-im.ui2.screens.chat.actions
|
(ns status-im2.common.home.actions.view
|
||||||
(:require
|
(:require [i18n.i18n :as i18n]
|
||||||
[status-im.chat.models :as chat.models]
|
[utils.re-frame :as rf]
|
||||||
[status-im.chat.models.pin-message :as models.pin-message]
|
[quo2.components.drawers.action-drawers :as drawer]
|
||||||
[status-im.i18n.i18n :as i18n]
|
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
|
||||||
[utils.re-frame :as rf]
|
|
||||||
[status-im.ui2.screens.common.core :as common]
|
;;TODO move to status-im2
|
||||||
[status-im.constants :as constants]
|
[status-im.constants :as constants]
|
||||||
[quo2.components.drawers.action-drawers :as drawer]))
|
[status-im.chat.models :as chat.models]
|
||||||
|
[status-im.chat.models.pin-message :as models.pin-message]))
|
||||||
|
|
||||||
(defn- entry [{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
|
(defn- entry [{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
|
||||||
{:pre [(keyword? icon)
|
{:pre [(keyword? icon)
|
||||||
|
@ -45,37 +46,41 @@
|
||||||
(defn clear-history-action [{:keys [chat-id] :as item}]
|
(defn clear-history-action [{:keys [chat-id] :as item}]
|
||||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||||
{:content (fn []
|
{:content (fn []
|
||||||
(common/alert {:title (i18n/label :t/clear-history?)
|
(confirmation-drawer/confirmation-drawer
|
||||||
:description (i18n/label :t/clear-history-confirmation-content)
|
{:title (i18n/label :t/clear-history?)
|
||||||
:context item
|
:description (i18n/label :t/clear-history-confirmation-content)
|
||||||
:button-text (i18n/label :t/clear-history)
|
:context item
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
|
:button-text (i18n/label :t/clear-history)
|
||||||
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
|
||||||
|
|
||||||
(defn delete-chat-action [{:keys [chat-id] :as item}]
|
(defn delete-chat-action [{:keys [chat-id] :as item}]
|
||||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||||
{:content (fn []
|
{:content (fn []
|
||||||
(common/alert {:title (i18n/label :t/delete-chat?)
|
(confirmation-drawer/confirmation-drawer
|
||||||
:description (i18n/label :t/delete-chat-confirmation)
|
{:title (i18n/label :t/delete-chat?)
|
||||||
:context item
|
:description (i18n/label :t/delete-chat-confirmation)
|
||||||
:button-text (i18n/label :t/delete-chat)
|
:context item
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
|
:button-text (i18n/label :t/delete-chat)
|
||||||
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
|
||||||
|
|
||||||
(defn leave-group-action [{:keys [chat-id] :as item}]
|
(defn leave-group-action [{:keys [chat-id] :as item}]
|
||||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||||
{:content (fn []
|
{:content (fn []
|
||||||
(common/alert {:title (i18n/label :t/leave-group?)
|
(confirmation-drawer/confirmation-drawer
|
||||||
:description (i18n/label :t/leave-chat-confirmation)
|
{:title (i18n/label :t/leave-group?)
|
||||||
:context item
|
:description (i18n/label :t/leave-chat-confirmation)
|
||||||
:button-text (i18n/label :t/leave-group)
|
:context item
|
||||||
:on-press #(hide-sheet-and-dispatch [:chat.ui/leave-chat chat-id])}))}]))
|
:button-text (i18n/label :t/leave-group)
|
||||||
|
:on-press #(hide-sheet-and-dispatch [:chat.ui/leave-chat chat-id])}))}]))
|
||||||
|
|
||||||
(defn block-user-action [{:keys [public-key] :as item}]
|
(defn block-user-action [{:keys [public-key] :as item}]
|
||||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||||
{:content (fn [] (common/alert {:title (i18n/label :t/block-user?)
|
{:content (fn [] (confirmation-drawer/confirmation-drawer
|
||||||
:description (i18n/label :t/block-contact-details)
|
{:title (i18n/label :t/block-user?)
|
||||||
:context item
|
:description (i18n/label :t/block-contact-details)
|
||||||
:button-text (i18n/label :t/block-user)
|
:context item
|
||||||
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}]))
|
:button-text (i18n/label :t/block-user)
|
||||||
|
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}]))
|
||||||
|
|
||||||
(defn mute-chat-entry [chat-id]
|
(defn mute-chat-entry [chat-id]
|
||||||
(let [muted? (rf/sub [:chats/muted chat-id])]
|
(let [muted? (rf/sub [:chats/muted chat-id])]
|
||||||
|
@ -330,4 +335,3 @@
|
||||||
constants/private-group-chat-type
|
constants/private-group-chat-type
|
||||||
[private-group-chat-actions item inside-chat?]
|
[private-group-chat-actions item inside-chat?]
|
||||||
[contact-actions item]))
|
[contact-actions item]))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
(ns status-im2.contexts.communities.home.style)
|
(ns status-im2.common.home.style)
|
||||||
|
|
||||||
(def title-column
|
(def title-column
|
||||||
{:flex-direction :row
|
{:flex-direction :row
|
|
@ -0,0 +1,110 @@
|
||||||
|
(ns status-im2.common.home.view
|
||||||
|
(:require [react-native.core :as rn]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[status-im2.common.plus-button.view :as components.plus-button]
|
||||||
|
[status-im2.common.home.style :as style]
|
||||||
|
[react-native.hole-view :as hole-view]
|
||||||
|
[status-im2.setup.config :as config]
|
||||||
|
[utils.re-frame :as rf]))
|
||||||
|
|
||||||
|
(defn navigate-to-activity-center []
|
||||||
|
(rf/dispatch [:mark-all-activity-center-notifications-as-read])
|
||||||
|
(if config/new-activity-center-enabled?
|
||||||
|
(rf/dispatch [:activity-center/open])
|
||||||
|
(rf/dispatch [:navigate-to :notifications-center])))
|
||||||
|
|
||||||
|
(defn title-column [{:keys [label handler accessibility-label]}]
|
||||||
|
[rn/view style/title-column
|
||||||
|
[rn/view {:flex 1}
|
||||||
|
[quo/text style/title-column-text
|
||||||
|
label]]
|
||||||
|
[components.plus-button/plus-button
|
||||||
|
{:on-press handler
|
||||||
|
:accessibility-label accessibility-label}]])
|
||||||
|
|
||||||
|
(defn- get-button-common-props [type]
|
||||||
|
(let [default? (= type :default)
|
||||||
|
dark? (colors/dark?)]
|
||||||
|
{:icon true
|
||||||
|
:size 32
|
||||||
|
:style {:margin-left 12}
|
||||||
|
:type (if default?
|
||||||
|
(if dark? :grey :dark-grey)
|
||||||
|
type)
|
||||||
|
:override-background-color (when (and dark? default?)
|
||||||
|
colors/neutral-90)}))
|
||||||
|
|
||||||
|
(defn- base-button [icon on-press accessibility-label button-common-props]
|
||||||
|
[quo/button (merge
|
||||||
|
{:on-press on-press
|
||||||
|
:accessibility-label accessibility-label}
|
||||||
|
button-common-props)
|
||||||
|
icon])
|
||||||
|
|
||||||
|
(defn top-nav
|
||||||
|
"[top-nav opts]
|
||||||
|
opts
|
||||||
|
{:type :default/:blurred/:shell
|
||||||
|
:style override-style
|
||||||
|
:avatar user-avatar}
|
||||||
|
"
|
||||||
|
[{:keys [type open-profile style avatar hide-search]}]
|
||||||
|
(let [button-common-props (get-button-common-props type)
|
||||||
|
notif-count (rf/sub [:activity.center/notifications-count])
|
||||||
|
new-notifications? (pos? notif-count)
|
||||||
|
notification-indicator :unread-dot
|
||||||
|
counter-label "0"]
|
||||||
|
[rn/view {:style (merge
|
||||||
|
{:height 56}
|
||||||
|
style)}
|
||||||
|
;; Left Section
|
||||||
|
[rn/touchable-without-feedback {:on-press open-profile}
|
||||||
|
[rn/view {:style {:position :absolute
|
||||||
|
:left 20
|
||||||
|
:top 12}}
|
||||||
|
[quo/user-avatar
|
||||||
|
(merge
|
||||||
|
{:ring? true
|
||||||
|
:status-indicator? true
|
||||||
|
:size :small}
|
||||||
|
avatar)]]]
|
||||||
|
;; Right Section
|
||||||
|
[rn/view {:style {:position :absolute
|
||||||
|
:right 20
|
||||||
|
:top 12
|
||||||
|
:flex-direction :row}}
|
||||||
|
(when-not hide-search
|
||||||
|
[base-button :i/search #() :open-search-button button-common-props])
|
||||||
|
[base-button :i/scan #() :open-scanner-button button-common-props]
|
||||||
|
[base-button :i/qr-code #() :show-qr-button button-common-props]
|
||||||
|
[rn/view ;; Keep view instead of "[:<>" to make sure relative
|
||||||
|
;; position is calculated from this view instead of its parent
|
||||||
|
[hole-view/hole-view {:key new-notifications? ;; Key is required to force removal of holes
|
||||||
|
:holes (cond
|
||||||
|
(not new-notifications?) ;; No new notifications, remove holes
|
||||||
|
[]
|
||||||
|
|
||||||
|
(= notification-indicator :unread-dot)
|
||||||
|
[{:x 37 :y -3 :width 10 :height 10 :borderRadius 5}]
|
||||||
|
|
||||||
|
:else
|
||||||
|
[{:x 33 :y -7 :width 18 :height 18 :borderRadius 7}])}
|
||||||
|
[base-button :i/activity-center navigate-to-activity-center
|
||||||
|
:open-activity-center-button button-common-props]]
|
||||||
|
(when new-notifications?
|
||||||
|
(if (= notification-indicator :counter)
|
||||||
|
[quo/counter {:outline false
|
||||||
|
:override-text-color colors/white
|
||||||
|
:override-bg-color colors/primary-50
|
||||||
|
:style {:position :absolute
|
||||||
|
:left 34
|
||||||
|
:top -6}}
|
||||||
|
counter-label]
|
||||||
|
[rn/view {:style {:width 8
|
||||||
|
:height 8
|
||||||
|
:border-radius 4
|
||||||
|
:top -2
|
||||||
|
:left 38
|
||||||
|
:position :absolute
|
||||||
|
:background-color colors/primary-50}}]))]]]))
|
|
@ -0,0 +1,25 @@
|
||||||
|
(ns status-im2.contexts.chat.home.chat-list-item.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def container
|
||||||
|
{:margin-top 8
|
||||||
|
:margin-horizontal 8
|
||||||
|
:padding-vertical 8
|
||||||
|
:padding-horizontal 12
|
||||||
|
:border-radius 12
|
||||||
|
:flex-direction :row
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn count-container []
|
||||||
|
{:width 8
|
||||||
|
:height 8
|
||||||
|
:border-radius 4
|
||||||
|
:position :absolute
|
||||||
|
:right 26
|
||||||
|
:top 16
|
||||||
|
:background-color (colors/theme-colors colors/neutral-40 colors/neutral-60)})
|
||||||
|
|
||||||
|
(defn timestamp []
|
||||||
|
{:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
||||||
|
:margin-top 3
|
||||||
|
:margin-left 8})
|
|
@ -0,0 +1,124 @@
|
||||||
|
(ns status-im2.contexts.chat.home.chat-list-item.view
|
||||||
|
(:require [clojure.string :as string]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[status-im2.contexts.chat.home.chat-list-item.style :as style]
|
||||||
|
[status-im2.common.home.actions.view :as actions]
|
||||||
|
|
||||||
|
;;TODO move to status-im2
|
||||||
|
[status-im.utils.datetime :as time]))
|
||||||
|
|
||||||
|
(def max-subheader-length 50)
|
||||||
|
|
||||||
|
(defn open-chat [chat-id]
|
||||||
|
(fn []
|
||||||
|
(rf/dispatch [:dismiss-keyboard])
|
||||||
|
(rf/dispatch [:chat.ui/navigate-to-chat-nav2 chat-id])
|
||||||
|
(rf/dispatch [:search/home-filter-changed nil])
|
||||||
|
(rf/dispatch [:accept-all-activity-center-notifications-from-chat chat-id])))
|
||||||
|
|
||||||
|
(defn truncate-literal [literal]
|
||||||
|
(when literal
|
||||||
|
(let [size (min max-subheader-length (.-length literal))]
|
||||||
|
{:components (.substring literal 0 size)
|
||||||
|
:length size})))
|
||||||
|
|
||||||
|
(defn add-parsed-to-subheader [acc {:keys [type destination literal children]}]
|
||||||
|
(let [result (case type
|
||||||
|
"paragraph"
|
||||||
|
(reduce
|
||||||
|
(fn [{:keys [_ length] :as acc-paragraph} parsed-child]
|
||||||
|
(if (>= length max-subheader-length)
|
||||||
|
(reduced acc-paragraph)
|
||||||
|
(add-parsed-to-subheader acc-paragraph parsed-child)))
|
||||||
|
{:components [quo/text]
|
||||||
|
:length 0}
|
||||||
|
children)
|
||||||
|
|
||||||
|
"mention"
|
||||||
|
{:components [quo/text (rf/sub [:contacts/contact-name-by-identity literal])]
|
||||||
|
:length 4} ;; we can't predict name length so take the smallest possible
|
||||||
|
|
||||||
|
"status-tag"
|
||||||
|
(truncate-literal (str "#" literal))
|
||||||
|
|
||||||
|
"link"
|
||||||
|
(truncate-literal destination)
|
||||||
|
|
||||||
|
(truncate-literal literal))]
|
||||||
|
{:components (conj (:components acc) (:components result))
|
||||||
|
:length (+ (:length acc) (:length result))}))
|
||||||
|
|
||||||
|
(defn render-subheader
|
||||||
|
"Render the preview of a last message to a maximum of max-subheader-length characters"
|
||||||
|
[parsed-text]
|
||||||
|
(let [result
|
||||||
|
(reduce
|
||||||
|
(fn [{:keys [_ length] :as acc-text} new-text-chunk]
|
||||||
|
(if (>= length max-subheader-length)
|
||||||
|
(reduced acc-text)
|
||||||
|
(add-parsed-to-subheader acc-text new-text-chunk)))
|
||||||
|
{:components [quo/text {:size :paragraph-2
|
||||||
|
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)
|
||||||
|
:width "90%"}
|
||||||
|
:number-of-lines 1
|
||||||
|
:ellipsize-mode :tail
|
||||||
|
:accessibility-label :chat-message-text}]
|
||||||
|
:length 0}
|
||||||
|
parsed-text)]
|
||||||
|
(:components result)))
|
||||||
|
|
||||||
|
(defn verified-or-contact-icon [{:keys [ens-verified added?]}]
|
||||||
|
(if ens-verified
|
||||||
|
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
||||||
|
[quo/icon :i/verified {:no-color true
|
||||||
|
:size 12
|
||||||
|
:color (colors/theme-colors colors/success-50 colors/success-60)}]]
|
||||||
|
(when added?
|
||||||
|
[rn/view {:style {:margin-left 5 :margin-top 4}}
|
||||||
|
[quo/icon :i/contact {:no-color true
|
||||||
|
:size 12
|
||||||
|
:color (colors/theme-colors colors/primary-50 colors/primary-60)}]])))
|
||||||
|
|
||||||
|
(defn name-view [display-name contact timestamp]
|
||||||
|
[rn/view {:style {:flex-direction :row}}
|
||||||
|
[quo/text {:weight :semi-bold
|
||||||
|
:accessibility-label :chat-name-text}
|
||||||
|
display-name]
|
||||||
|
[verified-or-contact-icon contact]
|
||||||
|
[quo/text {:size :label
|
||||||
|
:style (style/timestamp)}
|
||||||
|
(time/to-short-str timestamp)]])
|
||||||
|
|
||||||
|
(defn avatar-view [group-chat color display-name photo-path]
|
||||||
|
(if group-chat
|
||||||
|
[quo/group-avatar {:color color
|
||||||
|
:size :medium}]
|
||||||
|
[quo/user-avatar {:full-name display-name
|
||||||
|
:profile-picture photo-path
|
||||||
|
:size :small}]))
|
||||||
|
|
||||||
|
(defn chat-list-item [item]
|
||||||
|
(let [{:keys [chat-id color group-chat last-message timestamp name unviewed-mentions-count
|
||||||
|
unviewed-messages-count]} item
|
||||||
|
display-name (if group-chat name (first (rf/sub [:contacts/contact-two-names-by-identity 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]))]
|
||||||
|
[rn/touchable-opacity (merge {:style style/container
|
||||||
|
:on-press (open-chat chat-id)
|
||||||
|
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
|
||||||
|
{:content (fn [] [actions/actions item false])}])})
|
||||||
|
[avatar-view group-chat color display-name photo-path]
|
||||||
|
[rn/view {:style {:margin-left 8}}
|
||||||
|
[name-view display-name contact timestamp]
|
||||||
|
(if (string/blank? (get-in last-message [:content :parsed-text]))
|
||||||
|
[quo/text {:size :paragraph-2
|
||||||
|
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||||
|
(get-in last-message [:content :text])]
|
||||||
|
[render-subheader (get-in last-message [:content :parsed-text])])]
|
||||||
|
(if (> unviewed-mentions-count 0)
|
||||||
|
[quo/info-count unviewed-mentions-count {:top 16}]
|
||||||
|
(when (> unviewed-messages-count 0)
|
||||||
|
[rn/view {:style (style/count-container)}]))]))
|
|
@ -0,0 +1,27 @@
|
||||||
|
(ns status-im2.contexts.chat.home.contact-request.style
|
||||||
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
|
(def contact-requests
|
||||||
|
{:flex-direction :row
|
||||||
|
:margin 8
|
||||||
|
:padding-horizontal 12
|
||||||
|
:padding-vertical 8
|
||||||
|
:align-items :center})
|
||||||
|
|
||||||
|
(defn contact-requests-icon []
|
||||||
|
{:justify-content :center
|
||||||
|
:align-items :center
|
||||||
|
:width 32
|
||||||
|
:height 32
|
||||||
|
:border-radius 16
|
||||||
|
:border-width 1
|
||||||
|
:border-color (colors/theme-colors colors/neutral-20 colors/neutral-80)})
|
||||||
|
|
||||||
|
(defn contact-requests-sheet []
|
||||||
|
{: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-bottom 24})
|
|
@ -0,0 +1,70 @@
|
||||||
|
(ns status-im2.contexts.chat.home.contact-request.view
|
||||||
|
(:require [react-native.core :as rn]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[i18n.i18n :as i18n]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[clojure.string :as string]
|
||||||
|
[quo2.foundations.colors :as colors]
|
||||||
|
[status-im2.contexts.chat.home.contact-request.style :as style]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
|
||||||
|
;; TODO move to status-im2
|
||||||
|
[status-im.ui2.screens.chat.components.received-cr-item :as received-cr-item]))
|
||||||
|
|
||||||
|
(defn contact-requests-sheet [received-requests]
|
||||||
|
(let [selected-requests-tab (reagent/atom :received)]
|
||||||
|
(fn []
|
||||||
|
(let [sent-requests []]
|
||||||
|
[rn/view {:style {:margin-left 20}}
|
||||||
|
[rn/touchable-opacity
|
||||||
|
{:on-press #(rf/dispatch [:bottom-sheet/hide])
|
||||||
|
:style (style/contact-requests-sheet)}
|
||||||
|
[quo/icon :i/close]]
|
||||||
|
[rn/text {:size :heading-1 :weight :semi-bold}
|
||||||
|
(i18n/label :t/pending-requests)]
|
||||||
|
[quo/tabs
|
||||||
|
{:style {:margin-top 12 :margin-bottom 20}
|
||||||
|
:size 32
|
||||||
|
:on-change #(reset! selected-requests-tab %)
|
||||||
|
:default-active :received
|
||||||
|
:data [{:id :received
|
||||||
|
:label (i18n/label :t/received)}
|
||||||
|
{:id :sent
|
||||||
|
:label (i18n/label :t/sent)}]}]
|
||||||
|
[rn/flat-list
|
||||||
|
{:key-fn :chat-id
|
||||||
|
:data (if (= @selected-requests-tab :received) received-requests sent-requests)
|
||||||
|
:render-fn received-cr-item/received-cr-item}]]))))
|
||||||
|
|
||||||
|
(defn get-display-name [{:keys [chat-id message]}]
|
||||||
|
(let [name (first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
|
||||||
|
no-ens-name (string/blank? (get-in message [:content :ens-name]))]
|
||||||
|
(if no-ens-name
|
||||||
|
(first (string/split name " "))
|
||||||
|
name)))
|
||||||
|
|
||||||
|
(defn requests-summary [requests]
|
||||||
|
(case (count requests)
|
||||||
|
1
|
||||||
|
(get-display-name (first requests))
|
||||||
|
2
|
||||||
|
(str (get-display-name (first requests)) " " (i18n/label :t/and) " " (get-display-name (second requests)))
|
||||||
|
(str (get-display-name (first requests)) ", " (get-display-name (second requests)) " "
|
||||||
|
(i18n/label :t/and) " " (- (count requests) 2) " " (i18n/label :t/more))))
|
||||||
|
|
||||||
|
(defn contact-requests [requests]
|
||||||
|
[rn/touchable-opacity
|
||||||
|
{:active-opacity 1
|
||||||
|
:on-press #(do
|
||||||
|
(rf/dispatch [:bottom-sheet/show-sheet
|
||||||
|
{:content (fn [] [contact-requests-sheet requests])}])
|
||||||
|
(rf/dispatch [:mark-all-activity-center-notifications-as-read]))
|
||||||
|
:style style/contact-requests}
|
||||||
|
[rn/view {:style (style/contact-requests-icon)}
|
||||||
|
[quo/icon :i/pending-user {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]
|
||||||
|
[rn/view {:style {:margin-left 8}}
|
||||||
|
[rn/text {:weight :semi-bold} (i18n/label :t/pending-requests)]
|
||||||
|
[rn/text {:size :paragraph-2
|
||||||
|
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
|
||||||
|
(requests-summary requests)]]
|
||||||
|
[quo/info-count (count requests)]])
|
|
@ -0,0 +1,94 @@
|
||||||
|
(ns status-im2.contexts.chat.home.view
|
||||||
|
(:require [re-frame.core :as re-frame]
|
||||||
|
[reagent.core :as reagent]
|
||||||
|
[i18n.i18n :as i18n]
|
||||||
|
[react-native.core :as rn]
|
||||||
|
[quo2.core :as quo]
|
||||||
|
[utils.re-frame :as rf]
|
||||||
|
[status-im2.common.home.view :as common.home]
|
||||||
|
[status-im2.contexts.chat.home.contact-request.view :as contact-request]
|
||||||
|
[status-im2.contexts.chat.home.chat-list-item.view :as chat-list-item]
|
||||||
|
[status-im2.common.contact-list-item.view :as contact-list-item]))
|
||||||
|
|
||||||
|
(defn get-item-layout [_ index]
|
||||||
|
#js {:length 64 :offset (* 64 index) :index index})
|
||||||
|
|
||||||
|
(defn filter-items-by-tab [tab items]
|
||||||
|
(if (= tab :groups)
|
||||||
|
(filter :group-chat items)
|
||||||
|
(filter :chat-id items)))
|
||||||
|
|
||||||
|
(defn welcome-blank-chats []
|
||||||
|
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
|
||||||
|
[quo/icon :i/placeholder]
|
||||||
|
[quo/text {:weight :semi-bold} (i18n/label :t/no-messages)]
|
||||||
|
[quo/text (i18n/label :t/blank-messages-text)]])
|
||||||
|
|
||||||
|
(defn chats [selected-tab]
|
||||||
|
(let [{:keys [items search-filter]} (rf/sub [:home-items])
|
||||||
|
items (filter-items-by-tab selected-tab items)]
|
||||||
|
(if (and (empty? items)
|
||||||
|
(empty? search-filter))
|
||||||
|
[welcome-blank-chats]
|
||||||
|
[rn/flat-list
|
||||||
|
{:key-fn #(or (:chat-id %) (:public-key %) (:id %))
|
||||||
|
:get-item-layout get-item-layout
|
||||||
|
:on-end-reached #(re-frame/dispatch [:chat.ui/show-more-chats])
|
||||||
|
:keyboard-should-persist-taps :always
|
||||||
|
:data items
|
||||||
|
:render-fn chat-list-item/chat-list-item}])))
|
||||||
|
|
||||||
|
(defn welcome-blank-contacts []
|
||||||
|
[rn/view {:style {:flex 1 :align-items :center :justify-content :center}}
|
||||||
|
[quo/icon :i/placeholder]
|
||||||
|
[quo/text {:weight :semi-bold} (i18n/label :t/no-contacts)]
|
||||||
|
[quo/text (i18n/label :t/blank-contacts-text)]])
|
||||||
|
|
||||||
|
(defn contacts-section-header [{:keys [title]}]
|
||||||
|
[quo/divider-label {:label title}])
|
||||||
|
|
||||||
|
(defn contacts [contact-requests]
|
||||||
|
(let [items (rf/sub [:contacts/active-sections])]
|
||||||
|
(if (empty? items)
|
||||||
|
[welcome-blank-contacts]
|
||||||
|
[:<>
|
||||||
|
(when (pos? (count contact-requests))
|
||||||
|
[contact-request/contact-requests contact-requests])
|
||||||
|
[rn/section-list
|
||||||
|
{:key-fn :title
|
||||||
|
:sticky-section-headers-enabled false
|
||||||
|
:sections items
|
||||||
|
:render-section-header-fn contacts-section-header
|
||||||
|
:render-fn contact-list-item/contact-item}]])))
|
||||||
|
|
||||||
|
(defn tabs []
|
||||||
|
(let [selected-tab (reagent/atom :recent)]
|
||||||
|
(fn []
|
||||||
|
(let [contact-requests (rf/sub [:activity.center/notifications-contact-requests])]
|
||||||
|
[:<>
|
||||||
|
[quo/discover-card {:title (i18n/label :t/invite-friends-to-status)
|
||||||
|
:description (i18n/label :t/share-invite-link)}]
|
||||||
|
[quo/tabs {:style {:margin-left 20
|
||||||
|
:margin-bottom 20
|
||||||
|
:margin-top 24}
|
||||||
|
:size 32
|
||||||
|
:on-change #(reset! selected-tab %)
|
||||||
|
:default-active @selected-tab
|
||||||
|
:data [{:id :recent
|
||||||
|
:label (i18n/label :t/recent)}
|
||||||
|
{:id :groups
|
||||||
|
:label (i18n/label :t/groups)}
|
||||||
|
{:id :contacts
|
||||||
|
:label (i18n/label :t/contacts)
|
||||||
|
:notification-dot? (pos? (count contact-requests))}]}]
|
||||||
|
(if (= @selected-tab :contacts)
|
||||||
|
[contacts contact-requests]
|
||||||
|
[chats @selected-tab])]))))
|
||||||
|
|
||||||
|
(defn home []
|
||||||
|
[:<>
|
||||||
|
[common.home/top-nav {:type :default}]
|
||||||
|
[common.home/title-column {:label (i18n/label :t/messages)
|
||||||
|
:handler #(rf/dispatch [:bottom-sheet/show-sheet :add-new {}])
|
||||||
|
:accessibility-label :new-chat-button}]
|
||||||
|
[tabs]])
|
|
@ -1,29 +1,12 @@
|
||||||
(ns status-im2.contexts.communities.home.view
|
(ns status-im2.contexts.communities.home.view
|
||||||
(:require [re-frame.core :as re-frame]
|
(:require [reagent.core :as reagent]
|
||||||
[reagent.core :as reagent]
|
|
||||||
[react-native.core :as rn]
|
[react-native.core :as rn]
|
||||||
[react-native.safe-area :as safe-area]
|
|
||||||
[utils.re-frame :as rf]
|
[utils.re-frame :as rf]
|
||||||
[i18n.i18n :as i18n]
|
[i18n.i18n :as i18n]
|
||||||
[quo2.core :as quo]
|
[quo2.core :as quo]
|
||||||
[quo2.foundations.colors :as colors]
|
|
||||||
[quo2.components.community.discover-card :as discover-card]
|
[quo2.components.community.discover-card :as discover-card]
|
||||||
[quo2.components.navigation.top-nav :as topnav]
|
|
||||||
[status-im2.setup.config :as config]
|
|
||||||
[status-im2.common.plus-button.view :as components.plus-button]
|
|
||||||
[status-im2.contexts.communities.home.actions.view :as home.actions]
|
[status-im2.contexts.communities.home.actions.view :as home.actions]
|
||||||
[status-im2.contexts.communities.home.style :as style]))
|
[status-im2.common.home.view :as common.home]))
|
||||||
|
|
||||||
(defn navigate-to-activity-center []
|
|
||||||
(rf/dispatch [:mark-all-activity-center-notifications-as-read])
|
|
||||||
(if config/new-activity-center-enabled?
|
|
||||||
(rf/dispatch [:activity-center/open])
|
|
||||||
(rf/dispatch [:navigate-to :notifications-center])))
|
|
||||||
|
|
||||||
(defn plus-button []
|
|
||||||
[components.plus-button/plus-button
|
|
||||||
{:on-press #(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}])
|
|
||||||
:accessibility-label :new-chat-button}])
|
|
||||||
|
|
||||||
(defn render-fn [id]
|
(defn render-fn [id]
|
||||||
(let [community-item (rf/sub [:communities/home-item id])]
|
(let [community-item (rf/sub [:communities/home-item id])]
|
||||||
|
@ -78,29 +61,17 @@
|
||||||
:opened
|
:opened
|
||||||
[communities-list communities])]))
|
[communities-list communities])]))
|
||||||
|
|
||||||
(defn title-column []
|
|
||||||
[rn/view style/title-column
|
|
||||||
[rn/view {:flex 1}
|
|
||||||
[quo/text style/title-column-text
|
|
||||||
(i18n/label :t/communities)]]
|
|
||||||
[plus-button]])
|
|
||||||
|
|
||||||
(defn home []
|
(defn home []
|
||||||
[safe-area/consumer
|
(let [selected-tab (reagent/atom :joined)]
|
||||||
(fn [insets]
|
(fn []
|
||||||
(let [selected-tab (reagent/atom :joined)]
|
[:<>
|
||||||
(fn []
|
[common.home/top-nav {:type :default :hide-search true}]
|
||||||
[rn/view {:style {:flex 1
|
[common.home/title-column {:label (i18n/label :t/communities)
|
||||||
:padding-top (:top insets)
|
:handler #(rf/dispatch [:bottom-sheet/show-sheet :add-new {}])
|
||||||
:background-color (colors/theme-colors
|
:accessibility-label :new-chat-button}]
|
||||||
colors/neutral-5
|
[discover-card/discover-card {:on-press #(rf/dispatch [:navigate-to :discover-communities])
|
||||||
colors/neutral-95)}}
|
:title (i18n/label :t/discover)
|
||||||
[topnav/top-nav {:type :default
|
:description (i18n/label :t/whats-trending)
|
||||||
:open-activity-center navigate-to-activity-center}]
|
:accessibility-label :communities-home-discover-card}]
|
||||||
[title-column]
|
[home-community-segments selected-tab]
|
||||||
[discover-card/discover-card {:on-press #(rf/dispatch [:navigate-to :discover-communities])
|
[segments-community-lists selected-tab]])))
|
||||||
:title (i18n/label :t/discover)
|
|
||||||
:description (i18n/label :t/whats-trending)
|
|
||||||
:accessibility-label :communities-home-discover-card}]
|
|
||||||
[home-community-segments selected-tab]
|
|
||||||
[segments-community-lists selected-tab]])))])
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
(ns status-im2.contexts.communities.overview.style
|
(ns status-im2.contexts.communities.overview.style
|
||||||
(:require [quo2.foundations.colors :as colors]))
|
(:require [quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def container1
|
(defn container1 []
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:height 20
|
:height 20
|
||||||
:border-radius 16
|
:border-radius 16
|
||||||
:background-color (colors/theme-colors colors/white colors/neutral-90)})
|
:background-color (colors/theme-colors colors/white colors/neutral-90)})
|
||||||
|
|
||||||
(def container2
|
(defn container2 []
|
||||||
{:border-radius 40
|
{:border-radius 40
|
||||||
:border-width 1
|
:border-width 1
|
||||||
:border-color colors/white
|
:border-color colors/white
|
||||||
|
|
|
@ -94,9 +94,9 @@
|
||||||
:left-section {:icon :i/close
|
:left-section {:icon :i/close
|
||||||
:icon-background-color icon-color
|
:icon-background-color icon-color
|
||||||
:on-press #(rf/dispatch [:navigate-back])}}]]]
|
:on-press #(rf/dispatch [:navigate-back])}}]]]
|
||||||
[rn/view style/container1
|
[rn/view (style/container1)
|
||||||
[rn/view {:padding-horizontal 20}
|
[rn/view {:padding-horizontal 20}
|
||||||
[rn/view style/container2
|
[rn/view (style/container2)
|
||||||
[communities.icon/community-icon-redesign community 80]]
|
[communities.icon/community-icon-redesign community 80]]
|
||||||
(when (and (not joined)
|
(when (and (not joined)
|
||||||
(= status :gated))
|
(= status :gated))
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
(:require [react-native.core :as rn]
|
(:require [react-native.core :as rn]
|
||||||
[status-im2.contexts.quo-preview.preview :as preview]
|
[status-im2.contexts.quo-preview.preview :as preview]
|
||||||
[reagent.core :as reagent]
|
[reagent.core :as reagent]
|
||||||
[quo2.components.navigation.top-nav :as quo2]
|
[status-im2.common.home.view :as home.view]
|
||||||
[quo2.foundations.colors :as colors]))
|
[quo2.foundations.colors :as colors]))
|
||||||
|
|
||||||
(def descriptor [{:label "Type"
|
(def descriptor [{:label "Type"
|
||||||
|
@ -40,7 +40,7 @@
|
||||||
[rn/view {:padding-vertical 60
|
[rn/view {:padding-vertical 60
|
||||||
:flex-direction :row
|
:flex-direction :row
|
||||||
:align-items :center}
|
:align-items :center}
|
||||||
[quo2/top-nav @state (:value @state)]]]])))
|
[home.view/top-nav @state (:value @state)]]]])))
|
||||||
|
|
||||||
(defn preview-top-nav []
|
(defn preview-top-nav []
|
||||||
[rn/view {:background-color (colors/theme-colors colors/white colors/neutral-95)
|
[rn/view {:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
(ns status-im2.contexts.shell.home-stack
|
(ns status-im2.contexts.shell.home-stack
|
||||||
(:require [react-native.reanimated :as reanimated]
|
(:require [react-native.reanimated :as reanimated]
|
||||||
|
[react-native.core :as rn]
|
||||||
[status-im2.contexts.shell.style :as styles]
|
[status-im2.contexts.shell.style :as styles]
|
||||||
[status-im2.contexts.shell.constants :as constants]
|
[status-im2.contexts.shell.constants :as constants]
|
||||||
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
|
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
|
||||||
[status-im2.contexts.communities.home.view :as communities]
|
[status-im2.contexts.communities.home.view :as communities]
|
||||||
|
[status-im2.contexts.chat.home.view :as chat]
|
||||||
|
|
||||||
;; TODO move to status-im2
|
;; TODO move to status-im2
|
||||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||||
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
[status-im.ui.screens.wallet.accounts.views :as wallet.accounts]
|
||||||
[status-im.ui2.screens.chat.home :as chat.home]))
|
[react-native.safe-area :as safe-area]))
|
||||||
|
|
||||||
(defn load-stack? [stack-id]
|
(defn load-stack? [stack-id]
|
||||||
(case stack-id
|
(case stack-id
|
||||||
|
@ -33,23 +35,26 @@
|
||||||
:accessibility-label stack-id})}
|
:accessibility-label stack-id})}
|
||||||
(case stack-id
|
(case stack-id
|
||||||
:communities-stack [communities/home]
|
:communities-stack [communities/home]
|
||||||
:chats-stack [chat.home/home]
|
:chats-stack [chat/home]
|
||||||
:wallet-stack [wallet.accounts/accounts-overview]
|
:wallet-stack [wallet.accounts/accounts-overview]
|
||||||
:browser-stack [profile.user/my-profile])])]))
|
:browser-stack [profile.user/my-profile])])]))
|
||||||
|
|
||||||
(defn home-stack [shared-values]
|
(defn home-stack [shared-values]
|
||||||
[:f>
|
[safe-area/consumer
|
||||||
(fn []
|
(fn [insets]
|
||||||
(let [home-stack-original-style (styles/home-stack)
|
[:f>
|
||||||
home-stack-animated-style (reanimated/apply-animations-to-style
|
(fn []
|
||||||
{:top (:home-stack-top shared-values)
|
(let [home-stack-original-style (styles/home-stack)
|
||||||
:left (:home-stack-left shared-values)
|
home-stack-animated-style (reanimated/apply-animations-to-style
|
||||||
:opacity (:home-stack-opacity shared-values)
|
{:top (:home-stack-top shared-values)
|
||||||
:pointer-events (:home-stack-pointer shared-values)
|
:left (:home-stack-left shared-values)
|
||||||
:transform [{:scale (:home-stack-scale shared-values)}]}
|
:opacity (:home-stack-opacity shared-values)
|
||||||
home-stack-original-style)]
|
:pointer-events (:home-stack-pointer shared-values)
|
||||||
[reanimated/view {:style home-stack-animated-style}
|
:transform [{:scale (:home-stack-scale shared-values)}]}
|
||||||
[stack-view :communities-stack shared-values]
|
home-stack-original-style)]
|
||||||
[stack-view :chats-stack shared-values]
|
[reanimated/view {:style home-stack-animated-style}
|
||||||
[stack-view :browser-stack shared-values]
|
[rn/view {:margin-top (:top insets) :flex 1}
|
||||||
[stack-view :wallet-stack shared-values]]))])
|
[stack-view :communities-stack shared-values]
|
||||||
|
[stack-view :chats-stack shared-values]
|
||||||
|
[stack-view :browser-stack shared-values]
|
||||||
|
[stack-view :wallet-stack shared-values]]]))])])
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
[status-im2.contexts.shell.constants :as constants]
|
[status-im2.contexts.shell.constants :as constants]
|
||||||
[status-im2.contexts.shell.animation :as animation]
|
[status-im2.contexts.shell.animation :as animation]
|
||||||
[status-im2.contexts.shell.home-stack :as home-stack]
|
[status-im2.contexts.shell.home-stack :as home-stack]
|
||||||
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]))
|
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
|
||||||
|
[status-im2.common.home.view :as common.home]))
|
||||||
|
|
||||||
(defn placeholder []
|
(defn placeholder []
|
||||||
[rn/view {:style {:position :absolute
|
[rn/view {:style {:position :absolute
|
||||||
|
@ -44,8 +45,8 @@
|
||||||
:bottom -1
|
:bottom -1
|
||||||
:position :absolute
|
:position :absolute
|
||||||
:background-color colors/neutral-100}}
|
:background-color colors/neutral-100}}
|
||||||
[quo/top-nav {:type :shell
|
[common.home/top-nav {:type :shell
|
||||||
:style {:margin-top (:top insets)}}]
|
:style {:margin-top (:top insets)}}]
|
||||||
[placeholder]
|
[placeholder]
|
||||||
[rn/scroll-view {:style {:padding-horizontal 20
|
[rn/scroll-view {:style {:padding-horizontal 20
|
||||||
:flex-direction :row}}
|
:flex-direction :row}}
|
||||||
|
|
|
@ -5,8 +5,7 @@
|
||||||
[status-im2.contexts.shell.view :as shell]
|
[status-im2.contexts.shell.view :as shell]
|
||||||
[status-im2.contexts.quo-preview.main :as quo.preview]
|
[status-im2.contexts.quo-preview.main :as quo.preview]
|
||||||
|
|
||||||
;; TODO remove when not used anymore
|
;; TODO remove when not used anymore\
|
||||||
[status-im.ui2.screens.chat.home :as chat.home]
|
|
||||||
[status-im.ui2.screens.chat.view :as chat]
|
[status-im.ui2.screens.chat.view :as chat]
|
||||||
[status-im.ui.screens.screens :as old-screens]))
|
[status-im.ui.screens.screens :as old-screens]))
|
||||||
|
|
||||||
|
@ -20,9 +19,6 @@
|
||||||
:insets {:top false}
|
:insets {:top false}
|
||||||
:component shell/shell-stack}
|
:component shell/shell-stack}
|
||||||
|
|
||||||
{:name :home
|
|
||||||
:component chat.home/home}
|
|
||||||
|
|
||||||
{:name :chat
|
{:name :chat
|
||||||
:options {:topBar {:visible false}}
|
:options {:topBar {:visible false}}
|
||||||
:component chat/chat}
|
:component chat/chat}
|
||||||
|
|
|
@ -73,3 +73,13 @@
|
||||||
:timestamp (or (:timestamp %) (:timestamp (or (:message %) (:last-message %))))
|
:timestamp (or (:timestamp %) (:timestamp (or (:message %) (:last-message %))))
|
||||||
:contact (multiaccounts/contact-by-identity contacts (get-in % [:message :from])))
|
:contact (multiaccounts/contact-by-identity contacts (get-in % [:message :from])))
|
||||||
supported-notifications)))))
|
supported-notifications)))))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:activity.center/notifications-contact-requests
|
||||||
|
:<- [:activity.center/notifications-grouped-by-date]
|
||||||
|
(fn [notifications]
|
||||||
|
(reduce
|
||||||
|
(fn [acc {:keys [data]}]
|
||||||
|
(concat acc (filter #(= 1 (get-in % [:message :contact-request-state])) data)))
|
||||||
|
[]
|
||||||
|
notifications)))
|
||||||
|
|
|
@ -68,6 +68,21 @@
|
||||||
(fn [contacts]
|
(fn [contacts]
|
||||||
(contact.db/get-active-contacts contacts)))
|
(contact.db/get-active-contacts contacts)))
|
||||||
|
|
||||||
|
(re-frame/reg-sub
|
||||||
|
:contacts/active-sections
|
||||||
|
:<- [:contacts/active]
|
||||||
|
(fn [contacts]
|
||||||
|
(-> (reduce
|
||||||
|
(fn [acc contact]
|
||||||
|
(let [first-char (first (:alias contact))]
|
||||||
|
(if (get acc first-char)
|
||||||
|
(update-in acc [first-char :data] #(conj % contact))
|
||||||
|
(assoc acc first-char {:title first-char :data [contact]}))))
|
||||||
|
{}
|
||||||
|
contacts)
|
||||||
|
sort
|
||||||
|
vals)))
|
||||||
|
|
||||||
(re-frame/reg-sub
|
(re-frame/reg-sub
|
||||||
:contacts/sorted-contacts
|
:contacts/sorted-contacts
|
||||||
:<- [:contacts/active]
|
:<- [:contacts/active]
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
(ns utils.address
|
||||||
|
;; TODO move to status-im2
|
||||||
|
(:require [status-im.ethereum.eip55 :as eip55]
|
||||||
|
[status-im.ethereum.core :as ethereum]))
|
||||||
|
|
||||||
|
(defn get-shortened-address
|
||||||
|
"Takes first and last 4 digits from address including leading 0x
|
||||||
|
and adds unicode ellipsis in between"
|
||||||
|
[address]
|
||||||
|
(when address
|
||||||
|
(str (subs address 0 6) "\u2026" (subs address (- (count address) 3) (count address)))))
|
||||||
|
|
||||||
|
(defn get-shortened-checksum-address [address]
|
||||||
|
(when address
|
||||||
|
(get-shortened-address (eip55/address->checksum (ethereum/normalized-hex address)))))
|
|
@ -1839,6 +1839,7 @@
|
||||||
"jump-to": "Jump to",
|
"jump-to": "Jump to",
|
||||||
"untrustworthy": "Untrustworthy",
|
"untrustworthy": "Untrustworthy",
|
||||||
"blank-messages-text": "Your messages will be here",
|
"blank-messages-text": "Your messages will be here",
|
||||||
|
"blank-contacts-text": "Your contacts will be here",
|
||||||
"groups": "Groups",
|
"groups": "Groups",
|
||||||
"shell-placeholder-title": "Your apps will run here",
|
"shell-placeholder-title": "Your apps will run here",
|
||||||
"no-pinned-messages-desc": "This chat doesn't have any pinned messages.",
|
"no-pinned-messages-desc": "This chat doesn't have any pinned messages.",
|
||||||
|
|
Loading…
Reference in New Issue