Compare commits

...
Author SHA1 Message Date
ibrahem 0f0ce0d7bd Fix close button not working 2022-11-25 22:06:02 +02:00
ibrahem bc51a59774 Hardcode height to fix modal going under keyboard 2022-11-25 22:03:48 +02:00
ibrahem 4639660943 clean 2022-11-21 15:19:05 +02:00
ibrahem b58e7d6fff Revert changes to quo 2022-11-21 15:18:28 +02:00
ibrahem 3b593bedac improvements 2022-11-20 20:55:05 +03:00
ibrkhalil 944cb6c822 Cleaning 2022-11-20 15:58:37 +02:00
ibrahem 8700886ae4 lint 2022-11-15 23:33:27 +03:00
ibrahem c5cc18e9e0 Match implementation to design 2022-11-15 23:27:30 +03:00
ibrahem 2b6f354fb6 Improvements 2022-11-15 23:27:29 +03:00
ibrahem 717a225fd4 New chat flow for private chats and group chats 2022-11-15 23:27:27 +03:00
18 changed files with 1170 additions and 90 deletions
+2 -1
View File
@@ -138,13 +138,14 @@
(fn [{:keys [left-accessories left-component border-bottom
right-accessories right-component insets get-layout
title subtitle title-component style title-align
background]
background header-style]
:or {title-align :center
border-bottom false}}]
(let [status-bar-height (get insets :top 0)
height (+ header-height status-bar-height)]
[reanimated/view {:style (header-wrapper-style {:height height
:background background
:header-style header-style
:border-bottom border-bottom})}
[rn/view {:pointer-events :box-none
:height status-bar-height}]
+15
View File
@@ -0,0 +1,15 @@
(ns quo2.components.list-items.index
(:require [quo.react-native :as rn]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]))
(defn index [{:keys [title]}]
[rn/view
[rn/view {:style {:border-top-width 1
:border-color (colors/theme-colors colors/neutral-10 colors/neutral-80)
:padding-vertical 8
:padding-horizontal 16}}
[text/text {:weight :medium
:size :paragraph-2
:secondary-color (colors/theme-colors colors/neutral-50 colors/neutral-40)}
title]]])
@@ -0,0 +1,276 @@
(ns quo2.components.list-items.list-item
(:require [quo.react-native :as rn]
[quo.platform :as platform]
[quo.haptic :as haptic]
[quo.gesture-handler :as gh]
[quo.design-system.spacing :as spacing]
[quo.design-system.colors :as quo.colors]
[quo.components.controls.view :as controls]
[quo.components.tooltip :as tooltip]
[quo2.components.markdown.text :as text]
[quo2.foundations.colors :as colors]
[quo2.components.icon :as quo2.icons]
[quo.components.animated.pressable :as animated]))
(defn themes [theme]
(case theme
:main {:icon-color (:icon-04 @quo.colors/theme)
:icon-bg-color (:interactive-02 @quo.colors/theme)
:active-background (:interactive-02 @quo.colors/theme)
:passive-background (:ui-background @quo.colors/theme)
:text-color (:text-01 @quo.colors/theme)}
:accent {:icon-color (:icon-04 @quo.colors/theme)
:icon-bg-color (:interactive-02 @quo.colors/theme)
:active-background (:interactive-02 @quo.colors/theme)
:passive-background (:ui-background @quo.colors/theme)
:text-color (:text-04 @quo.colors/theme)}
:negative {:icon-color (:negative-01 @quo.colors/theme)
:icon-bg-color (:negative-02 @quo.colors/theme)
:active-background (:negative-02 @quo.colors/theme)
:passive-background (:ui-background @quo.colors/theme)
:text-color (:negative-01 @quo.colors/theme)}
:positive {:icon-color (:positive-01 @quo.colors/theme)
:icon-bg-color (:positive-02 @quo.colors/theme)
:active-background (:positive-02 @quo.colors/theme)
:passive-background (:ui-background @quo.colors/theme)
:text-color (:positive-01 @quo.colors/theme)}
:disabled {:icon-color (:icon-02 @quo.colors/theme)
:icon-bg-color (:ui-01 @quo.colors/theme)
:active-background (:ui-01 @quo.colors/theme)
:passive-background (:ui-background @quo.colors/theme)
:text-color (:text-02 @quo.colors/theme)}))
(defn size->icon-size [size]
(case size
:small 36
40))
(defn size->container-size [size]
(case size
:small 52
64))
(defn size->single-title-size [size]
(case size
:small :paragraph-1
:paragraph-1))
(defn container [{:keys [size container-style container-padding-horizontal container-padding-vertical]} & children]
(into [rn/view {:style (merge (or container-padding-horizontal (:tiny spacing/padding-horizontal))
{:min-height (size->container-size size)
:padding-vertical (or container-padding-vertical 8)
:flex-direction :row
:align-items :center
:justify-content :space-between} container-style)}]
children))
(defn icon-column
[{:keys [icon icon-bg-color icon-color size icon-container-style]}]
(when icon
(let [icon-size (size->icon-size size)]
[rn/view {:style (or icon-container-style (:tiny spacing/padding-horizontal))}
(cond
(vector? icon)
icon
(keyword? icon)
[rn/view {:style {:width icon-size
:height icon-size
:align-items :center
:justify-content :center
:border-radius (/ icon-size 2)
:background-color icon-bg-color}}
(quo2.icons/icon icon {:color icon-color})])])))
(defn title-column
[{:keys [title text-color subtitle subtitle-max-lines subtitle-secondary
title-accessibility-label size text-size title-text-weight
right-side-present? title-column-style]}]
[rn/view {:style (or title-column-style
(merge (:tiny spacing/padding-horizontal)
;; make left-side title grow if nothing is present on right-side
(when-not right-side-present?
{:flex 1
:justify-content :center})))}
(cond
(and title subtitle)
[:<>
;; FIXME(Ferossgp): ReactNative 63 will support view inside text on andrid, remove thess if when migrating
(if (string? title)
[text/text {:weight (or title-text-weight :medium)
:style {:color text-color}
:accessibility-label title-accessibility-label
:ellipsize-mode :tail
:number-of-lines 1
:size text-size}
title]
title)
(if (string? subtitle-secondary)
[rn/view {:flex-direction :row}
[text/text {:style {:max-width "56.5%"}
:weight :regular
:color :secondary
:ellipsize-mode :tail
:secondary-color colors/neutral-50
:number-of-lines subtitle-max-lines
:size text-size}
subtitle]
[text/text {:style {:width "7%" :text-align :center}
:weight :regular
:color :secondary
:ellipsize-mode :middle
:secondary-color colors/neutral-50
:number-of-lines subtitle-max-lines
:size text-size}
"•"]
[text/text {:style {:max-width "36.5%"}
:weight :regular
:color :secondary
:ellipsize-mode :middle
:secondary-color colors/neutral-50
:number-of-lines subtitle-max-lines
:size text-size}
subtitle-secondary]]
(if (string? subtitle)
[text/text {:weight :regular
:color :secondary
:ellipsize-mode :tail
:secondary-color colors/neutral-50
:number-of-lines subtitle-max-lines
:size text-size}
subtitle]
subtitle))]
title
(if (string? title)
[text/text {:weight (or title-text-weight :regular)
:number-of-lines 1
:style {:color text-color}
:title-accessibility-label title-accessibility-label
:ellipsize-mode :tail
:size (or text-size (size->single-title-size size))}
title]
title))])
(defn left-side [props]
[rn/view {:style {:flex-direction :row
;; Occupy only content width, never grow, but shrink if need be
:flex-grow 0
:flex-shrink 1
:padding-right 16
:align-items (or (:left-side-alignment props) :center)}}
[icon-column props]
[title-column props]])
(defn right-side [{:keys [chevron active disabled accessory accessory-text accessory-style animated-accessory?]}]
(when (or chevron accessory)
[rn/view {:style (merge {:align-items :center
:justify-content :flex-end
:flex-direction :row
;; Grow to occupy full space, shrink when need be, but always maitaining 16px left gutter
:flex-grow 1
:flex-shrink 0
:margin-left 16
;; When the left-side leaves no room for right-side, the rendered element is pushed out. A flex-basis ensures that there is some room reserved.
;; The number 80px was determined by trial and error.
:flex-basis 80}
accessory-style)}
[rn/view {:style (:tiny spacing/padding-horizontal)}
(case accessory
:radio [controls/radio {:value active :disabled disabled}]
:checkbox [(if animated-accessory?
controls/animated-checkbox
controls/checkbox)
{:value active :disabled disabled}]
:switch [controls/switch {:value active :disabled disabled}]
:text [text/text {:color :secondary
:ellipsize-mode :middle
:number-of-lines 1}
accessory-text]
accessory)]
(when (and chevron platform/ios?)
[rn/view {:style {:padding-right (:tiny spacing/spacing)}}
(quo2.icons/icon :main-icons/next {:container-style {:opacity 0.4
:align-items :center
:justify-content :center}
:resize-mode :center
:color (:icon-02 @quo.colors/theme)})])]))
(defn list-item
[{:keys [theme accessory disabled subtitle-max-lines icon icon-container-style
left-side-alignment icon-color icon-bg-color title-column-style
title subtitle subtitle-secondary active on-press on-long-press chevron size text-size
accessory-text accessibility-label title-accessibility-label accessory-style
haptic-feedback text-color active-background passive-background haptic-type error animated animated-accessory? title-text-weight container-style
active-background-enabled background-color container-padding-horizontal container-padding-vertical]
:or {subtitle-max-lines 1
theme :main
haptic-feedback true
animated platform/ios?
active-background-enabled true
haptic-type :selection}}]
(let [theme (if disabled :disabled theme)
icon-color (or icon-color (:icon-color (themes theme)))
icon-bg-color (or icon-bg-color (:icon-bg-color (themes theme)))
optional-haptic (fn []
(when haptic-feedback
(haptic/trigger haptic-type)))
component (cond
(and (not on-press)
(not on-long-press))
rn/view
animated animated/pressable
:else gh/touchable-highlight)]
[rn/view {:background-color (cond (not= background-color nil)
background-color
(and (= accessory :radio) active)
active-background
:else
passive-background)}
[component
(merge {:type :list-item
:disabled disabled
:bg-color (when active-background-enabled active-background)
:accessibility-label accessibility-label}
(when on-press
{:on-press (fn []
(optional-haptic)
(on-press))})
(when on-long-press
{:on-long-press (fn []
(optional-haptic)
(on-long-press))}))
[container {:size size :container-style container-style :container-padding-vertical container-padding-vertical :container-padding-horizontal container-padding-horizontal}
[left-side {:icon-color icon-color
:text-color (if on-press
text-color
(:text-color (themes :main)))
:left-side-alignment left-side-alignment
:icon-bg-color icon-bg-color
:title-accessibility-label title-accessibility-label
:icon icon
:icon-container-style icon-container-style
:title title
:title-text-weight title-text-weight
:size size
:text-size text-size
:subtitle subtitle
:subtitle-max-lines subtitle-max-lines
:subtitle-secondary subtitle-secondary
:right-side-present? (or accessory chevron)
:title-column-style title-column-style}]
[right-side {:chevron chevron
:active active
:disabled disabled
:on-press on-press
:accessory-text accessory-text
:animated-accessory? animated-accessory?
:accessory-style accessory-style
:accessory accessory}]]]
(when error
[tooltip/tooltip (merge {:bottom-value 0}
(when accessibility-label
{:accessibility-label (str (name accessibility-label) "-error")}))
[text/text {:color :negative
:size :small}
error]])]))
+3 -3
View File
@@ -1,11 +1,10 @@
(ns quo2.components.markdown.text
(:require [react-native.core :as rn]
[quo2.theme :as theme]
[quo2.foundations.colors :as colors]
[quo2.foundations.typography :as typography]
[reagent.core :as reagent]))
(defn text-style [{:keys [size align weight style]}]
(defn text-style [{:keys [size align weight style secondary-color]}]
(merge (case (or weight :regular)
:regular typography/font-regular
:medium typography/font-medium
@@ -24,7 +23,8 @@
{:text-align (or align :auto)}
(if (:color style)
style
(assoc style :color (if (= (theme/get-theme) :dark) colors/white colors/neutral-100)))))
(assoc style :color (or secondary-color
(colors/theme-colors colors/neutral-100 colors/white))))))
(defn text []
(let [this (reagent/current-component)
@@ -0,0 +1,270 @@
(ns quo2.components.markdown.text-input
(:require [clojure.spec.alpha :as s]
[reagent.core :as reagent]
[oops.core :refer [ocall]]
[quo.react-native :as rn]
;; TODO(Ferossgp): Move icon component to lib
[status-im.ui.components.icons.icons :as icons]
[quo.components.tooltip :as tooltip]
[quo.platform :as platform]
[quo.design-system.typography :as typography]
[quo.design-system.spacing :as spacing]
[quo.design-system.colors :as colors]
[quo.components.text :as text]))
;; NOTE(Ferossgp): Refactor with hooks when available
;; We track all currently mounted text input refs
;; in a ref-to-defaultValue map
;; so that we can clear them (restore their default values)
;; when global react-navigation's onWillBlur event is invoked
(defonce text-input-refs (atom {}))
(s/def ::multiline boolean?)
(s/def ::secure-text-entry boolean?)
(s/def ::show-cancel boolean?)
(s/def ::label (s/nilable (s/or :string string? :component vector?)))
(s/def ::cancel-label (s/nilable string?))
(s/def ::default-value (s/nilable string?))
(s/def ::placeholder (s/nilable string?))
(s/def ::keyboard-type (s/nilable (s/or :string string? :keyword keyword?))) ; TODO: make set
(s/def ::accessibility-label (s/nilable (s/or :string string? :keyword keyword?)))
(s/def ::on-focus fn?)
(s/def ::on-blur fn?)
(s/def ::on-press fn?)
(s/def ::accessory (s/keys :opt-un [::on-press
::icon
::component]))
(s/def ::after (s/nilable ::accessory))
(s/def ::before (s/nilable ::accessory))
(s/def ::style (s/nilable map?))
(s/def ::input-style ::style)
(s/def ::container-style ::style)
(s/def ::text-input (s/keys :opt-un
[::label
::multiline
::error
::style
::input-style
::keyboard-type
::before
::after
::cancel-label
::on-focus
::on-blur
::container-style
::show-cancel
::accessibility-label
::bottom-value
::secure-text-entry]))
(defn check-spec [spec prop]
(if (s/valid? spec prop)
true
(do
(s/explain spec prop)
false)))
(def height 44) ; 22 line-height + 11*2 vertical padding
(def multiline-height 88) ; 3 * 22 three line-height + 11* vertical padding
(defn label-style []
{:margin-bottom (:tiny spacing/spacing)})
(defn text-input-row-style []
{:flex-direction :row
:align-items :center})
(defn text-input-view-style [style]
(merge {:border-radius 8
:flex-direction :row
:flex 1
:align-items :center
:background-color (:ui-01 @colors/theme)}
style))
(defn text-input-style [multiline input-style monospace before after]
(merge (if monospace
typography/monospace
typography/font-regular)
{:padding-top 11
:padding-bottom 11
:font-size 15
:margin 0
:text-align-vertical :center
:flex 1
:color (:text-01 @colors/theme)
:height height}
(when-not before
{:padding-left (:base spacing/spacing)})
(when-not after
{:padding-right (:base spacing/spacing)})
(when multiline
{:text-align-vertical :top
:line-height 22
:height multiline-height})
input-style))
(defn cancel-style []
{:margin-left (:tiny spacing/spacing)
:padding-left (:tiny spacing/spacing)
:justify-content :center
:align-self :stretch})
(defn accessory-style []
(merge (:base spacing/padding-horizontal)
{:flex 1
:justify-content :center}))
(defn accessory-element [{:keys [icon component icon-opts style accessibility-label on-press]}]
(let [el (if on-press
rn/touchable-opacity
rn/view)]
[el (merge {:style {:align-self :stretch}}
(when on-press
{:on-press on-press}))
[rn/view (merge {:style (merge (accessory-style)
style)}
(when accessibility-label
{:accessibility-label accessibility-label}))
(cond
icon
[icons/icon icon (merge {:color (:icon-01 @colors/theme)}
icon-opts)]
component
component
:else
nil)]]))
(defn text-input-raw []
(let [focused (reagent/atom nil)
visible (reagent/atom false)
ref (atom nil)
blur (fn []
(some-> @ref (ocall "blur")))]
(fn [{:keys [label multiline error style input-style keyboard-type before after
cancel-label on-focus on-blur show-cancel accessibility-label
bottom-value secure-text-entry container-style get-ref on-cancel
monospace auto-complete-type auto-correct]
:or {cancel-label "Cancel"}
:as props}]
{:pre [(check-spec ::text-input props)]}
(let [show-cancel (if (nil? show-cancel)
;; Enabled by default on iOs and disabled on Android
platform/ios?
show-cancel)
after (cond
(and secure-text-entry @visible)
{:icon :main-icons/hide
:on-press #(reset! visible false)}
(and secure-text-entry (not @visible))
{:icon :main-icons/show
:on-press #(reset! visible true)}
:else after)
secure (boolean (and secure-text-entry (not @visible))) ; must be a boolean to work on iOS
auto-complete (cond
(= keyboard-type :visible-password)
:off
secure-text-entry
:password
:else
auto-complete-type)
auto-correct (and (not= keyboard-type :visible-password) (not secure-text-entry) auto-correct)
on-cancel (fn []
(when on-cancel
(on-cancel))
(blur))
keyboard-type (cond
(and platform/ios? (= keyboard-type :visible-password))
:default
; the correct approach on Android would be keep secure-text-entry on set keyboard type
; to visible-password. But until https://github.com/facebook/react-native/issues/27946
; is solved that's the second best way.
(and platform/android? secure-text-entry)
:default
:else
keyboard-type)]
[rn/view {:style container-style}
(when label
[text/text {:style (label-style)}
label])
[rn/view {:style (text-input-row-style)}
[rn/view {:style (text-input-view-style style)
:important-for-accessibility (if secure-text-entry
:no-hide-descendants
:auto)}
(when before
[accessory-element before])
[rn/text-input
(merge {:style (text-input-style multiline input-style monospace before after)
:ref (fn [r]
(reset! ref r)
(when get-ref (get-ref r)))
:placeholder-text-color (:text-02 @colors/theme)
:underline-color-android :transparent
:auto-capitalize :none
:secure-text-entry secure
:auto-correct auto-correct
:auto-complete-type auto-complete
:on-focus (fn [evt]
(when on-focus (on-focus evt))
(when show-cancel
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets)))
(reset! focused true))
:on-blur (fn [evt]
(when on-blur (on-blur evt))
(when show-cancel
(rn/configure-next (:ease-in-ease-out rn/layout-animation-presets)))
(reset! focused false))
:keyboard-type keyboard-type}
(when (and platform/ios? (not after))
{:clear-button-mode :while-editing})
(dissoc props
:style :keyboard-type :on-focus :on-blur
:secure-text-entry :ref :get-ref :auto-correct :auto-complete-type))]
(when after
[accessory-element after])]
(when (and show-cancel
(not multiline)
@focused)
[rn/touchable-opacity {:style (cancel-style)
:on-press on-cancel}
[text/text {:color :link} cancel-label]])
(when error
[tooltip/tooltip (merge {:bottom-value (if bottom-value bottom-value 0)}
(when accessibility-label
{:accessibility-label (str (name accessibility-label) "-error")}))
[text/text {:color :negative
:align :center
:size :small}
error]])]]))))
;; TODO(Ferossgp): Refactor me when hooks available
(defn text-input [{:keys [preserve-input?]
:as props}]
(if preserve-input?
[text-input-raw props]
(let [id (random-uuid)]
(reagent/create-class
{:component-will-unmount
(fn []
(swap! text-input-refs dissoc id))
:reagent-render
(fn [{:keys [get-ref default-value]
:as props}]
[text-input-raw (merge props
{:get-ref (fn [r]
;; Store input and its defaultValue
;; one we receive a non-nil ref
(when r
(swap! text-input-refs assoc id {:ref r :value default-value}))
(when get-ref (get-ref r)))})])}))))
+5 -1
View File
@@ -33,7 +33,9 @@
quo2.components.notifications.notification-dot
quo2.components.tags.tags
quo2.components.tabs.tabs
quo2.components.tabs.account-selector))
quo2.components.tabs.account-selector
quo2.components.list-items.index
quo2.components.list-items.list-item))
(def button quo2.components.buttons.button/button)
(def dynamic-button quo2.components.buttons.dynamic-button/dynamic-button)
@@ -80,6 +82,8 @@
(def channel-list-item quo2.components.list-items.channel/list-item)
(def menu-item quo2.components.list-items.menu-item/menu-item)
(def preview-list quo2.components.list-items.preview-list/preview-list)
(def index quo2.components.list-items.index/index)
(def list-item quo2.components.list-items.list-item/list-item)
;;;; NOTIFICATIONS
(def activity-log quo2.components.notifications.activity-logs/activity-log)
+5
View File
@@ -91,6 +91,11 @@
(def white-opa-90 (alpha white 0.9))
(def white-opa-95 (alpha white 0.95))
;;;;Black
;;Solid
(def black "#000000")
;;;;Primary
;;Solid
+1 -1
View File
@@ -8,7 +8,7 @@
(defn default-navigation [modal? {:keys [on-press label icon]}]
(cond-> {:icon (if modal? :main-icons/close :main-icons/arrow-left)
:accessibility-label :back-button
:on-press #(re-frame/dispatch [:navigate-back])}
:on-press #(re-frame/dispatch [:bottom-sheet/hide :navigate-back])}
on-press
(assoc :on-press on-press)
@@ -27,6 +27,12 @@
(= view :add-new)
(merge home.sheet/add-new)
(= view :add-new-sheet-view)
(merge home.sheet/add-new-sheet)
(= view :start-a-new-chat)
(merge home.sheet/start-a-new-chat)
(= view :keycard.login/more)
(merge keycard/more-sheet)
+52 -14
View File
@@ -1,23 +1,26 @@
(ns status-im.ui.screens.home.sheet.views
(:require [re-frame.core :as re-frame]
[status-im.ui.components.react :as react]
[status-im.qr-scanner.core :as qr-scanner]
[quo.core :as quo]
(:require [quo.core :as quo]
[quo2.foundations.colors :as colors]
[status-im.utils.re-frame :as rf]
[status-im.i18n.i18n :as i18n]
[status-im.qr-scanner.core :as qr-scanner]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.react :as rn]
[status-im.ui2.screens.chat.components.new-chat :as new-chat-aio]
[status-im.utils.config :as config]
[status-im.ui.components.invite.views :as invite]))
[quo2.components.list-items.list-item :as quo2.list-item]))
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide])
(re-frame/dispatch event))
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(defn add-new-view []
[react/view
[react/view {:style {:flex-direction :row
:padding-left 16
:padding-right 8
:justify-content :space-between
:align-items :center}}
[rn/view
[rn/view {:style {:flex-direction :row
:padding-left 16
:padding-right 8
:justify-content :space-between
:align-items :center}}
[quo/text {:size :large
:weight :bold}
(i18n/label :t/open-home)]
@@ -47,7 +50,7 @@
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:on-press #(hide-sheet-and-dispatch [:open-modal :new-public-chat])}]
(when @(re-frame/subscribe [:communities/enabled?])
(when (rf/sub [:communities/enabled?])
[quo/list-item
{:theme :accent
:title (i18n/label :t/communities-alpha)
@@ -57,5 +60,40 @@
[invite/list-item
{:accessibility-label :chats-menu-invite-friends-button}]])
(defn add-new-sheet-view []
[rn/view
[quo2.list-item/list-item
{:theme :main
:title (i18n/label :t/new-chat)
:icon-bg-color :transparent
:icon-container-style {:padding-horizontal 0}
:container-padding-horizontal {:padding-horizontal 4}
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:accessibility-label :start-a-new-chat
:icon :i/new-message
:on-press #(hide-sheet-and-dispatch [:bottom-sheet/show-sheet :start-a-new-chat])}]
[quo2.list-item/list-item
{:theme :main
:title (i18n/label :t/add-a-contact)
:icon-bg-color :transparent
:icon-container-style {:padding-horizontal 0}
:container-padding-horizontal {:padding-horizontal 4}
:container-padding-vertical 12
:title-column-style {:margin-left 2}
:icon-color (colors/theme-colors colors/neutral-50 colors/neutral-40)
:accessibility-label :add-a-contact
:subtitle (i18n/label :t/enter-a-chat-key)
:icon :i/add-user
:on-press #(hide-sheet-and-dispatch [:open-modal :new-contact])}]])
(def add-new-sheet
{:content add-new-sheet-view})
(def add-new
{:content add-new-view})
(def start-a-new-chat
{:content (fn [] [new-chat-aio/contact-toggle-list])})
+12 -5
View File
@@ -115,7 +115,8 @@
[status-im.ui.screens.wallet.buy-crypto.views :as wallet.buy-crypto]
[status-im.ui.screens.wallet.recipient.views :as recipient]
[status-im.ui.screens.wallet.send.views :as wallet.send]
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]))
[status-im.ui.screens.wallet.manage-connections.views :as manage-all-connections]
[status-im.ui2.screens.chat.components.new-chat :as new-chat-aio]))
(defn right-button-options [id icon]
{:id id
@@ -595,11 +596,17 @@
:options {:topBar {:visible false}}
:component contact/nickname}
;[Group chat] Edit group chat name
{:name :edit-group-chat-name
{:name :new-chat-aio
:on-focus [::new-chat.events/new-chat-focus]
;;TODO accessories
:options {:topBar {:visible false}}
:component new-chat-aio/contact-toggle-list}
;[Chat] New Public chat
{:name :new-public-chat
:insets {:bottom true}
:options {:topBar {:title {:text (i18n/label :t/edit-group)}}}
:component group-chat/edit-group-chat-name}
:options {:topBar {:title {:text (i18n/label :t/new-public-group-chat)}}}
:component new-public-chat/new-public-chat}
;[Group chat] Add participants
{:name :add-participants-toggle-list
@@ -0,0 +1,50 @@
(ns status-im.ui2.components.search-input
(:require [reagent.core :as reagent]
[status-im.i18n.i18n :as i18n]
[quo.design-system.colors :as colors]
[quo2.foundations.colors :as quo2.colors]
[quo.components.text-input :as text-input]))
(defn search-input [{:keys [search-active?]}]
(let [input-ref (reagent/atom nil)
placeholder-text (reagent/atom :t/search-contacts)
search-active? (or search-active? (reagent/atom nil))]
(fn [{:keys [on-focus on-change search-border-width show-cancel? search-border-radius on-blur on-cancel search-filter auto-focus] :or {show-cancel? false}}]
[text-input/text-input {:placeholder (i18n/label @placeholder-text)
:placeholder-text-color (if (= @placeholder-text :t/search-contacts)
(quo2.colors/theme-colors quo2.colors/neutral-30 quo2.colors/neutral-50)
(quo2.colors/theme-colors quo2.colors/neutral-30 quo2.colors/neutral-60))
:accessibility-label :search-input
:text-padding-left 0
:blur-on-submit true
:multiline false
:get-ref #(reset! input-ref %)
:default-value search-filter
:auto-focus auto-focus
:on-cancel on-cancel
:show-cancel show-cancel?
:auto-correct false
:auto-capitalize :none
:container-style {:border-radius (or search-border-radius 10)
:border-width (or search-border-width 1)
:border-color (:ui-01 @colors/theme)
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
:overflow :hidden}
:input-style {:height 32
:padding-vertical 2
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}
:on-focus #(do
(when on-focus
(on-focus search-filter))
(swap! search-active? not)
(reset! placeholder-text :t/who-are-you-looking-for))
:on-blur #(do
(when on-blur
(on-blur))
(swap! search-active? not)
(reset! placeholder-text :t/search-contacts))
:on-change (fn [e]
(let [^js native-event (.-nativeEvent ^js e)
text (.-text native-event)]
(when on-change
(on-change text))))}])))
+40
View File
@@ -0,0 +1,40 @@
(ns status-im.ui2.components.toolbar
(:require [status-im.ui.components.react :as react]
[quo.design-system.colors :as colors]))
(defn toolbar-container [{:keys [show-border? size center? margin-bottom container-styling]
:or {size :default}}]
(merge {:align-items :center
:padding-horizontal 8
:margin-bottom (or margin-bottom 0)
:width "100%"
:flex-direction :row
:justify-content :space-between}
container-styling
(when center?
{:justify-content :center})
(when show-border?
{:border-top-width 1
:border-top-color colors/gray-lighter})
(case size
:large {:height 60}
{:height 52})))
;; TODO(Ferossgp): Allow components when moving to Quo
(defn toolbar [{:keys [center left right show-border? size margin-bottom container-styling]}]
(if center
[react/view {:style (toolbar-container {:show-border? show-border?
:center? true
:margin-bottom margin-bottom
:size size
:container-styling container-styling})}
center]
[react/view {:style (toolbar-container {:show-border? show-border?
:margin-bottom margin-bottom
:center? false
:size size
:container-styling container-styling})}
[react/view {:flex-shrink 1}
(when left left)]
[react/view
(when right right)]]))
@@ -0,0 +1,283 @@
(ns status-im.ui2.screens.chat.components.new-chat
(:require [cljs.spec.alpha :as spec]
[clojure.string :as string]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.invite.views :as invite]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui2.components.search-input :as search]
[status-im.ui2.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.group.styles :as styles]
[quo.core :as quo]
[quo2.core :as quo2]
[quo2.components.buttons.button :as button]
[status-im.utils.re-frame :as rf]
[status-im.utils.debounce :as debounce]
[quo2.foundations.colors :as quo2.colors]
[status-im.ui2.screens.chat.actions :refer [hide-sheet-and-dispatch]])
(:require-macros [status-im.utils.views :as views]))
(defn- render-contact [row]
(let [[first-name second-name] (multiaccounts/contact-two-names row false)]
[quo2/list-item
{:title first-name
:subtitle second-name
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo row)]}]))
(defn- on-toggle [allow-new-users? checked? public-key]
(cond
checked?
(rf/dispatch [:deselect-contact public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(rf/dispatch [:select-contact public-key allow-new-users?])))
(defn- on-toggle-participant [allow-new-users? checked? public-key]
(cond
checked?
(rf/dispatch [:deselect-participant public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(rf/dispatch [:select-participant public-key allow-new-users?])))
(defn- toggle-item []
(fn [allow-new-users? subs-name {:keys [public-key] :as contact} on-toggle]
(let [contact-selected? @(re-frame/subscribe [subs-name public-key])
[first-name second-name] (multiaccounts/contact-two-names contact true)]
[quo2/list-item
{:title first-name
:text-color (quo2.colors/theme-colors quo2.colors/neutral-100 quo2.colors/white)
:subtitle second-name
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo contact)]
:on-press #(on-toggle allow-new-users? contact-selected? public-key)
:active contact-selected?
:accessory :checkbox
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}])))
(defn- group-toggle-contact [{:keys [:allow-new-users?] :as contact} _ _]
[toggle-item allow-new-users? :is-contact-selected? contact on-toggle])
(defn- group-toggle-participant [{:keys [:allow-new-users?] :as contact} _ _]
[toggle-item allow-new-users? :is-participant-selected? contact on-toggle-participant])
(defn toggle-list [{:keys [contacts render-fn]}]
[list/section-list
{:content-container-style {:padding-vertical 8}
:key-fn :id
:keyboard-should-persist-taps :always
:sticky-section-headers-enabled false
:sections contacts
:render-section-header-fn quo2/index
:render-fn render-fn}])
(defn no-contacts [{:keys [no-contacts]}]
[react/view {:style styles/no-contacts}
[react/text
{:style (styles/no-contact-text)}
no-contacts]
[invite/button]])
(defn filter-contacts [filter-text contacts]
(let [lower-filter-text (string/lower-case (str filter-text))
filter-fn (fn [{:keys [data]}]
(let [{:keys [name alias nickname]} (first data)]
(or
(string/includes? (string/lower-case (str name)) lower-filter-text)
(string/includes? (string/lower-case (str alias)) lower-filter-text)
(when nickname
(string/includes? (string/lower-case (str nickname)) lower-filter-text)))))]
(if filter-text
(filter filter-fn contacts)
contacts)))
;; Set name of new group-chat
(defn new-group []
(let [contacts (rf/sub [:selected-group-contacts])
group-name (rf/sub [:new-chat-name])
group-name-empty? (not (spec/valid? :global/not-empty-string group-name))]
[react/keyboard-avoiding-view {:style styles/group-container
:ignore-offset true}
[react/view {:flex 1}
[topbar/topbar {:use-insets false
:title (i18n/label :t/new-group-chat)
:subtitle (i18n/label :t/group-chat-members-count
{:selected (inc (count contacts))
:max constants/max-group-chat-participants})}]
[react/view {:style {:padding-top 16
:flex 1}}
[react/view {:style {:padding-horizontal 16}}
[quo/text-input
{:auto-focus true
:on-change-text #(rf/dispatch [:set :new-chat-name %])
:default-value group-name
:placeholder (i18n/label :t/set-a-topic)
:accessibility-label :chat-name-input}]
[react/text {:style (styles/members-title)}
(i18n/label :t/members-title)]]
[react/view {:style {:margin-top 8
:flex 1}}
[list/flat-list {:data contacts
:key-fn :address
:render-fn render-contact
:bounces false
:keyboard-should-persist-taps :always
:enable-empty-sections true}]]]
[toolbar/toolbar
{:show-border? true
:left [quo/button {:type :secondary
:before :main-icon/back
:accessibility-label :previous-button
:on-press #(rf/dispatch [:navigate-back])}
(i18n/label :t/back)]
:right [quo/button {:type :secondary
:accessibility-label :create-group-chat-button
:disabled group-name-empty?
:on-press #(debounce/dispatch-and-chill [:group-chats.ui/create-pressed group-name]
300)}
(i18n/label :t/create-group-chat)]}]]]))
(defn searchable-contact-list []
(let [search-value (reagent/atom nil)]
(fn [{:keys [contacts no-contacts-label toggle-fn allow-new-users? show-cancel?]}]
[react/view {:style {:flex 1}}
[react/view {:style (styles/search-container)}
[search/search-input {:on-cancel #(reset! search-value nil)
:search-border-radius 0
:show-cancel show-cancel?
:search-border-width 0
:on-change #(reset! search-value %)}]]
[react/view {:style {:flex 1
:padding-vertical 8
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}}
(if (seq contacts)
[toggle-list {:contacts (filter-contacts @search-value contacts)
:render-data allow-new-users?
:render-fn toggle-fn}]
[no-contacts {:no-contacts no-contacts-label}])]])))
;; Start group chat
(defn contact-toggle-list []
(let [contacts (rf/sub [:contacts/sorted-and-grouped-by-first-letter])
selected-contacts-count (rf/sub [:selected-contacts-count])
window-height (rf/sub [:dimensions/window-height])
one-contact-selected? (= selected-contacts-count 1)
no-contacts-selected? (zero? selected-contacts-count)
{:keys [alias public-key]} (-> contacts first :data first)]
[react/view {:style {:height (* window-height 0.95)}}
[topbar/topbar {:use-insets false
:border-bottom false
:style {:top -15}
:close-icon-container-props {:style {:width 32
:height 32
:border-radius 10
:justify-content :center
:align-items :center
:background-color (quo2.colors/theme-colors quo2.colors/neutral-10 quo2.colors/neutral-80)}}
:close-icon-props {:size 20
:color (quo2.colors/theme-colors quo2.colors/black quo2.colors/white)}
:navigation {:sheet? true}
:modal? true
:background (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)}]
[react/view {:style {:flex-direction :row
:justify-content :space-between
:align-items :flex-end
:padding-horizontal 20}}
[quo2/text {:weight :semi-bold
:size :heading-1
:color (quo2.colors/theme-colors quo2.colors/neutral-40 quo2.colors/neutral-50)}
(i18n/label :t/new-chat)]
[quo2/text {:size :paragraph-2
:weight :regular
:secondary-color (quo2.colors/theme-colors quo2.colors/neutral-40 quo2.colors/neutral-50)}
(i18n/label :t/selected-count-from-max
{:selected (inc selected-contacts-count)
:max constants/max-group-chat-participants})]]
[react/view {:style {:height 430}}
[searchable-contact-list
{:contacts contacts
:show-cancel? false
:no-contacts-label (i18n/label :t/group-chat-no-contacts)
:toggle-fn group-toggle-contact}]]
(when-not no-contacts-selected?
[toolbar/toolbar
{:show-border? false
:margin-bottom 20
:center [button/button {:type :primary
:accessibility-label :next-button
:on-press #(do
(if one-contact-selected?
(hide-sheet-and-dispatch [:chat.ui/start-chat public-key])
(hide-sheet-and-dispatch [:navigate-to :new-group])))}
(if one-contact-selected?
(i18n/label :t/chat-with {:selected-user alias})
(i18n/label :t/setup-group-chat))]}])]))
;; Add participants to existing group chat
(defn add-participants-toggle-list []
(let [contacts (rf/sub [:contacts/all-contacts-not-in-current-chat])
current-chat (rf/sub [:chats/current-chat])
selected-contacts-count (rf/sub [:selected-participants-count])
current-participants-count (count (:contacts current-chat))]
[kb-presentation/keyboard-avoiding-view {:style styles/group-container}
[topbar/topbar {:use-insets false
:border-bottom false
:title (i18n/label :t/add-members)
:subtitle (i18n/label :t/group-chat-members-count
{:selected (+ current-participants-count selected-contacts-count)
:max constants/max-group-chat-participants})}]
[searchable-contact-list
{:contacts contacts
:no-contacts-label (i18n/label :t/group-chat-all-contacts-invited)
:toggle-fn group-toggle-participant
:allow-new-users? (< (+ current-participants-count
selected-contacts-count)
constants/max-group-chat-participants)}]
[toolbar/toolbar
{:show-border? true
:center [quo/button {:type :secondary
:accessibility-label :next-button
:disabled (zero? selected-contacts-count)
:on-press #(rf/dispatch [:group-chats.ui/add-members-pressed])}
(i18n/label :t/add)]}]]))
(defn edit-group-chat-name []
(let [{:keys [name chat-id]} (rf/sub [:chats/current-chat])
new-group-chat-name (reagent/atom nil)]
[kb-presentation/keyboard-avoiding-view {:style styles/group-container}
[react/scroll-view {:style {:padding 16
:flex 1}}
[quo/text-input
{:on-change-text #(reset! new-group-chat-name %)
:default-value name
:on-submit-editing #(when (seq @new-group-chat-name)
(rf/dispatch [:group-chats.ui/name-changed chat-id @new-group-chat-name]))
:placeholder (i18n/label :t/enter-contact-code)
:accessibility-label :new-chat-name
:return-key-type :go}]]
[react/view {:style {:flex 1}}]
[toolbar/toolbar
{:show-border? true
:center
[quo/button {:type :secondary
:accessibility-label :done
:disabled (and (<= (count @new-group-chat-name) 1)
(not (nil? @new-group-chat-name)))
:on-press #(cond
(< 1 (count @new-group-chat-name))
(rf/dispatch [:group-chats.ui/name-changed chat-id @new-group-chat-name])
(nil? @new-group-chat-name)
(rf/dispatch [:navigate-back]))}
(i18n/label :t/done)]}]]))
+88 -63
View File
@@ -15,10 +15,11 @@
[status-im.add-new.db :as db]
[status-im.utils.debounce :as debounce]
[status-im.utils.utils :as utils]
[status-im.utils.re-frame :as rf]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.components.plus-button :as components.plus-button]
[status-im.ui.components.invite.views :as invite]
[status-im.utils.handlers :refer [<sub >evt]]
[status-im.utils.handlers :refer [>evt]]
[status-im.utils.config :as config]
[quo2.components.markdown.text :as quo2.text]
[status-im.qr-scanner.core :as qr-scanner]
@@ -42,25 +43,38 @@
(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/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}}]]
: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])
{:style {:position :absolute
:right 0
:top 0
:width 44
:height 44
:align-items :center
:justify-content :center}
:on-press #(rf/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}]
[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/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)]])
@@ -69,7 +83,8 @@
:flex-direction :row
:align-items :center
:justify-content :center}}
[react/i18n-text {:style styles/welcome-blank-text :key :welcome-blank-message}]])
[react/i18n-text {:style styles/welcome-blank-text
:key :welcome-blank-message}]])
(defonce search-active? (reagent/atom false))
@@ -79,25 +94,24 @@
[search-input/search-input
{:search-active? search-active?
:search-filter search-filter
:on-cancel #(re-frame/dispatch [:search/home-filter-changed nil])
:on-cancel #(rf/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]))
(rf/dispatch [:search/home-filter-changed nil]))
(rf/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])))
(rf/dispatch [:search/home-filter-changed ""])
(rf/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])
(rf/dispatch [:search/home-filter-changed text])
(rf/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)]
(let [{:keys [state ens-name public-key]} (rf/sub [: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)]
@@ -108,16 +122,16 @@
: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]))}])
(rf/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]))}])])))
(rf/dispatch [:chat.ui/start-public-chat search-value])
(rf/dispatch [:set :public-group-topic nil])
(rf/dispatch [:search/home-filter-changed nil]))}])])))
(defn chat-list-key-fn [item]
(or (:chat-id item) (:public-key item) (:id item)))
@@ -143,7 +157,11 @@
(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/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]
@@ -162,23 +180,22 @@
(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])
(let [{window-height :height} (rn/use-window-dimensions)
safe-area (safe-area/use-safe-area)
notifications (rf/sub [:activity.center/notifications-grouped-by-date])
{received-requests :received-requests} (find-contact-requests notifications)
sent-requests []]
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}}
: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
@@ -186,7 +203,8 @@
{:color (colors/theme-colors "#000000" "#ffffff")})}
(i18n/label :t/pending-requests)]
[quo2.tabs/tabs
{:style {:margin-top 12 :margin-bottom 20}
{:style {:margin-top 12
:margin-bottom 20}
:size 32
:on-change #(reset! selected-requests-tab %)
:default-active :received
@@ -200,7 +218,7 @@
: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]))
(let [name (first (rf/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 " "))
@@ -242,14 +260,13 @@
[info-count (count requests)]])
(defn chats []
(let [{:keys [items search-filter]} (<sub [:home-items])
(let [{:keys [items search-filter]} (rf/sub [:home-items])
current-active-tab @selected-tab
items (prepare-items current-active-tab items)
contacts (<sub [:contacts/active])
contacts (rf/sub [:contacts/active])
contacts (prepare-contacts contacts)
notifications (<sub [:activity.center/notifications-grouped-by-date])
notifications (rf/sub [:activity.center/notifications-grouped-by-date])
{requests :received-requests new-info :has-unread?} (find-contact-requests notifications)]
(println "wtfff" items contacts)
[rn/view {:style {:flex 1}}
[discover-card/discover-card {:title (i18n/label :t/invite-friends-to-status)
:description (i18n/label :t/share-invite-link)}]
@@ -274,7 +291,7 @@
[list/flat-list
{:key-fn chat-list-key-fn
:getItemLayout get-item-layout
:on-end-reached #(re-frame/dispatch [:chat.ui/show-more-chats])
:on-end-reached #(rf/dispatch [:chat.ui/show-more-chats])
:keyboard-should-persist-taps :always
:data items
:render-fn messages-home-item}]
@@ -287,8 +304,8 @@
:render-section-header-fn contacts-section-header
:render-fn contact-item}]]))]))
(views/defview chats-list []
(views/letsubs [loading? [:chats/loading?]]
(defn chats-list []
(let [loading? (rf/sub [:chats/loading?])]
[:<>
[connectivity/loading-indicator]
(if loading?
@@ -296,16 +313,24 @@
[rn/activity-indicator {:animating true}]]
[chats])]))
(views/defview plus-button []
(views/letsubs [logging-in? [:multiaccounts/login]]
(defn plus-button []
(let [logging-in? (rf/sub [:multiaccounts/login])]
[components.plus-button/plus-button
{:on-press (when-not logging-in?
#(re-frame/dispatch [:bottom-sheet/show-sheet :add-new {}]))
#(rf/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]]
(defn plus-button-new-messages []
(let [logging-in? (rf/sub [:multiaccounts/login])]
[components.plus-button/plus-button
{:on-press (when-not logging-in?
#(rf/dispatch [:bottom-sheet/show-sheet :add-new-sheet-view {}]))
:loading logging-in?
:accessibility-label :new-chat-button}]))
(defn notifications-button []
(let [notif-count (rf/sub [:activity.center/notifications-count])]
[rn/view
[quo2.button/button {:type :grey
:size 32
@@ -313,10 +338,10 @@
:style {:margin-left 12}
:accessibility-label :notifications-button
:on-press #(do
(re-frame/dispatch [:mark-all-activity-center-notifications-as-read])
(rf/dispatch [:mark-all-activity-center-notifications-as-read])
(if config/new-activity-center-enabled?
(re-frame/dispatch [:navigate-to :activity-center])
(re-frame/dispatch [:navigate-to :notifications-center])))}
(rf/dispatch [:navigate-to :activity-center])
(rf/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})
@@ -331,7 +356,7 @@
:width 32
:style {:margin-left 12}
:on-press #(do
(re-frame/dispatch [::qr-scanner/scan-code
(rf/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)}]])
@@ -341,12 +366,12 @@
:width 32
:accessibility-label "scan-button"
:on-press #(do
(re-frame/dispatch [::qr-scanner/scan-code
{:handler ::qr-scanner/on-scan-success}]))}
(rf/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]]
(defn profile-button []
(let [{:keys [public-key preferred-name emoji]} (rf/sub [:multiaccount])]
[rn/view
[chat-icon/emoji-chat-icon-view public-key false preferred-name emoji
{:size 28
@@ -355,7 +380,7 @@
(defn home []
[:f>
(fn []
(quo.react/effect! #(re-frame/dispatch [:get-activity-center-notifications]))
(quo.react/effect! #(rf/dispatch [:get-activity-center-notifications]))
[rn/keyboard-avoiding-view {:style {:flex 1
:background-color (colors/theme-colors colors/neutral-5 colors/neutral-95)}
:ignore-offset true}
@@ -376,6 +401,6 @@
:margin-top 15
:margin-bottom 20}
[quo2.text/text {:size :heading-1 :weight :semi-bold} (i18n/label :t/messages)]
[plus-button]]
[plus-button-new-messages]]
[chats-list]])])
@@ -0,0 +1,36 @@
(ns status-im.ui2.screens.group.styles
(:require [quo.design-system.colors :as colors]
[quo2.foundations.colors :as quo2.colors]))
(def group-container
{:flex 1
:flex-direction :column
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)})
(defn no-contact-text []
{:margin-bottom 20
:margin-horizontal 50
:text-align :center
:color colors/gray})
(def toolbar-header-container
{:align-items :center})
(defn toolbar-sub-header []
{:color colors/gray})
(def no-contacts
{:flex 1
:justify-content :center
:align-items :center})
(defn search-container []
{:border-bottom-color colors/gray-lighter
:background-color (quo2.colors/theme-colors quo2.colors/white quo2.colors/neutral-90)
:padding-horizontal 20
:padding-top 10})
(defn members-title []
{:color colors/gray
:margin-top 14
:margin-bottom 4})
+17 -1
View File
@@ -6,7 +6,8 @@
[clojure.string :as string]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.gfycat.core :as gfycat]
[status-im.ethereum.core :as ethereum]))
[status-im.ethereum.core :as ethereum]
[status-im.constants :as constants]))
(re-frame/reg-sub
::query-current-chat-contacts
@@ -68,6 +69,21 @@
(fn [contacts]
(contact.db/get-active-contacts contacts)))
(re-frame/reg-sub
:contacts/sorted-and-grouped-by-first-letter
:<- [:contacts/active]
:<- [:selected-contacts-count]
(fn [[contacts selected-contacts-count]]
(->> contacts
(filter :mutual?)
(map #(assoc % :allow-new-users? (< selected-contacts-count
(dec constants/max-group-chat-participants))))
(group-by (comp (fnil string/upper-case "") first :alias))
(sort-by (fn [[title]] title))
(map (fn [[title data]]
{:title title
:data data})))))
(re-frame/reg-sub
:contacts/sorted-contacts
:<- [:contacts/active]
+9 -1
View File
@@ -1457,6 +1457,8 @@
"set-custom-fee": "Set custom fee",
"not-enough-snt": "Not enough SNT",
"add-new-contact": "Add new contact",
"add-a-contact": "Add a contact",
"enter-a-chat-key": "Enter a chat key or scan a QR",
"you-dont-have-contacts": "You dont have any contacts yet.",
"set-max": "Set max",
"continue-anyway": "Continue anyway",
@@ -1853,5 +1855,11 @@
"mark-user-untrustworthy": "Mark {{username}} as untrustworthy",
"leave-group?": "Leave Group?",
"block-user?": "Block User?",
"clear-history?": "Clear History?"
"clear-history?": "Clear History?",
"chat-with": "Chat with {{selected-user}}",
"setup-group-chat": "Setup group chat",
"search-contacts": "Search contacts",
"who-are-you-looking-for": "Who are you looking for ?",
"close-contact-search": "Close contact search",
"selected-count-from-max": "{{selected}}/{{max}}"
}