Group details screen (3) (#14494)

* group details screen (3)
This commit is contained in:
Omar Basem 2022-12-23 07:18:09 +04:00 committed by GitHub
parent 1af6d925d2
commit e21b8d4396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 1201 additions and 1306 deletions

View File

@ -1,6 +1,6 @@
(ns quo2.components.avatars.group-avatar
(:require [quo2.components.icon :as icon]
[quo2.foundations.colors :as colors]
(:require [quo2.foundations.colors :as colors]
[quo2.components.icon :as icon]
[react-native.core :as rn]))
(def sizes
@ -11,20 +11,17 @@
:medium 32
:large 48}})
;; TODO: this implementation does not support group display picture (can only display default group
;; icon).
(defn group-avatar
[_]
;; TODO: this implementation does not support group display picture (can only display default group icon).
(defn group-avatar [_]
(fn [{:keys [color size]}]
(let [container-size (get-in sizes [:container size])
icon-size (get-in sizes [:icon size])]
[rn/view
{:width container-size
[rn/view {:width container-size
:height container-size
:align-items :center
:justify-content :center
:border-radius (/ container-size 2)
:background-color (colors/custom-color-by-theme color 50 60)}
[icon/icon :i/group
{:size icon-size
;:background-color (colors/custom-color-by-theme color 50 60) ; TODO: this is temporary only. Issue: https://github.com/status-im/status-mobile/issues/14566
:background-color color}
[icon/icon :i/group {:size icon-size
:color colors/white-opa-70}]])))

View File

@ -39,7 +39,16 @@
{:json-rpc/call [{:method "wakuext_removeMemberFromGroupChat"
:params [nil chat-id member]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated % do-not-navigate?])}]})
:on-success #(re-frame/dispatch [:chat-updated % true])}]})
(fx/defn remove-members
{:events [:group-chats.ui/remove-members-pressed]}
[{{:keys [current-chat-id] :group-chat/keys [deselected-members]} :db :as cofx}]
{:json-rpc/call [{:method "wakuext_removeMembersFromGroupChat"
:params [nil current-chat-id deselected-members]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated % true])
:on-error #()}]})
(fx/defn join-chat
{:events [:group-chats.ui/join-pressed]}
@ -79,11 +88,11 @@
(fx/defn add-members
"Add members to a group chat"
{:events [:group-chats.ui/add-members-pressed]}
[{{:keys [current-chat-id selected-participants]} :db :as cofx}]
[{{:keys [current-chat-id] :group-chat/keys [selected-participants]} :db :as cofx}]
{:json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil current-chat-id selected-participants]
:js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})
:on-success #(re-frame/dispatch [:chat-updated % true])}]})
(fx/defn add-members-from-invitation
"Add members to a group chat"
@ -179,6 +188,16 @@
:type
(= constants/invitation-state-removed)))
(fx/defn deselect-member
{:events [:deselect-member]}
[{:keys [db]} id]
{:db (update db :group-chat/deselected-members conj id)})
(fx/defn undo-deselect-member
{:events [:undo-deselect-member]}
[{:keys [db]} id]
{:db (update db :group-chat/deselected-members disj id)})
(fx/defn deselect-contact
{:events [:deselect-contact]}
[{:keys [db]} id]
@ -192,17 +211,22 @@
(fx/defn deselect-participant
{:events [:deselect-participant]}
[{:keys [db]} id]
{:db (update db :selected-participants disj id)})
{:db (update db :group-chat/selected-participants disj id)})
(fx/defn select-participant
{:events [:select-participant]}
[{:keys [db]} id]
{:db (update db :selected-participants conj id)})
{:db (update db :group-chat/selected-participants conj id)})
(fx/defn add-participants-toggle-list
{:events [:group/add-participants-toggle-list]}
(fx/defn clear-added-participants
{:events [:group/clear-added-participants]}
[{db :db}]
{:db (assoc db :selected-participants #{})})
{:db (assoc db :group-chat/selected-participants #{})})
(fx/defn clear-removed-members
{:events [:group/clear-removed-members]}
[{db :db}]
{:db (assoc db :group-chat/deselected-members #{})})
(fx/defn show-group-chat-profile
{:events [:show-group-chat-profile]}

View File

@ -1,25 +1,26 @@
(ns status-im.ui.screens.group.views
(:require [clojure.string :as string]
[quo.core :as quo]
[re-frame.core :as re-frame]
[reagent.core :as reagent]
[status-im.constants :as constants]
[status-im.i18n.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[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.keyboard-avoid-presentation :as kb-presentation]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react]
[status-im.ui.components.search-input.view :as search]
[status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.group.styles :as styles]
[quo.core :as quo]
[utils.debounce :as debounce])
(:require-macros [status-im.utils.views :as views]))
(defn- render-contact
[row]
(defn- render-contact [row]
(let [[first-name second-name] (multiaccounts/contact-two-names row false)]
[quo/list-item
{:title first-name
@ -27,8 +28,7 @@
:icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo row)]}]))
(defn- on-toggle
[allow-new-users? checked? public-key]
(defn- on-toggle [allow-new-users? checked? public-key]
(cond
checked?
@ -39,8 +39,7 @@
allow-new-users?)
(re-frame/dispatch [:select-contact public-key allow-new-users?])))
(defn- on-toggle-participant
[allow-new-users? checked? public-key]
(defn- on-toggle-participant [allow-new-users? checked? public-key]
(cond
checked?
@ -51,8 +50,7 @@
allow-new-users?)
(re-frame/dispatch [:select-participant public-key allow-new-users?])))
(defn- toggle-item
[]
(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)]
@ -65,63 +63,52 @@
:active contact-selected?
:accessory :checkbox}])))
(defn- group-toggle-contact
[contact _ _ allow-new-users?]
(defn- group-toggle-contact [contact _ _ allow-new-users?]
[toggle-item allow-new-users? :is-contact-selected? contact on-toggle])
(defn- group-toggle-participant
[contact _ _ allow-new-users?]
(defn- group-toggle-participant [contact _ _ allow-new-users?]
[toggle-item allow-new-users? :is-participant-selected? contact on-toggle-participant])
(defn toggle-list
[{:keys [contacts render-fn render-data]}]
[list/flat-list
{:data contacts
(defn toggle-list [{:keys [contacts render-fn render-data]}]
[list/flat-list {:data contacts
:key-fn :public-key
:render-data render-data
:render-fn render-fn
:keyboardShouldPersistTaps :always}])
(defn no-contacts
[{:keys [no-contacts]}]
(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]
(defn filter-contacts [filter-text contacts]
(let [lower-filter-text (string/lower-case (str filter-text))
filter-fn (fn [{:keys [name alias nickname]}]
(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))))]
(string/includes? (string/lower-case (str nickname)) lower-filter-text))))]
(if filter-text
(filter filter-fn contacts)
contacts)))
;; Set name of new group-chat
(views/defview new-group
[]
(views/defview new-group []
(views/letsubs [contacts [:selected-group-contacts]
group-name [:new-chat-name]]
(let [group-name-empty? (not (and (string? group-name) (not-empty group-name)))]
[react/keyboard-avoiding-view
{:style styles/group-container
[react/keyboard-avoiding-view {:style styles/group-container
:ignore-offset true}
[react/view {:flex 1}
[topbar/topbar
{:use-insets false
[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
[react/view {:style {:padding-top 16
:flex 1}}
[react/view {:style {:padding-horizontal 16}}
[quo/text-input
@ -132,11 +119,9 @@
:accessibility-label :chat-name-input}]
[react/text {:style (styles/members-title)}
(i18n/label :t/members-title)]]
[react/view
{:style {:margin-top 8
[react/view {:style {:margin-top 8
:flex 1}}
[list/flat-list
{:data contacts
[list/flat-list {:data contacts
:key-fn :address
:render-fn render-contact
:bounces false
@ -145,51 +130,41 @@
[toolbar/toolbar
{:show-border? true
:left
[quo/button
{:type :secondary
[quo/button {:type :secondary
:before :main-icon/back
:accessibility-label :previous-button
:on-press #(re-frame/dispatch [:navigate-back])}
(i18n/label :t/back)]
:right
[quo/button
{:type :secondary
[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]
:on-press #(debounce/dispatch-and-chill [:group-chats.ui/create-pressed group-name]
300)}
(i18n/label :t/create-group-chat)]}]]])))
(defn searchable-contact-list
[]
(defn searchable-contact-list []
(let [search-value (reagent/atom nil)]
(fn [{:keys [contacts no-contacts-label toggle-fn allow-new-users?]}]
[react/view {:style {:flex 1}}
[react/view {:style (styles/search-container)}
[search/search-input-old
{:on-cancel #(reset! search-value nil)
[search/search-input-old {:on-cancel #(reset! search-value nil)
:on-change #(reset! search-value %)}]]
[react/view
{:style {:flex 1
[react/view {:style {:flex 1
:padding-vertical 8}}
(if (seq contacts)
[toggle-list
{:contacts (filter-contacts @search-value 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
(views/defview contact-toggle-list
[]
(views/defview contact-toggle-list []
(views/letsubs [contacts [:contacts/active]
selected-contacts-count [:selected-contacts-count]]
[react/keyboard-avoiding-view
{:style styles/group-container
[react/keyboard-avoiding-view {:style styles/group-container
:ignore-offset true}
[topbar/topbar
{:use-insets false
[topbar/topbar {:use-insets false
:border-bottom false
:title (i18n/label :t/new-group-chat)
:subtitle (i18n/label :t/group-chat-members-count
@ -204,23 +179,20 @@
[toolbar/toolbar
{:show-border? true
:right
[quo/button
{:type :secondary
[quo/button {:type :secondary
:after :main-icon/next
:accessibility-label :next-button
:on-press #(re-frame/dispatch [:navigate-to :new-group])}
(i18n/label :t/next)]}]]))
;; Add participants to existing group chat
(views/defview add-participants-toggle-list
[]
(views/defview add-participants-toggle-list []
(views/letsubs [contacts [:contacts/all-contacts-not-in-current-chat]
current-chat [:chats/current-chat]
selected-contacts-count [:selected-participants-count]]
selected-contacts-count [:group-chat/selected-participants-count]]
(let [current-participants-count (count (:contacts current-chat))]
[kb-presentation/keyboard-avoiding-view {:style styles/group-container}
[topbar/topbar
{:use-insets false
[topbar/topbar {:use-insets false
:border-bottom false
:title (i18n/label :t/add-members)
:subtitle (i18n/label :t/group-chat-members-count
@ -236,27 +208,23 @@
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:type :secondary
[quo/button {:type :secondary
:accessibility-label :next-button
:disabled (zero? selected-contacts-count)
:on-press #(re-frame/dispatch [:group-chats.ui/add-members-pressed])}
(i18n/label :t/add)]}]])))
(views/defview edit-group-chat-name
[]
(views/defview edit-group-chat-name []
(views/letsubs [{:keys [name chat-id]} [: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
[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)
(re-frame/dispatch [:group-chats.ui/name-changed chat-id
@new-group-chat-name]))
(re-frame/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}]]
@ -264,15 +232,13 @@
[toolbar/toolbar
{:show-border? true
:center
[quo/button
{:type :secondary
[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))
(re-frame/dispatch [:group-chats.ui/name-changed chat-id
@new-group-chat-name])
(re-frame/dispatch [:group-chats.ui/name-changed chat-id @new-group-chat-name])
(nil? @new-group-chat-name)
(re-frame/dispatch [:navigate-back]))}

View File

@ -1,5 +1,6 @@
(ns status-im.ui2.screens.chat.group-details.style
(:require [quo2.foundations.colors :as colors]))
(:require [quo2.foundations.colors :as colors]
[react-native.platform :as platform]))
(defn actions-view
[]
@ -33,12 +34,15 @@
:align-items :center
:margin-bottom 24})
(def bottom-container
{:position :absolute
(defn bottom-container [safe-area]
{
;:position :absolute
:padding-horizontal 20
:padding-vertical 12
:padding-bottom 33
:padding-bottom (+ 33 (if platform/ios? (:bottom safe-area) 0))
:width "100%"
:background-color colors/white
:flex-direction :row
:bottom 0})
;:padding-bottom (if platform/ios? (:bottom safe-area) 0)
:margin-bottom (if platform/ios? 0 70)
})

View File

@ -1,22 +1,18 @@
(ns status-im.ui2.screens.chat.group-details.view
(:require [i18n.i18n :as i18n]
[oops.core :refer [oget]]
[quo.components.safe-area :as safe-area]
[quo2.core :as quo2]
(:require [react-native.core :as rn]
[quo2.foundations.colors :as colors]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.chat.models :as chat.models]
[status-im.ui2.screens.chat.group-details.style :as style]
[status-im.ui2.screens.common.contact-list.view :as contact-list]
[quo2.core :as quo2]
[utils.re-frame :as rf]
[i18n.i18n :as i18n]
[status-im.chat.models :as chat.models]
[status-im2.common.contact-list-item.view :as contact-list-item]
[quo.components.safe-area :as safe-area]
[status-im2.common.home.actions.view :as actions]
[utils.re-frame :as rf]))
[status-im.ui2.screens.common.contact-list.view :as contact-list]))
(defn back-button
[]
[quo2/button
{:type :grey
(defn back-button []
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-left 20}
@ -24,11 +20,9 @@
:on-press #(rf/dispatch [:navigate-back])}
[quo2/icon :i/arrow-left {:color (colors/theme-colors colors/neutral-100 colors/white)}]])
(defn options-button
[]
(defn options-button []
(let [group (rf/sub [:chats/current-chat])]
[quo2/button
{:type :grey
[quo2/button {:type :grey
:size 32
:width 32
:style {:margin-right 20}
@ -37,136 +31,105 @@
{:content (fn [] [actions/group-details-actions group])}])}
[quo2/icon :i/options {:color (colors/theme-colors colors/neutral-100 colors/white)}]]))
(defn top-buttons
[]
[rn/view
{:style {:flex-direction :row
(defn top-buttons []
[rn/view {:style {:flex-direction :row
:padding-horizontal 20
:justify-content :space-between}}
[back-button] [options-button]])
(defn count-container
[count]
[rn/view {:style (style/count-container)}
[quo2/text
{:size :label
(defn count-container [count accessibility-label]
[rn/view {:style (style/count-container)
:accessibility-label accessibility-label}
[quo2/text {:size :label
:weight :medium
:style {:text-align :center}} count]])
(defn contacts-section-header
[{:keys [title]}]
[rn/view
{:style {:padding-horizontal 20
:border-top-width 1
:border-top-color colors/neutral-20
:padding-vertical 8
:margin-top 8}}
[quo2/text
{:size :paragraph-2
(defn contacts-section-header [{:keys [title]}]
[rn/view {:style {:padding-horizontal 20 :border-top-width 1 :border-top-color colors/neutral-20 :padding-vertical 8 :margin-top 8}}
[quo2/text {:size :paragraph-2
:weight :medium
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}} title]])
(def added (reagent/atom ()))
(defn contact-requests-sheet
[group]
(let [added (reagent/atom ())]
(fn []
(defn add-members-sheet [group admin?]
[:f>
(fn []
(let [{window-height :height} (rn/use-window-dimensions)
safe-area (safe-area/use-safe-area)]
safe-area (safe-area/use-safe-area)
selected-participants (rf/sub [:group-chat/selected-participants])
deselected-members (rf/sub [:group-chat/deselected-members])]
[rn/view {:style {:height (- window-height (:top safe-area))}}
[rn/touchable-opacity
{:on-press #(rf/dispatch [:bottom-sheet/hide])
:accessibility-label :close-manage-members
:style (style/close-icon)}
[quo2/icon :i/close {:color (colors/theme-colors colors/neutral-100 colors/white)}]]
[quo2/text
{:size :heading-1
[quo2/text {:size :heading-1
:weight :semi-bold
:style {:margin-left 20}}
(i18n/label :t/add-members)]
[rn/text-input
{:placeholder (str (i18n/label :t/search) "...")
:style {:height 32
:padding-horizontal 20
:margin-vertical 12}
:on-change (fn [e]
(rf/dispatch [:contacts/set-search-query (oget e "nativeEvent.text")]))}]
[contact-list/contact-list
{:icon :check
(i18n/label (if admin? :t/manage-members :t/add-members))]
[contact-list/contact-list {:icon :check
:group group
:added added
:search? true}]
[rn/view {:style style/bottom-container}
[quo2/button
{:style {:flex 1}
:on-press #(rf/dispatch [:bottom-sheet/hide])
:disabled (zero? (count @added))}
(i18n/label :t/save)]]]))])))
[rn/view {:style (style/bottom-container safe-area)}
[quo2/button {:style {:flex 1}
:accessibility-label :save
:on-press (fn []
(rf/dispatch [:group-chats.ui/add-members-pressed])
(js/setTimeout #(rf/dispatch [:group-chats.ui/remove-members-pressed]) 500)
(rf/dispatch [:bottom-sheet/hide]))
:disabled (and (zero? (count selected-participants)) (zero? (count deselected-members)))}
(i18n/label :t/save)]]]))])
(defn group-details
[]
(let [{:keys [admins chat-id chat-name color public? muted contacts] :as group} (rf/sub
[:chats/current-chat])
(defn group-details []
(let [{:keys [admins chat-id chat-name color public? muted contacts] :as group} (rf/sub [:chats/current-chat])
members (rf/sub [:contacts/group-members-sections])
pinned-messages (rf/sub [:chats/pinned chat-id])
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/view
{:style {:flex 1
[rn/view {:style {:flex 1
:background-color (colors/theme-colors colors/white colors/neutral-95)}}
[quo2/header
{:left-component [back-button]
[quo2/header {:left-component [back-button]
:right-component [options-button]
:background (colors/theme-colors colors/white colors/neutral-95)}]
[rn/view
{:style {:flex-direction :row
[rn/view {:style {:flex-direction :row
:margin-top 24
:padding-horizontal 20}}
[quo2/group-avatar
{:color color
[quo2/group-avatar {:color color
:size :medium}]
[quo2/text
{:weight :semi-bold
[quo2/text {:weight :semi-bold
:size :heading-1
:style {:margin-horizontal 8}} chat-name]
[rn/view {:style {:margin-top 8}}
[quo2/icon (if public? :i/world :i/privacy)
{:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[quo2/icon (if public? :i/world :i/privacy) {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]]]
[rn/view {:style (style/actions-view)}
[rn/touchable-opacity
{:style (style/action-container color)
[rn/touchable-opacity {:style (style/action-container color)
:accessibility-label :pinned-messages
:on-press (fn []
(rf/dispatch [:bottom-sheet/show-sheet :pinned-messages-list chat-id]))}
[rn/view
{:style {:flex-direction :row
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/pin {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count pinned-messages)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label :t/pinned-messages)]]
[rn/touchable-opacity
{:style (style/action-container color)
[count-container (count pinned-messages) :pinned-count]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label :t/pinned-messages)]]
[rn/touchable-opacity {:style (style/action-container color)
:accessibility-label :toggle-mute
:on-press #(rf/dispatch [::chat.models/mute-chat-toggled chat-id (not muted)])}
[quo2/icon (if muted :i/muted :i/activity-center)
{:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity
{:style (style/action-container color)
:on-press #(rf/dispatch
[quo2/icon (if muted :i/muted :i/activity-center) {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if muted :unmute-group :mute-group))]]
[rn/touchable-opacity {:style (style/action-container color)
:accessibility-label :manage-members
:on-press (fn []
(rf/dispatch [:group/clear-added-participants])
(rf/dispatch [:group/clear-removed-members])
(rf/dispatch
[:bottom-sheet/show-sheet
{:content (fn [] [contact-requests-sheet group])}])}
[rn/view
{:style {:flex-direction :row
{:content (fn [] [add-members-sheet group admin?])}]))}
[rn/view {:style {:flex-direction :row
:justify-content :space-between}}
[quo2/icon :i/add-user {:size 20 :color (colors/theme-colors colors/neutral-100 colors/white)}]
[count-container (count contacts)]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium}
(i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list
{:key-fn :title
[count-container (count contacts) :members-count]]
[quo2/text {:style {:margin-top 16} :size :paragraph-1 :weight :medium} (i18n/label (if admin? :t/manage-members :t/add-members))]]]
[rn/section-list {:key-fn :title
:sticky-section-headers-enabled false
:sections members
:render-section-header-fn contacts-section-header

View File

@ -1,21 +1,19 @@
(ns status-im.ui2.screens.common.contact-list.view
(:require [quo2.core :as quo]
[react-native.core :as rn]
(:require [react-native.core :as rn]
[status-im2.common.contact-list-item.view :as contact-list-item]
[utils.re-frame :as rf]))
[utils.re-frame :as rf]
[quo2.core :as quo]))
(defn contacts-section-header
[{:keys [title]}]
(defn contacts-section-header [{:keys [title]}]
[quo/divider-label {:label title}])
(defn contact-list
[data]
(let [contacts (rf/sub [:contacts/filtered-active-sections])]
(defn contact-list [data]
(let [contacts (if (:group data) (rf/sub [:contacts/add-members-sections]) (rf/sub [:contacts/filtered-active-sections]))]
[rn/section-list
{:key-fn :title
:sticky-section-headers-enabled false
:sections contacts
:render-section-header-fn contacts-section-header
:content-container-style {:padding-bottom 120}
:content-container-style {:padding-bottom 20}
:render-data data
:render-fn contact-list-item/contact-list-item}]))

View File

@ -1,15 +1,14 @@
(ns status-im2.common.contact-list-item.view
(:require [quo2.core :as quo]
[quo2.foundations.colors :as colors]
(:require [quo2.foundations.colors :as colors]
[status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.re-frame :as rf]
[status-im2.common.home.actions.view :as actions]
[quo2.core :as quo]
[react-native.core :as rn]
[react-native.platform :as platform]
[status-im2.common.home.actions.view :as actions]
[status-im2.contexts.chat.home.chat-list-item.style :as style]
[utils.address :as utils.address]
[utils.re-frame :as rf]))
[utils.address :as utils.address]))
(defn open-chat
[chat-id]
(defn open-chat [chat-id]
(let [view-id (rf/sub [:view-id])]
(when (= view-id :shell-stack)
(rf/dispatch [:dismiss-keyboard])
@ -18,44 +17,45 @@
(rf/dispatch [:chat.ui/navigate-to-chat chat-id]))
(rf/dispatch [:search/home-filter-changed nil]))))
(defn action-icon
[{:keys [public-key] :as item} {:keys [icon group added] :as extra-data}]
(let [{:keys [contacts]} group
member? (contains? contacts public-key)]
[rn/touchable-opacity
{:on-press #(rf/dispatch [:bottom-sheet/show-sheet
(defn action-icon [{:keys [public-key] :as item} {:keys [icon group] :as extra-data}]
(let [{:keys [contacts admins]} group
member? (contains? contacts public-key)
current-pk (rf/sub [:multiaccount/public-key])
admin? (get admins current-pk)]
[rn/touchable-opacity {:on-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item extra-data])}])
:style {:position :absolute
:right 20}}
(if (= icon :options)
[quo/icon :i/options {:size 20 :color (colors/theme-colors colors/neutral-50 colors/neutral-40)}]
[quo/checkbox
{:default-checked? member?
[quo/checkbox {:default-checked? member?
:accessibility-label :contact-toggle-check
:disabled? (and member? (not admin?))
:on-change (fn [selected]
(if-not member?
(if selected
(swap! added conj public-key)
(reset! added (remove #(= % public-key) @added))))}])]))
(rf/dispatch [:select-participant public-key true])
(rf/dispatch [:deselect-participant public-key true]))
(if selected
(rf/dispatch [:undo-deselect-member public-key true])
(rf/dispatch [:deselect-member public-key true]))))}])]))
(defn contact-list-item
[item _ _ extra-data]
(defn contact-list-item [item _ _ extra-data]
(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)
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])
online? (rf/sub [:visibility-status-updates/online? public-key])]
[rn/touchable-opacity (merge {:style (style/container)
:accessibility-label :contact
:active-opacity 1
:on-press #(open-chat public-key)
:on-long-press #(rf/dispatch [:bottom-sheet/show-sheet
{:content (fn [] [actions/actions item extra-data])}])})
[quo/user-avatar
{:full-name display-name
[quo/user-avatar {:full-name display-name
:profile-picture photo-path
:status-indicator? true
:online? true
:online? online?
:size :small
:ring? false}]
[rn/view {:style {:margin-left 8}}
@ -63,16 +63,11 @@
[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)}]]
[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
{:size :paragraph-1
[quo/icon :i/contact {:no-color true :size 12 :color (colors/theme-colors colors/primary-50 colors/primary-60)}]]))]
[quo/text {:size :paragraph-1
:style {:color (colors/theme-colors colors/neutral-50 colors/neutral-40)}}
(utils.address/get-shortened-address public-key)]]
(when-not (= current-pk public-key)

View File

@ -1,14 +1,14 @@
(ns status-im2.common.home.actions.view
(:require [i18n.i18n :as i18n]
[utils.re-frame :as rf]
[quo2.components.drawers.action-drawers :as drawer]
[status-im.chat.models :as chat.models]
[status-im2.common.confirmation-drawer.view :as confirmation-drawer] ;;TODO move to
;;status-im2
[status-im2.common.constants :as constants]
[utils.re-frame :as rf]))
[status-im2.common.confirmation-drawer.view :as confirmation-drawer]
(defn- entry
[{:keys [icon label on-press danger? sub-label chevron? add-divider?]}]
;;TODO move to status-im2
[status-im2.common.constants :as constants]
[status-im.chat.models :as chat.models]))
(defn- entry [{:keys [icon label on-press danger? sub-label chevron? add-divider? accessibility-label]}]
{:pre [(keyword? icon)
(string? label)
(fn? on-press)
@ -20,88 +20,67 @@
:danger? danger?
:sub-label sub-label
:right-icon (when chevron? :i/chevron-right)
:add-divider? add-divider?})
:add-divider? add-divider?
:accessibility-label accessibility-label})
(defn hide-sheet-and-dispatch
[event]
(defn hide-sheet-and-dispatch [event]
(rf/dispatch [:bottom-sheet/hide])
(rf/dispatch event))
(defn show-profile-action
[chat-id]
(defn show-profile-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/show-profile chat-id])
(rf/dispatch [:pin-message/load-pin-messages chat-id]))
(defn mark-all-read-action
[chat-id]
(defn mark-all-read-action [chat-id]
(hide-sheet-and-dispatch [:chat/mark-all-as-read chat-id]))
(defn edit-nickname-action
[chat-id]
(defn edit-nickname-action [chat-id]
(hide-sheet-and-dispatch [:chat.ui/edit-nickname chat-id]))
(defn mute-chat-action
[chat-id]
(defn mute-chat-action [chat-id]
(hide-sheet-and-dispatch [::chat.models/mute-chat-toggled chat-id true]))
(defn unmute-chat-action
[chat-id]
(defn unmute-chat-action [chat-id]
(hide-sheet-and-dispatch [::chat.models/mute-chat-toggled chat-id false]))
(defn clear-history-action
[{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch
[:bottom-sheet/show-sheet
(defn clear-history-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{: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)
:on-press #(hide-sheet-and-dispatch [:chat.ui/clear-history chat-id])}))}]))
(defn delete-chat-action
[{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch
[:bottom-sheet/show-sheet
(defn delete-chat-action [{:keys [chat-id] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{: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)
:on-press #(hide-sheet-and-dispatch [:chat.ui/remove-chat chat-id])}))}]))
(defn leave-group-action
[item chat-id]
(hide-sheet-and-dispatch
[:bottom-sheet/show-sheet
(defn leave-group-action [item chat-id]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{: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)
:on-press #(do
(rf/dispatch [:navigate-back])
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed
chat-id]))}))}]))
(hide-sheet-and-dispatch [:group-chats.ui/leave-chat-confirmed chat-id]))}))}]))
(defn block-user-action
[{:keys [public-key] :as item}]
(hide-sheet-and-dispatch
[:bottom-sheet/show-sheet
{:content (fn []
(confirmation-drawer/confirmation-drawer
{:title (i18n/label :t/block-user?)
(defn block-user-action [{:keys [public-key] :as item}]
(hide-sheet-and-dispatch [:bottom-sheet/show-sheet
{: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)
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed
public-key])}))}]))
:on-press #(hide-sheet-and-dispatch [:contact.ui/block-contact-confirmed public-key])}))}]))
(defn mute-chat-entry
[chat-id]
(defn mute-chat-entry [chat-id]
(let [muted? (rf/sub [:chats/muted chat-id])]
(entry {:icon (if muted? :i/muted :i/activity-center)
:label (i18n/label
@ -115,8 +94,7 @@
:sub-label nil
:chevron? true})))
(defn mark-as-read-entry
[chat-id]
(defn mark-as-read-entry [chat-id]
(entry {:icon :i/correct
:label (i18n/label :t/mark-as-read)
:on-press #(mark-all-read-action chat-id)
@ -125,8 +103,7 @@
:chevron? false
:add-divider? true}))
(defn clear-history-entry
[chat-id]
(defn clear-history-entry [chat-id]
(entry {:icon :i/delete
:label (i18n/label :t/clear-history)
:on-press #(clear-history-action chat-id)
@ -135,8 +112,7 @@
:chevron? false
:add-divider? true}))
(defn delete-chat-entry
[item]
(defn delete-chat-entry [item]
(entry {:icon :i/delete
:label (i18n/label :t/delete-chat)
:on-press #(delete-chat-action item)
@ -144,8 +120,7 @@
:sub-label nil
:chevron? false}))
(defn leave-group-entry
[item extra-data]
(defn leave-group-entry [item extra-data]
(entry {:icon :i/log-out
:label (i18n/label :t/leave-group)
:on-press #(leave-group-action item (if extra-data (:chat-id extra-data) (:chat-id item)))
@ -154,8 +129,7 @@
:chevron? false
:add-divider? extra-data}))
(defn view-profile-entry
[chat-id]
(defn view-profile-entry [chat-id]
(entry {:icon :i/friend
:label (i18n/label :t/view-profile)
:on-press #(show-profile-action chat-id)
@ -163,8 +137,7 @@
:sub-label nil
:chevron? false}))
(defn edit-nickname-entry
[chat-id]
(defn edit-nickname-entry [chat-id]
(entry {:icon :i/edit
:label (i18n/label :t/edit-nickname)
:on-press #(edit-nickname-action chat-id)
@ -173,8 +146,7 @@
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn edit-name-image-entry
[]
(defn edit-name-image-entry []
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -183,8 +155,7 @@
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn notifications-entry
[add-divider?]
(defn notifications-entry [add-divider?]
(entry {:icon :i/notifications
:label (i18n/label :t/notifications)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -194,8 +165,7 @@
:add-divider? add-divider?}))
;; TODO(OmarBasem): Requires design input.
(defn fetch-messages-entry
[]
(defn fetch-messages-entry []
(entry {:icon :i/save
:label (i18n/label :t/fetch-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -204,8 +174,7 @@
:chevron? true}))
;; TODO(OmarBasem): Requires design input.
(defn pinned-messages-entry
[]
(defn pinned-messages-entry []
(entry {:icon :i/pin
:label (i18n/label :t/pinned-messages)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -213,8 +182,7 @@
:sub-label nil
:chevron? true}))
(defn remove-from-contacts-entry
[contact]
(defn remove-from-contacts-entry [contact]
(entry {:icon :i/remove-user
:label (i18n/label :t/remove-from-contacts)
:on-press #(hide-sheet-and-dispatch [:contact.ui/remove-contact-pressed contact])
@ -223,8 +191,7 @@
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn rename-entry
[]
(defn rename-entry []
(entry {:icon :i/edit
:label (i18n/label :t/rename)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -233,8 +200,7 @@
:chevron? false}))
;; TODO(OmarBasem): Requires design input.
(defn show-qr-entry
[]
(defn show-qr-entry []
(entry {:icon :i/qr-code
:label (i18n/label :t/show-qr)
:on-press #(js/alert "TODO: to be implemented, requires design input")
@ -243,8 +209,7 @@
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-profile-entry
[]
(defn share-profile-entry []
(entry {:icon :i/share
:label (i18n/label :t/share-profile)
:on-press #(js/alert "TODO: to be implemented")
@ -253,8 +218,7 @@
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn share-group-entry
[]
(defn share-group-entry []
(entry {:icon :i/share
:label (i18n/label :t/share)
:on-press #(js/alert "TODO: to be implemented")
@ -263,8 +227,7 @@
:chevron? false}))
;; TODO(OmarBasem): Requires status-go impl.
(defn mark-untrustworthy-entry
[]
(defn mark-untrustworthy-entry []
(entry {:icon :i/alert
:label (i18n/label :t/mark-untrustworthy)
:on-press #(js/alert "TODO: to be implemented, requires status-go impl.")
@ -273,8 +236,7 @@
:chevron? false
:add-divider? true}))
(defn block-user-entry
[item]
(defn block-user-entry [item]
(entry {:icon :i/block
:label (i18n/label :t/block-user)
:on-press #(block-user-action item)
@ -282,30 +244,27 @@
:sub-label nil
:chevron? false}))
(defn remove-from-group-entry
[{:keys [public-key]} chat-id]
(defn remove-from-group-entry [{:keys [public-key]} chat-id]
(let [username (first (rf/sub [:contacts/contact-two-names-by-identity public-key]))]
(entry {:icon :i/placeholder
:label (i18n/label :t/remove-user-from-group {:username username})
:on-press #(hide-sheet-and-dispatch [:group-chats.ui/remove-member-pressed chat-id
public-key true])
:on-press #(hide-sheet-and-dispatch [:group-chats.ui/remove-member-pressed chat-id public-key true])
:danger? true
:sub-label nil
:chevron? false
:add-divider? true})))
(defn group-details-entry
[chat-id]
(defn group-details-entry [chat-id]
(entry {:icon :i/members
:label (i18n/label :t/group-details)
:accessibility-label :group-details
:on-press #(hide-sheet-and-dispatch [:show-group-chat-profile chat-id])
:danger? false
:sub-label nil
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn add-members-entry
[]
(defn add-members-entry []
(entry {:icon :i/add-user
:label (i18n/label :t/add-members)
:on-press #(js/alert "TODO: to be implemented")
@ -314,8 +273,7 @@
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn manage-members-entry
[]
(defn manage-members-entry []
(entry {:icon :i/add-user
:label (i18n/label :t/manage-members)
:on-press #(js/alert "TODO: to be implemented")
@ -324,8 +282,7 @@
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn edit-group-entry
[]
(defn edit-group-entry []
(entry {:icon :i/edit
:label (i18n/label :t/edit-name-and-image)
:on-press #(js/alert "TODO: to be implemented")
@ -334,8 +291,7 @@
:chevron? false}))
;; TODO(OmarBasem): to be implemented.
(defn group-privacy-entry
[]
(defn group-privacy-entry []
(entry {:icon :i/privacy
:label (i18n/label :t/change-group-privacy)
:on-press #(js/alert "TODO: to be implemented")
@ -343,15 +299,13 @@
:sub-label nil
:chevron? false}))
(defn destructive-actions
[{:keys [group-chat] :as item}]
(defn destructive-actions [{:keys [group-chat] :as item}]
[(clear-history-entry item)
(if group-chat
(leave-group-entry item nil)
(delete-chat-entry item))])
(defn notification-actions
[{:keys [chat-id group-chat public?]} inside-chat?]
(defn notification-actions [{:keys [chat-id group-chat public?]} inside-chat?]
[(mark-as-read-entry chat-id)
(mute-chat-entry chat-id)
(notifications-entry false)
@ -365,11 +319,12 @@
(when public?
(share-group-entry))])
(defn group-actions
[{:keys [chat-id admins]} inside-chat?]
(defn group-actions [{:keys [chat-id admins]} inside-chat?]
(let [current-pub-key (rf/sub [:multiaccount/public-key])
admin? (get admins current-pub-key)]
[(group-details-entry chat-id)
admin? (get admins current-pub-key)
removed? (rf/sub [:group-chat/removed-from-current-chat?])]
[(when-not removed?
(group-details-entry chat-id))
(when inside-chat?
(if admin?
(manage-members-entry)
@ -377,35 +332,27 @@
(when (and admin? inside-chat?) (edit-group-entry))
(when (and admin? inside-chat?) (group-privacy-entry))]))
(defn one-to-one-actions
[{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer
[[(view-profile-entry chat-id)
(defn one-to-one-actions [{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer [[(view-profile-entry chat-id)
(edit-nickname-entry chat-id)]
(notification-actions item inside-chat?)
(destructive-actions item)]])
(defn public-chat-actions
[{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer
[[(group-details-entry chat-id)
(defn public-chat-actions [{:keys [chat-id] :as item} inside-chat?]
[drawer/action-drawer [[(group-details-entry chat-id)
(when inside-chat?
(add-members-entry))]
(notification-actions item inside-chat?)
(destructive-actions item)]])
(defn private-group-chat-actions
[item inside-chat?]
[drawer/action-drawer
[(group-actions item inside-chat?)
(defn private-group-chat-actions [item inside-chat?]
[drawer/action-drawer [(group-actions item inside-chat?)
(notification-actions item inside-chat?)
(destructive-actions item)]])
(defn contact-actions
[{:keys [public-key] :as contact} {:keys [chat-id admin?] :as extra-data}]
(defn contact-actions [{:keys [public-key] :as contact} {:keys [chat-id admin?] :as extra-data}]
(let [current-pub-key (rf/sub [:multiaccount/public-key])]
[drawer/action-drawer
[[(view-profile-entry public-key)
[drawer/action-drawer [[(view-profile-entry public-key)
(remove-from-contacts-entry contact)
(rename-entry)
(show-qr-entry)
@ -417,8 +364,7 @@
(leave-group-entry contact extra-data)
(remove-from-group-entry contact chat-id))])]]))
(defn actions
[{:keys [chat-type] :as item} {:keys [inside-chat?] :as extra-data}]
(defn actions [{:keys [chat-type] :as item} {:keys [inside-chat?] :as extra-data}]
(case chat-type
constants/one-to-one-chat-type
[one-to-one-actions item inside-chat?]
@ -428,11 +374,9 @@
[private-group-chat-actions item inside-chat?]
[contact-actions item extra-data]))
(defn group-details-actions
[{:keys [admins] :as group}]
(defn group-details-actions [{:keys [admins] :as group}]
(let [current-pub-key (rf/sub [:multiaccount/public-key])
admin? (get admins current-pub-key)]
[drawer/action-drawer
[(when admin? [(edit-name-image-entry)])
[drawer/action-drawer [(when admin? [(edit-name-image-entry)])
[(notifications-entry admin?)]
(destructive-actions group)]]))

View File

@ -19,7 +19,7 @@
{:on-press #(rf/dispatch [:bottom-sheet/hide])
:style (style/contact-requests-sheet)}
[quo/icon :i/close]]
[rn/text {:size :heading-1 :weight :semi-bold}
[quo/text {:size :heading-1 :weight :semi-bold}
(i18n/label :t/pending-requests)]
[quo/tabs
{:style {:margin-top 12 :margin-bottom 20}

View File

@ -1,26 +1,27 @@
(ns status-im2.contexts.chat.messages.view
(:require [quo2.core :as quo]
(:require [reagent.core :as reagent]
[re-frame.db]
[i18n.i18n :as i18n]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im.ui2.screens.chat.composer.view :as composer]
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]
[status-im2.common.constants :as constants]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner] ;;TODO move to status-im2
[status-im2.navigation.state :as navigation.state]
[utils.re-frame :as rf]
[utils.debounce :as debounce]
[utils.re-frame :as rf]))
[quo2.core :as quo]
[status-im2.common.constants :as constants]
[status-im2.navigation.state :as navigation.state]
[status-im2.contexts.chat.messages.list.view :as messages.list]
[status-im2.contexts.chat.messages.pin.banner.view :as pin.banner]
(defn navigate-back-handler
[]
;;TODO move to status-im2
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]
[status-im.ui2.screens.chat.composer.view :as composer]))
(defn navigate-back-handler []
(when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat))
(rn/hw-back-remove-listener navigate-back-handler)
(rf/dispatch [:close-chat])
(rf/dispatch [:navigate-back])))
(defn page-nav
[]
(defn page-nav []
(let [{:keys [group-chat chat-id chat-name emoji chat-type]} (rf/sub [:chats/current-chat])
display-name (if (= chat-type constants/one-to-one-chat-type)
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
@ -55,15 +56,14 @@
:icon :i/options
:accessibility-label :options-button}]}]))
(defn chat-render
[]
(defn chat-render []
(let [;;we want to react only on these fields, do not use full chat map here
{:keys [chat-id show-input?] :as chat} (rf/sub [:chats/current-chat-chat-view])
show-input? (not (rf/sub [:group-chat/removed-from-current-chat?]))
{:keys [chat-id] :as chat} (rf/sub [:chats/current-chat-chat-view])
mutual-contact-requests-enabled? (rf/sub [:mutual-contact-requests/enabled?])]
[rn/keyboard-avoiding-view {:style {:flex 1}}
[page-nav]
;; TODO (flexsurfer) this should be in-app notification component in quo2
;; https://github.com/status-im/status-mobile/issues/14527
;; TODO (flexsurfer) this should be in-app notification component in quo2 https://github.com/status-im/status-mobile/issues/14527
[pin-limit-popover/pin-limit-popover chat-id]
[pin.banner/banner chat-id]
;;MESSAGES LIST
@ -74,10 +74,14 @@
:bottom-space 15}]
;;INPUT COMPOSER
(when show-input?
[composer/composer chat-id])]))
[composer/composer chat-id])
[quo/floating-shell-button
{:jump-to {:on-press #(rf/dispatch [:shell/navigate-to-jump-to])
:label (i18n/label :t/jump-to)}}
{:position :absolute
:bottom 117}]]))
(defn chat
[]
(defn chat []
(reagent/create-class
{:component-did-mount (fn []
(rn/hw-back-remove-listener navigate-back-handler)

View File

@ -1,12 +1,11 @@
(ns status-im2.contexts.quo-preview.avatars.group-avatar
(:require [quo2.components.avatars.group-avatar :as quo2]
[quo2.foundations.colors :as colors]
(:require [reagent.core :as reagent]
[react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
[status-im2.contexts.quo-preview.preview :as preview]
[quo2.foundations.colors :as colors]
[quo2.components.avatars.group-avatar :as quo2]))
(def descriptor
[{:label "Size"
(def descriptor [{:label "Size"
:key :size
:type :select
:options [{:key :small
@ -23,10 +22,9 @@
(fn [c]
{:key c
:value c})
(keys colors/customization))}])
["#ff0000" "#0000ff"])}]) ; TODO: this is temporary only. Issue: https://github.com/status-im/status-mobile/issues/14566
(defn cool-preview
[]
(defn cool-preview []
(let [state (reagent/atom {:theme :light
:color :purple
:size :small})]
@ -35,20 +33,16 @@
[rn/view {:padding-bottom 150}
[rn/view {:flex 1}
[preview/customizer state descriptor]]
[rn/view
{:padding-vertical 60
[rn/view {:padding-vertical 60
:flex-direction :row
:justify-content :center}
[quo2/group-avatar @state]]]])))
(defn preview-group-avatar
[]
[rn/view
{:background-color (colors/theme-colors colors/white
(defn preview-group-avatar []
[rn/view {:background-color (colors/theme-colors colors/white
colors/neutral-90)
:flex 1}
[rn/flat-list
{:flex 1
[rn/flat-list {:flex 1
:keyboardShouldPersistTaps :always
:header [cool-preview]
:key-fn str}]])

View File

@ -1,16 +1,18 @@
(ns status-im2.setup.db
(:require [react-native.core :as rn] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
(:require
[react-native.core :as rn]
;; TODO (14/11/22 flexsurfer move to status-im2 namespace
[status-im.fleet.core :as fleet]
[status-im.wallet.db :as wallet.db]))
;; initial state of app-db
(def app-db
{:contacts/contacts {}
(def app-db {:contacts/contacts {}
:pairing/installations {}
:group/selected-contacts #{}
:chats {}
:current-chat-id nil
:selected-participants #{}
:group-chat/selected-participants #{}
:group-chat/deselected-members #{}
:sync-state :done
:link-previews-whitelist []
:app-state "active"

View File

@ -1,18 +1,18 @@
(ns status-im2.subs.chat.chats
(:require [clojure.string :as string]
(:require [re-frame.core :as re-frame]
[clojure.string :as string]
[status-im2.common.constants :as constants]
[quo.design-system.colors :as colors]
[re-frame.core :as re-frame]
[status-im.add-new.db :as db]
[status-im.chat.models :as chat.models]
[status-im.chat.models.mentions :as mentions]
[status-im.communities.core :as communities]
[status-im.group-chats.core :as group-chat]
[status-im.group-chats.db :as group-chats.db]
[status-im.i18n.i18n :as i18n]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.config :as config]
[status-im.utils.image-server :as image-server]
[status-im2.common.constants :as constants]))
[status-im.multiaccounts.core :as multiaccounts]
[status-im.group-chats.core :as group-chat]
[status-im.chat.models.mentions :as mentions]
[status-im.group-chats.db :as group-chats.db]
[status-im.utils.config :as config]
[status-im.add-new.db :as db]
[status-im.i18n.i18n :as i18n]))
(re-frame/reg-sub
:chats/chat
@ -36,9 +36,7 @@
[(re-frame/subscribe [:chats/by-community-id community-id])
(re-frame/subscribe [:communities/community-chats community-id])])
(fn [[chats comm-chats] [_ community-id]]
(filter #(string/blank? (get-in comm-chats
[(string/replace (:chat-id %) community-id "") :categoryID]))
chats)))
(filter #(string/blank? (get-in comm-chats [(string/replace (:chat-id %) community-id "") :categoryID])) chats)))
(re-frame/reg-sub
:chats/sorted-categories-by-community-id
@ -46,13 +44,11 @@
[(re-frame/subscribe [:chats/by-community-id community-id])
(re-frame/subscribe [:communities/community-chats community-id])])
(fn [[chats comm-chats] [_ community-id]]
(let [chat-cat (into {}
(map (fn [{:keys [id categoryID position]}]
(let [chat-cat (into {} (map (fn [{:keys [id categoryID position]}]
{(str community-id id) {:categoryID categoryID
:position position}})
(vals comm-chats)))]
(group-by :categoryID
(sort-by :position
(group-by :categoryID (sort-by :position
(map #(cond-> (merge % (chat-cat (:chat-id %)))
(= community-id constants/status-community-id)
(assoc :color colors/blue))
@ -167,8 +163,7 @@
:<- [:contacts/contacts]
:<- [:chat/inputs]
:<- [:mutual-contact-requests/enabled?]
(fn [[{:keys [group-chat chat-id] :as current-chat} my-public-key community blocked-users-set contacts
inputs mutual-contact-requests-enabled?]]
(fn [[{:keys [group-chat chat-id] :as current-chat} my-public-key community blocked-users-set contacts inputs mutual-contact-requests-enabled?]]
(when current-chat
(cond-> current-chat
(chat.models/public-chat? current-chat)
@ -198,9 +193,7 @@
:chats/current-chat-chat-view
:<- [:chats/current-chat]
(fn [current-chat]
(select-keys current-chat
[:chat-id :show-input? :group-chat :admins :invitation-admin :public? :chat-type :color
:chat-name :synced-to :synced-from :community-id :emoji])))
(select-keys current-chat [:chat-id :show-input? :group-chat :admins :invitation-admin :public? :chat-type :color :chat-name :synced-to :synced-from :community-id :emoji])))
(re-frame/reg-sub
:current-chat/metadata
@ -305,8 +298,7 @@
:<- [:chats/reply-message]
:<- [:chats/edit-message]
:<- [:chats/sending-contact-request]
(fn [[{:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply edit
sending-contact-request]]
(fn [[{:keys [processing]} sending-image mainnet? one-to-one-chat? {:keys [public?]} reply edit sending-contact-request]]
(let [sending-image (seq sending-image)]
{:send (not processing)
:stickers (and (or config/stickers-test-enabled? mainnet?)
@ -349,13 +341,12 @@
(count (filter-selected-contacts selected-contacts contacts))))
(re-frame/reg-sub
:selected-participants-count
:<- [:selected-participants]
:group-chat/selected-participants-count
:<- [:group-chat/selected-participants]
(fn [selected-participants]
(count selected-participants)))
(defn filter-contacts
[selected-contacts active-contacts]
(defn filter-contacts [selected-contacts active-contacts]
(filter #(selected-contacts (:public-key %)) active-contacts))
(re-frame/reg-sub
@ -403,10 +394,7 @@
(fn [[{:keys [users community-id] :as chat} blocked all-contacts
{:keys [public-key] :as current-multiaccount}]]
(let [community-members @(re-frame/subscribe [:communities/community-members community-id])
mentionable-users (mentions/get-mentionable-users chat
all-contacts
current-multiaccount
community-members)
mentionable-users (mentions/get-mentionable-users chat all-contacts current-multiaccount community-members)
members-left (into #{} (filter #(group-chat/member-removed? chat %) (keys users)))]
(apply dissoc mentionable-users (conj (concat blocked members-left) public-key)))))

View File

@ -1,13 +1,15 @@
(ns status-im2.subs.contact
(:require [clojure.string :as string]
[i18n.i18n :as i18n]
[re-frame.core :as re-frame]
(:require [re-frame.core :as re-frame]
[status-im.contact.db :as contact.db]
[status-im.ethereum.core :as ethereum]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.image-server :as image-server]
[status-im.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[status-im.multiaccounts.core :as multiaccounts]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.image-server :as image-server]))
[status-im.ethereum.core :as ethereum]
[clojure.string :as string]
[utils.collection]
[i18n.i18n :as i18n]
[utils.re-frame :as rf]))
(re-frame/reg-sub
::query-current-chat-contacts
@ -34,26 +36,19 @@
(fn [multiaccount]
(get multiaccount :profile-pictures-visibility)))
(defn- replace-contact-image-uri
[contact port identity]
(defn- replace-contact-image-uri [contact port identity]
(let [identicon (image-server/get-identicons-uri port identity)
contact-images (:images contact)
contact-images (reduce (fn [acc image]
(let [image-name (:type image)
; We pass the clock so that we reload the image if the image is
; updated
contact-images (reduce (fn [acc image] (let [image-name (:type image)
; We pass the clock so that we reload the image if the image is updated
clock (:clock image)
uri (image-server/get-contact-image-uri port
identity
image-name
clock)]
uri (image-server/get-contact-image-uri port identity image-name clock)]
(assoc-in acc [(keyword image-name) :uri] uri)))
contact-images
(vals contact-images))]
(assoc contact :identicon identicon :images contact-images)))
(defn- reduce-contacts-image-uri
[contacts port]
(defn- reduce-contacts-image-uri [contacts port]
(reduce-kv (fn [acc public-key contact]
(let [contact (replace-contact-image-uri contact port public-key)]
(assoc acc public-key contact)))
@ -91,6 +86,22 @@
sort
vals)))
(re-frame/reg-sub
:contacts/add-members-sections
:<- [:contacts/current-chat-contacts]
:<- [:contacts/active]
(fn [[members 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]}))))
{}
(utils.collection/distinct-by :public-key (concat members contacts)))
sort
vals)))
(re-frame/reg-sub
:contacts/sorted-contacts
:<- [:contacts/active]
@ -143,8 +154,7 @@
(string/lower-case search-filter))
contacts)))))
(defn- enrich-contact
[_ identity ens-name port]
(defn- enrich-contact [_ identity ens-name port]
(let [contact (contact.db/enrich-contact
(contact.db/public-key-and-ens-name->new-contact identity ens-name))]
(replace-contact-image-uri contact port identity)))
@ -187,8 +197,7 @@
[(re-frame/subscribe [:contacts/contact-by-identity identity])
(re-frame/subscribe [:multiaccount])])
(fn [[contact current-multiaccount] [_ identity]]
(multiaccounts/contact-two-names-by-identity contact
current-multiaccount
(multiaccounts/contact-two-names-by-identity contact current-multiaccount
identity)))
(re-frame/reg-sub
@ -272,9 +281,7 @@
contacts
(->> contacts
(map (fn [item]
(update item
:data
(fn [data]
(update item :data (fn [data]
(filter #(string/includes?
(string/lower-case (:alias %))
(string/lower-case query))
@ -286,12 +293,13 @@
:<- [:contacts/current-chat-contacts]
(fn [members]
(let [admins (filter :admin? members)
online (filter #(and (not (:admin? %)) (:online? %)) members)
offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
online (filter #(let [online (rf/sub [:visibility-status-updates/online? (:public-key %)])]
(and (not (:admin? %)) online)) members)
offline (filter #(let [online (rf/sub [:visibility-status-updates/online? (:public-key %)])]
(and (not (:admin? %)) (not online))) members)]
(vals (cond-> {}
(seq admins) (assoc :owner {:title (i18n/label :t/owner) :data admins})
(seq online) (assoc :online {:title (i18n/label :t/online) :data online})
(seq offline) (assoc :offline {:title (i18n/label :t/offline) :data offline}))))))

View File

@ -217,7 +217,7 @@
(re-frame/reg-sub
:is-participant-selected?
:<- [:selected-participants]
:<- [:group-chat/selected-participants]
(fn [selected-participants [_ element]]
(-> selected-participants
(contains? element))))

View File

@ -98,7 +98,8 @@
(reg-root-key-sub :new-chat-name :new-chat-name)
(reg-root-key-sub :group-chat-profile/editing? :group-chat-profile/editing?)
(reg-root-key-sub :group-chat-profile/profile :group-chat-profile/profile)
(reg-root-key-sub :selected-participants :selected-participants)
(reg-root-key-sub :group-chat/selected-participants :group-chat/selected-participants)
(reg-root-key-sub :group-chat/deselected-members :group-chat/deselected-members)
(reg-root-key-sub :chat/inputs :chat/inputs)
(reg-root-key-sub :chat/memberships :chat/memberships)
(reg-root-key-sub :camera-roll/photos :camera-roll/photos)

View File

@ -14,3 +14,9 @@
Similar to group-by except that the map values are single objects (depends on key uniqueness)."
[key coll]
(into {} (map #(vector (key %) %) coll)))
(defn distinct-by
"Given a key and a collection returns a unique collection by that key"
[key coll]
(let [groups (group-by key coll)]
(map #(first (groups %)) (distinct (map key coll)))))

View File

@ -1912,5 +1912,6 @@
"instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”",
"show-existing-keys": "Show Existing Keys",
"scan-sync-code": "Scan Sync Code",
"confirm-selection": "Confirm selection"
"confirm-selection": "Confirm selection",
"online": "Online"
}