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,15 +12,7 @@
|
|||
|
||||
(def default-tab-size 32)
|
||||
|
||||
(defn tabs [{:keys [default-active on-change style]}]
|
||||
(let [active-tab-id (reagent/atom default-active)]
|
||||
(fn [{:keys [data size] :or {size default-tab-size}}]
|
||||
[rn/view (merge {:flex-direction :row} style)
|
||||
(doall
|
||||
(for [{:keys [label id new-info accessibility-label]} data]
|
||||
^{:key id}
|
||||
[rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}}
|
||||
(when new-info
|
||||
(defn indicator []
|
||||
[rn/view {:position :absolute
|
||||
:z-index 1
|
||||
:right -2
|
||||
|
@ -32,6 +24,17 @@
|
|||
:align-items :center
|
||||
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
|
||||
[notification-dot]])
|
||||
|
||||
(defn tabs [{:keys [default-active on-change style]}]
|
||||
(let [active-tab-id (reagent/atom default-active)]
|
||||
(fn [{:keys [data size] :or {size default-tab-size}}]
|
||||
[rn/view (merge {:flex-direction :row} style)
|
||||
(doall
|
||||
(for [{:keys [label id notification-dot? accessibility-label]} data]
|
||||
^{:key id}
|
||||
[rn/view {:style {:margin-right (if (= size default-tab-size) 12 8)}}
|
||||
(when notification-dot?
|
||||
[indicator])
|
||||
[tab/tab
|
||||
{:id id
|
||||
:size size
|
||||
|
|
|
@ -35,11 +35,11 @@
|
|||
quo2.components.tags.context-tags
|
||||
quo2.components.tabs.tabs
|
||||
quo2.components.tabs.account-selector
|
||||
quo2.components.navigation.top-nav
|
||||
quo2.components.navigation.floating-shell-button
|
||||
quo2.components.tags.status-tags
|
||||
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 dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
|
||||
|
@ -61,12 +61,11 @@
|
|||
(def tabs quo2.components.tabs.tabs/tabs)
|
||||
(def scrollable-tabs quo2.components.tabs.tabs/scrollable-tabs)
|
||||
(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 status-tag quo2.components.tags.status-tags/status-tag)
|
||||
(def page-nav quo2.components.navigation.page-nav/page-nav)
|
||||
(def disclaimer quo2.components.selectors.disclaimer/disclaimer)
|
||||
|
||||
(def checkbox quo2.components.selectors.selectors/checkbox)
|
||||
;;;; AVATAR
|
||||
(def account-avatar quo2.components.avatars.account-avatar/account-avatar)
|
||||
(def channel-avatar quo2.components.avatars.channel-avatar/channel-avatar)
|
||||
|
|
|
@ -392,6 +392,7 @@
|
|||
(get-node-config)
|
||||
(communities/fetch)
|
||||
(logging/set-log-level (:log-level multiaccount))
|
||||
(notifications-center/get-activity-center-notifications)
|
||||
(notifications-center/get-activity-center-notifications-count))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
|
|
|
@ -17,8 +17,7 @@
|
|||
[quo2.components.markdown.text :as quo2.text]
|
||||
[quo2.components.tabs.tabs :as quo2.tabs]
|
||||
[status-im.ui.screens.wallet.accounts.common :as common]
|
||||
[status-im.ui.screens.wallet.account.views :as account.views]
|
||||
[quo.components.safe-area :as safe-area])
|
||||
[status-im.ui.screens.wallet.account.views :as account.views])
|
||||
(:require-macros [status-im.utils.views :as views]))
|
||||
|
||||
(views/defview account-card [{:keys [name color address type wallet] :as account} keycard? card-width]
|
||||
|
@ -266,10 +265,7 @@
|
|||
;mainnet? @(re-frame/subscribe [:mainnet?])
|
||||
selected-account-atom (reagent/atom nil)]
|
||||
(fn []
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
[react/view {:style {:flex 1
|
||||
:padding-top (:top insets)
|
||||
:background-color (quo2.colors/theme-colors quo2.colors/neutral-5 quo2.colors/neutral-95)}}
|
||||
[react/view {:padding-horizontal 20}
|
||||
[react/view {:flex-direction :row :height 56 :align-items :center :justify-content :flex-end}
|
||||
|
@ -291,7 +287,7 @@
|
|||
:i/placeholder]]
|
||||
[total-value]
|
||||
[accounts selected-account-atom]]
|
||||
[account.views/account-new @selected-account-atom]])])))
|
||||
[account.views/account-new @selected-account-atom]])))
|
||||
|
||||
(defn accounts-overview-old []
|
||||
(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]
|
||||
[utils.re-frame :as rf]
|
||||
[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 []
|
||||
[quo2/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:style {:margin-left 20}
|
||||
:accessibility-label :back-button
|
||||
:on-press #(rf/dispatch [:navigate-back])}
|
||||
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
||||
:on-press #(rf/dispatch [:navigate-back])
|
||||
:icon true}
|
||||
:i/arrow-left])
|
||||
|
||||
(defn options-button []
|
||||
[quo2/button {:type :grey
|
||||
:size 32
|
||||
:width 32
|
||||
:style {:margin-right 20}
|
||||
:accessibility-label :options-button}
|
||||
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
|
||||
:accessibility-label :options-button
|
||||
:icon true}
|
||||
:i/options])
|
||||
|
||||
(defn count-container [count]
|
||||
[rn/view {:style (style/count-container)}
|
||||
|
|
|
@ -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]
|
||||
[quo2.components.icon :as icons]
|
||||
[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.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]]))
|
||||
|
||||
(defview mention-element [from]
|
||||
|
@ -286,7 +286,7 @@
|
|||
:number-of-lines 1
|
||||
:style {:width "45%"}}
|
||||
display-name]
|
||||
[message-home-item/verified-or-contact-icon contact]
|
||||
[home.chat-list-item/verified-or-contact-icon contact]
|
||||
(when show-key?
|
||||
(let [props {:size :label
|
||||
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}]
|
||||
|
@ -329,12 +329,13 @@
|
|||
:pointer-events :box-none}
|
||||
[rn/view {:style {:width 40}}
|
||||
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:chat.ui/show-profile from])}
|
||||
[user-avatar/user-avatar {:full-name display-name
|
||||
:profile-picture photo-path
|
||||
:status-indicator? true
|
||||
:online? true
|
||||
:size :small
|
||||
:ring? false}])]
|
||||
:ring? false}]])]
|
||||
[rn/view {:style (style/message-author-wrapper)}
|
||||
(when (or (and (seq response-to) (:quoted-message message)) last-in-group? pinned)
|
||||
[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
|
||||
(clear-timeout id)))))
|
||||
|
||||
;;TODO (14/11/22 flexsurfer) haven't moved yet
|
||||
(defn get-shortened-address
|
||||
"Takes first and last 4 digits from address including leading 0x
|
||||
and adds unicode ellipsis in between"
|
||||
|
@ -101,6 +100,7 @@
|
|||
(when 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]
|
||||
(let [decimal-part (get (string/split (str amount) ".") 1)]
|
||||
(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]))
|
||||
|
||||
(defn context-container []
|
||||
|
@ -12,7 +12,7 @@
|
|||
:margin-left -4
|
||||
:margin-bottom 16})
|
||||
|
||||
(defn buttons-container []
|
||||
(def buttons-container
|
||||
{:flex-direction :row
|
||||
:justify-content :space-between
|
||||
: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
|
||||
(:require
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.chat.models.pin-message :as models.pin-message]
|
||||
[status-im.i18n.i18n :as i18n]
|
||||
(ns status-im2.common.home.actions.view
|
||||
(:require [i18n.i18n :as i18n]
|
||||
[utils.re-frame :as rf]
|
||||
[status-im.ui2.screens.common.core :as common]
|
||||
[quo2.components.drawers.action-drawers :as drawer]
|
||||
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
|
||||
|
||||
;;TODO move to status-im2
|
||||
[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?]}]
|
||||
{:pre [(keyword? icon)
|
||||
|
@ -45,7 +46,8 @@
|
|||
(defn clear-history-action [{:keys [chat-id] :as item}]
|
||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
(common/alert {:title (i18n/label :t/clear-history?)
|
||||
(confirmation-drawer/confirmation-drawer
|
||||
{:title (i18n/label :t/clear-history?)
|
||||
:description (i18n/label :t/clear-history-confirmation-content)
|
||||
:context item
|
||||
:button-text (i18n/label :t/clear-history)
|
||||
|
@ -54,7 +56,8 @@
|
|||
(defn delete-chat-action [{:keys [chat-id] :as item}]
|
||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
(common/alert {:title (i18n/label :t/delete-chat?)
|
||||
(confirmation-drawer/confirmation-drawer
|
||||
{:title (i18n/label :t/delete-chat?)
|
||||
:description (i18n/label :t/delete-chat-confirmation)
|
||||
:context item
|
||||
:button-text (i18n/label :t/delete-chat)
|
||||
|
@ -63,7 +66,8 @@
|
|||
(defn leave-group-action [{:keys [chat-id] :as item}]
|
||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn []
|
||||
(common/alert {:title (i18n/label :t/leave-group?)
|
||||
(confirmation-drawer/confirmation-drawer
|
||||
{:title (i18n/label :t/leave-group?)
|
||||
:description (i18n/label :t/leave-chat-confirmation)
|
||||
:context item
|
||||
:button-text (i18n/label :t/leave-group)
|
||||
|
@ -71,7 +75,8 @@
|
|||
|
||||
(defn block-user-action [{:keys [public-key] :as item}]
|
||||
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
|
||||
{:content (fn [] (common/alert {:title (i18n/label :t/block-user?)
|
||||
{:content (fn [] (confirmation-drawer/confirmation-drawer
|
||||
{:title (i18n/label :t/block-user?)
|
||||
:description (i18n/label :t/block-contact-details)
|
||||
:context item
|
||||
:button-text (i18n/label :t/block-user)
|
||||
|
@ -330,4 +335,3 @@
|
|||
constants/private-group-chat-type
|
||||
[private-group-chat-actions item inside-chat?]
|
||||
[contact-actions item]))
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
(ns status-im2.contexts.communities.home.style)
|
||||
(ns status-im2.common.home.style)
|
||||
|
||||
(def title-column
|
||||
{: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
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
(:require [reagent.core :as reagent]
|
||||
[react-native.core :as rn]
|
||||
[react-native.safe-area :as safe-area]
|
||||
[utils.re-frame :as rf]
|
||||
[i18n.i18n :as i18n]
|
||||
[quo2.core :as quo]
|
||||
[quo2.foundations.colors :as colors]
|
||||
[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.style :as style]))
|
||||
|
||||
(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}])
|
||||
[status-im2.common.home.view :as common.home]))
|
||||
|
||||
(defn render-fn [id]
|
||||
(let [community-item (rf/sub [:communities/home-item id])]
|
||||
|
@ -78,29 +61,17 @@
|
|||
:opened
|
||||
[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 []
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
(let [selected-tab (reagent/atom :joined)]
|
||||
(fn []
|
||||
[rn/view {:style {:flex 1
|
||||
:padding-top (:top insets)
|
||||
:background-color (colors/theme-colors
|
||||
colors/neutral-5
|
||||
colors/neutral-95)}}
|
||||
[topnav/top-nav {:type :default
|
||||
:open-activity-center navigate-to-activity-center}]
|
||||
[title-column]
|
||||
[:<>
|
||||
[common.home/top-nav {:type :default :hide-search true}]
|
||||
[common.home/title-column {:label (i18n/label :t/communities)
|
||||
:handler #(rf/dispatch [:bottom-sheet/show-sheet :add-new {}])
|
||||
:accessibility-label :new-chat-button}]
|
||||
[discover-card/discover-card {:on-press #(rf/dispatch [:navigate-to :discover-communities])
|
||||
: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]])))])
|
||||
[segments-community-lists selected-tab]])))
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
(ns status-im2.contexts.communities.overview.style
|
||||
(:require [quo2.foundations.colors :as colors]))
|
||||
|
||||
(def container1
|
||||
(defn container1 []
|
||||
{:flex 1
|
||||
:height 20
|
||||
:border-radius 16
|
||||
:background-color (colors/theme-colors colors/white colors/neutral-90)})
|
||||
|
||||
(def container2
|
||||
(defn container2 []
|
||||
{:border-radius 40
|
||||
:border-width 1
|
||||
:border-color colors/white
|
||||
|
|
|
@ -94,9 +94,9 @@
|
|||
:left-section {:icon :i/close
|
||||
:icon-background-color icon-color
|
||||
:on-press #(rf/dispatch [:navigate-back])}}]]]
|
||||
[rn/view style/container1
|
||||
[rn/view (style/container1)
|
||||
[rn/view {:padding-horizontal 20}
|
||||
[rn/view style/container2
|
||||
[rn/view (style/container2)
|
||||
[communities.icon/community-icon-redesign community 80]]
|
||||
(when (and (not joined)
|
||||
(= status :gated))
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
(:require [react-native.core :as rn]
|
||||
[status-im2.contexts.quo-preview.preview :as preview]
|
||||
[reagent.core :as reagent]
|
||||
[quo2.components.navigation.top-nav :as quo2]
|
||||
[status-im2.common.home.view :as home.view]
|
||||
[quo2.foundations.colors :as colors]))
|
||||
|
||||
(def descriptor [{:label "Type"
|
||||
|
@ -40,7 +40,7 @@
|
|||
[rn/view {:padding-vertical 60
|
||||
:flex-direction :row
|
||||
:align-items :center}
|
||||
[quo2/top-nav @state (:value @state)]]]])))
|
||||
[home.view/top-nav @state (:value @state)]]]])))
|
||||
|
||||
(defn preview-top-nav []
|
||||
[rn/view {:background-color (colors/theme-colors colors/white colors/neutral-95)
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
(ns status-im2.contexts.shell.home-stack
|
||||
(:require [react-native.reanimated :as reanimated]
|
||||
[react-native.core :as rn]
|
||||
[status-im2.contexts.shell.style :as styles]
|
||||
[status-im2.contexts.shell.constants :as constants]
|
||||
[status-im2.contexts.shell.bottom-tabs :as bottom-tabs]
|
||||
[status-im2.contexts.communities.home.view :as communities]
|
||||
[status-im2.contexts.chat.home.view :as chat]
|
||||
|
||||
;; TODO move to status-im2
|
||||
[status-im.ui.screens.profile.user.views :as profile.user]
|
||||
[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]
|
||||
(case stack-id
|
||||
|
@ -33,11 +35,13 @@
|
|||
:accessibility-label stack-id})}
|
||||
(case stack-id
|
||||
:communities-stack [communities/home]
|
||||
:chats-stack [chat.home/home]
|
||||
:chats-stack [chat/home]
|
||||
:wallet-stack [wallet.accounts/accounts-overview]
|
||||
:browser-stack [profile.user/my-profile])])]))
|
||||
|
||||
(defn home-stack [shared-values]
|
||||
[safe-area/consumer
|
||||
(fn [insets]
|
||||
[:f>
|
||||
(fn []
|
||||
(let [home-stack-original-style (styles/home-stack)
|
||||
|
@ -49,7 +53,8 @@
|
|||
:transform [{:scale (:home-stack-scale shared-values)}]}
|
||||
home-stack-original-style)]
|
||||
[reanimated/view {:style home-stack-animated-style}
|
||||
[rn/view {:margin-top (:top insets) :flex 1}
|
||||
[stack-view :communities-stack shared-values]
|
||||
[stack-view :chats-stack shared-values]
|
||||
[stack-view :browser-stack shared-values]
|
||||
[stack-view :wallet-stack shared-values]]))])
|
||||
[stack-view :wallet-stack shared-values]]]))])])
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
[status-im2.contexts.shell.constants :as constants]
|
||||
[status-im2.contexts.shell.animation :as animation]
|
||||
[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 []
|
||||
[rn/view {:style {:position :absolute
|
||||
|
@ -44,7 +45,7 @@
|
|||
:bottom -1
|
||||
:position :absolute
|
||||
:background-color colors/neutral-100}}
|
||||
[quo/top-nav {:type :shell
|
||||
[common.home/top-nav {:type :shell
|
||||
:style {:margin-top (:top insets)}}]
|
||||
[placeholder]
|
||||
[rn/scroll-view {:style {:padding-horizontal 20
|
||||
|
|
|
@ -5,8 +5,7 @@
|
|||
[status-im2.contexts.shell.view :as shell]
|
||||
[status-im2.contexts.quo-preview.main :as quo.preview]
|
||||
|
||||
;; TODO remove when not used anymore
|
||||
[status-im.ui2.screens.chat.home :as chat.home]
|
||||
;; TODO remove when not used anymore\
|
||||
[status-im.ui2.screens.chat.view :as chat]
|
||||
[status-im.ui.screens.screens :as old-screens]))
|
||||
|
||||
|
@ -20,9 +19,6 @@
|
|||
:insets {:top false}
|
||||
:component shell/shell-stack}
|
||||
|
||||
{:name :home
|
||||
:component chat.home/home}
|
||||
|
||||
{:name :chat
|
||||
:options {:topBar {:visible false}}
|
||||
:component chat/chat}
|
||||
|
|
|
@ -73,3 +73,13 @@
|
|||
:timestamp (or (:timestamp %) (:timestamp (or (:message %) (:last-message %))))
|
||||
:contact (multiaccounts/contact-by-identity contacts (get-in % [:message :from])))
|
||||
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]
|
||||
(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
|
||||
:contacts/sorted-contacts
|
||||
:<- [: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",
|
||||
"untrustworthy": "Untrustworthy",
|
||||
"blank-messages-text": "Your messages will be here",
|
||||
"blank-contacts-text": "Your contacts will be here",
|
||||
"groups": "Groups",
|
||||
"shell-placeholder-title": "Your apps will run here",
|
||||
"no-pinned-messages-desc": "This chat doesn't have any pinned messages.",
|
||||
|
|
Loading…
Reference in New Issue