Revert "Group details screen (3) (#14494)"

This reverts commit e21b8d43963532f23eab4d09ae0e490f25c0e05f.
This commit is contained in:
andrey 2022-12-23 07:32:23 +01:00
parent e21b8d4396
commit 8ff32f4fc3
No known key found for this signature in database
GPG Key ID: C20F2FDE9A98BA61
18 changed files with 1311 additions and 1206 deletions

View File

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

View File

@ -37,26 +37,17 @@
{:events [:group-chats.ui/remove-member-pressed]} {:events [:group-chats.ui/remove-member-pressed]}
[_ chat-id member do-not-navigate?] [_ chat-id member do-not-navigate?]
{:json-rpc/call [{:method "wakuext_removeMemberFromGroupChat" {:json-rpc/call [{:method "wakuext_removeMemberFromGroupChat"
:params [nil chat-id member] :params [nil chat-id member]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated % true])}]}) :on-success #(re-frame/dispatch [:chat-updated % do-not-navigate?])}]})
(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 (fx/defn join-chat
{:events [:group-chats.ui/join-pressed]} {:events [:group-chats.ui/join-pressed]}
[_ chat-id] [_ chat-id]
{:json-rpc/call [{:method "wakuext_confirmJoiningGroup" {:json-rpc/call [{:method "wakuext_confirmJoiningGroup"
:params [chat-id] :params [chat-id]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn create (fx/defn create
{:events [:group-chats.ui/create-pressed] {:events [:group-chats.ui/create-pressed]
@ -64,54 +55,54 @@
[{:keys [db] :as cofx} group-name] [{:keys [db] :as cofx} group-name]
(let [selected-contacts (:group/selected-contacts db)] (let [selected-contacts (:group/selected-contacts db)]
{:json-rpc/call [{:method "wakuext_createGroupChatWithMembers" {:json-rpc/call [{:method "wakuext_createGroupChatWithMembers"
:params [nil group-name (into [] selected-contacts)] :params [nil group-name (into [] selected-contacts)]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn create-from-link (fx/defn create-from-link
[cofx {:keys [chat-id invitation-admin chat-name]}] [cofx {:keys [chat-id invitation-admin chat-name]}]
(if (get-in cofx [:db :chats chat-id]) (if (get-in cofx [:db :chats chat-id])
{:dispatch [:chat.ui/navigate-to-chat chat-id]} {:dispatch [:chat.ui/navigate-to-chat chat-id]}
{:json-rpc/call [{:method "wakuext_createGroupChatFromInvitation" {:json-rpc/call [{:method "wakuext_createGroupChatFromInvitation"
:params [chat-name chat-id invitation-admin] :params [chat-name chat-id invitation-admin]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn make-admin (fx/defn make-admin
{:events [:group-chats.ui/make-admin-pressed]} {:events [:group-chats.ui/make-admin-pressed]}
[_ chat-id member] [_ chat-id member]
{:json-rpc/call [{:method "wakuext_addAdminsToGroupChat" {:json-rpc/call [{:method "wakuext_addAdminsToGroupChat"
:params [nil chat-id [member]] :params [nil chat-id [member]]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn add-members (fx/defn add-members
"Add members to a group chat" "Add members to a group chat"
{:events [:group-chats.ui/add-members-pressed]} {:events [:group-chats.ui/add-members-pressed]}
[{{:keys [current-chat-id] :group-chat/keys [selected-participants]} :db :as cofx}] [{{:keys [current-chat-id selected-participants]} :db :as cofx}]
{:json-rpc/call [{:method "wakuext_addMembersToGroupChat" {:json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil current-chat-id selected-participants] :params [nil current-chat-id selected-participants]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated % true])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn add-members-from-invitation (fx/defn add-members-from-invitation
"Add members to a group chat" "Add members to a group chat"
{:events [:group-chats.ui/add-members-from-invitation]} {:events [:group-chats.ui/add-members-from-invitation]}
[{{:keys [current-chat-id] :as db} :db :as cofx} id participant] [{{:keys [current-chat-id] :as db} :db :as cofx} id participant]
{:db (assoc-in db [:group-chat/invitations id :state] constants/invitation-state-approved) {:db (assoc-in db [:group-chat/invitations id :state] constants/invitation-state-approved)
:json-rpc/call [{:method "wakuext_addMembersToGroupChat" :json-rpc/call [{:method "wakuext_addMembersToGroupChat"
:params [nil current-chat-id [participant]] :params [nil current-chat-id [participant]]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]}) :on-success #(re-frame/dispatch [:chat-updated %])}]})
(fx/defn leave (fx/defn leave
"Leave chat" "Leave chat"
{:events [:group-chats.ui/leave-chat-confirmed]} {:events [:group-chats.ui/leave-chat-confirmed]}
[{:keys [db] :as cofx} chat-id] [{:keys [db] :as cofx} chat-id]
{:json-rpc/call [{:method "wakuext_leaveGroupChat" {:json-rpc/call [{:method "wakuext_leaveGroupChat"
:params [nil chat-id true] :params [nil chat-id true]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-removed %])}]}) :on-success #(re-frame/dispatch [:chat-removed %])}]})
(fx/defn remove (fx/defn remove
"Remove chat" "Remove chat"
@ -133,11 +124,11 @@
{:events [:group-chats.ui/name-changed]} {:events [:group-chats.ui/name-changed]}
[{:keys [db] :as cofx} chat-id new-name] [{:keys [db] :as cofx} chat-id new-name]
(when (valid-name? new-name) (when (valid-name? new-name)
{:db (assoc-in db [:chats chat-id :name] new-name) {:db (assoc-in db [:chats chat-id :name] new-name)
:json-rpc/call [{:method "wakuext_changeGroupChatName" :json-rpc/call [{:method "wakuext_changeGroupChatName"
:params [nil chat-id new-name] :params [nil chat-id new-name]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:chat-updated %])}]})) :on-success #(re-frame/dispatch [:chat-updated %])}]}))
(fx/defn membership-retry (fx/defn membership-retry
{:events [:group-chats.ui/membership-retry]} {:events [:group-chats.ui/membership-retry]}
@ -155,20 +146,20 @@
[{{:keys [current-chat-id chats] :as db} :db :as cofx}] [{{:keys [current-chat-id chats] :as db} :db :as cofx}]
(let [{:keys [invitation-admin]} (get chats current-chat-id) (let [{:keys [invitation-admin]} (get chats current-chat-id)
message (get-in db [:chat/memberships current-chat-id :message])] message (get-in db [:chat/memberships current-chat-id :message])]
{:db (assoc-in db [:chat/memberships current-chat-id] nil) {:db (assoc-in db [:chat/memberships current-chat-id] nil)
:json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest" :json-rpc/call [{:method "wakuext_sendGroupChatInvitationRequest"
:params [nil current-chat-id invitation-admin message] :params [nil current-chat-id invitation-admin message]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})) :on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}))
(fx/defn send-group-chat-membership-rejection (fx/defn send-group-chat-membership-rejection
"Send group chat membership rejection" "Send group chat membership rejection"
{:events [:send-group-chat-membership-rejection]} {:events [:send-group-chat-membership-rejection]}
[cofx invitation-id] [cofx invitation-id]
{:json-rpc/call [{:method "wakuext_sendGroupChatInvitationRejection" {:json-rpc/call [{:method "wakuext_sendGroupChatInvitationRejection"
:params [nil invitation-id] :params [nil invitation-id]
:js-response true :js-response true
:on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]}) :on-success #(re-frame/dispatch [:sanitize-messages-and-process-response %])}]})
(fx/defn handle-invitations (fx/defn handle-invitations
[{db :db} invitations] [{db :db} invitations]
@ -188,16 +179,6 @@
:type :type
(= constants/invitation-state-removed))) (= 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 (fx/defn deselect-contact
{:events [:deselect-contact]} {:events [:deselect-contact]}
[{:keys [db]} id] [{:keys [db]} id]
@ -211,22 +192,17 @@
(fx/defn deselect-participant (fx/defn deselect-participant
{:events [:deselect-participant]} {:events [:deselect-participant]}
[{:keys [db]} id] [{:keys [db]} id]
{:db (update db :group-chat/selected-participants disj id)}) {:db (update db :selected-participants disj id)})
(fx/defn select-participant (fx/defn select-participant
{:events [:select-participant]} {:events [:select-participant]}
[{:keys [db]} id] [{:keys [db]} id]
{:db (update db :group-chat/selected-participants conj id)}) {:db (update db :selected-participants conj id)})
(fx/defn clear-added-participants (fx/defn add-participants-toggle-list
{:events [:group/clear-added-participants]} {:events [:group/add-participants-toggle-list]}
[{db :db}] [{db :db}]
{:db (assoc db :group-chat/selected-participants #{})}) {:db (assoc db :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 (fx/defn show-group-chat-profile
{:events [:show-group-chat-profile]} {:events [:show-group-chat-profile]}

View File

@ -1,26 +1,25 @@
(ns status-im.ui.screens.group.views (ns status-im.ui.screens.group.views
(:require [clojure.string :as string] (:require [clojure.string :as string]
[quo.core :as quo]
[re-frame.core :as re-frame] [re-frame.core :as re-frame]
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.constants :as constants] [status-im.constants :as constants]
[status-im.i18n.i18n :as i18n] [status-im.i18n.i18n :as i18n]
[status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.multiaccounts.core :as multiaccounts] [status-im.multiaccounts.core :as multiaccounts]
[status-im.ui.components.keyboard-avoid-presentation [status-im.ui.components.chat-icon.screen :as chat-icon]
:as
kb-presentation]
[status-im.ui.components.invite.views :as invite] [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.list.views :as list]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.search-input.view :as search] [status-im.ui.components.search-input.view :as search]
[status-im.ui.components.toolbar :as toolbar] [status-im.ui.components.toolbar :as toolbar]
[status-im.ui.components.topbar :as topbar] [status-im.ui.components.topbar :as topbar]
[status-im.ui.screens.group.styles :as styles] [status-im.ui.screens.group.styles :as styles]
[quo.core :as quo]
[utils.debounce :as debounce]) [utils.debounce :as debounce])
(:require-macros [status-im.utils.views :as views])) (: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)] (let [[first-name second-name] (multiaccounts/contact-two-names row false)]
[quo/list-item [quo/list-item
{:title first-name {:title first-name
@ -28,7 +27,8 @@
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo row)]}])) (multiaccounts/displayed-photo row)]}]))
(defn- on-toggle [allow-new-users? checked? public-key] (defn- on-toggle
[allow-new-users? checked? public-key]
(cond (cond
checked? checked?
@ -39,7 +39,8 @@
allow-new-users?) allow-new-users?)
(re-frame/dispatch [:select-contact public-key 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 (cond
checked? checked?
@ -50,196 +51,229 @@
allow-new-users?) allow-new-users?)
(re-frame/dispatch [:select-participant public-key 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] (fn [allow-new-users? subs-name {:keys [public-key] :as contact} on-toggle]
(let [contact-selected? @(re-frame/subscribe [subs-name public-key]) (let [contact-selected? @(re-frame/subscribe [subs-name public-key])
[first-name second-name] (multiaccounts/contact-two-names contact true)] [first-name second-name] (multiaccounts/contact-two-names contact true)]
[quo/list-item [quo/list-item
{:title first-name {:title first-name
:subtitle second-name :subtitle second-name
:icon [chat-icon/contact-icon-contacts-tab :icon [chat-icon/contact-icon-contacts-tab
(multiaccounts/displayed-photo contact)] (multiaccounts/displayed-photo contact)]
:on-press #(on-toggle allow-new-users? contact-selected? public-key) :on-press #(on-toggle allow-new-users? contact-selected? public-key)
:active contact-selected? :active contact-selected?
:accessory :checkbox}]))) :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]) [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]) [toggle-item allow-new-users? :is-participant-selected? contact on-toggle-participant])
(defn toggle-list [{:keys [contacts render-fn render-data]}] (defn toggle-list
[list/flat-list {:data contacts [{:keys [contacts render-fn render-data]}]
:key-fn :public-key [list/flat-list
:render-data render-data {:data contacts
:render-fn render-fn :key-fn :public-key
:keyboardShouldPersistTaps :always}]) :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/view {:style styles/no-contacts}
[react/text [react/text
{:style (styles/no-contact-text)} {:style (styles/no-contact-text)}
no-contacts] no-contacts]
[invite/button]]) [invite/button]])
(defn filter-contacts [filter-text contacts] (defn filter-contacts
[filter-text contacts]
(let [lower-filter-text (string/lower-case (str filter-text)) (let [lower-filter-text (string/lower-case (str filter-text))
filter-fn (fn [{:keys [name alias nickname]}] filter-fn (fn [{:keys [name alias nickname]}]
(or (or
(string/includes? (string/lower-case (str name)) lower-filter-text) (string/includes? (string/lower-case (str name)) lower-filter-text)
(string/includes? (string/lower-case (str alias)) lower-filter-text) (string/includes? (string/lower-case (str alias)) lower-filter-text)
(when nickname (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 (if filter-text
(filter filter-fn contacts) (filter filter-fn contacts)
contacts))) contacts)))
;; Set name of new group-chat ;; 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]] (views/letsubs [contacts [:selected-group-contacts]
(let [group-name-empty? (not (and (string? group-name) (not-empty group-name)))] group-name [:new-chat-name]]
[react/keyboard-avoiding-view {:style styles/group-container (let [group-name-empty? (not (and (string? group-name) (not-empty group-name)))]
:ignore-offset true} [react/keyboard-avoiding-view
[react/view {:flex 1} {:style styles/group-container
[topbar/topbar {:use-insets false :ignore-offset true}
:title (i18n/label :t/new-group-chat) [react/view {:flex 1}
:subtitle (i18n/label :t/group-chat-members-count [topbar/topbar
{:selected (inc (count contacts)) {:use-insets false
:max constants/max-group-chat-participants})}] :title (i18n/label :t/new-group-chat)
[react/view {:style {:padding-top 16 :subtitle (i18n/label :t/group-chat-members-count
:flex 1}} {:selected (inc (count contacts))
[react/view {:style {:padding-horizontal 16}} :max constants/max-group-chat-participants})}]
[quo/text-input [react/view
{:auto-focus true {:style {:padding-top 16
:on-change-text #(re-frame/dispatch [:set :new-chat-name %]) :flex 1}}
:default-value group-name [react/view {:style {:padding-horizontal 16}}
:placeholder (i18n/label :t/set-a-topic) [quo/text-input
:accessibility-label :chat-name-input}] {:auto-focus true
[react/text {:style (styles/members-title)} :on-change-text #(re-frame/dispatch [:set :new-chat-name %])
(i18n/label :t/members-title)]] :default-value group-name
[react/view {:style {:margin-top 8 :placeholder (i18n/label :t/set-a-topic)
:flex 1}} :accessibility-label :chat-name-input}]
[list/flat-list {:data contacts [react/text {:style (styles/members-title)}
:key-fn :address (i18n/label :t/members-title)]]
:render-fn render-contact [react/view
:bounces false {:style {:margin-top 8
:keyboard-should-persist-taps :always :flex 1}}
:enable-empty-sections true}]]] [list/flat-list
[toolbar/toolbar {:data contacts
{:show-border? true :key-fn :address
:left :render-fn render-contact
[quo/button {:type :secondary :bounces false
:before :main-icon/back :keyboard-should-persist-taps :always
:accessibility-label :previous-button :enable-empty-sections true}]]]
:on-press #(re-frame/dispatch [:navigate-back])} [toolbar/toolbar
(i18n/label :t/back)] {:show-border? true
:right :left
[quo/button {:type :secondary [quo/button
:accessibility-label :create-group-chat-button {:type :secondary
:disabled group-name-empty? :before :main-icon/back
:on-press #(debounce/dispatch-and-chill [:group-chats.ui/create-pressed group-name] :accessibility-label :previous-button
300)} :on-press #(re-frame/dispatch [:navigate-back])}
(i18n/label :t/create-group-chat)]}]]]))) (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 [] (defn searchable-contact-list
[]
(let [search-value (reagent/atom nil)] (let [search-value (reagent/atom nil)]
(fn [{:keys [contacts no-contacts-label toggle-fn allow-new-users?]}] (fn [{:keys [contacts no-contacts-label toggle-fn allow-new-users?]}]
[react/view {:style {:flex 1}} [react/view {:style {:flex 1}}
[react/view {:style (styles/search-container)} [react/view {:style (styles/search-container)}
[search/search-input-old {:on-cancel #(reset! search-value nil) [search/search-input-old
:on-change #(reset! search-value %)}]] {:on-cancel #(reset! search-value nil)
[react/view {:style {:flex 1 :on-change #(reset! search-value %)}]]
:padding-vertical 8}} [react/view
{:style {:flex 1
:padding-vertical 8}}
(if (seq contacts) (if (seq contacts)
[toggle-list {:contacts (filter-contacts @search-value contacts) [toggle-list
:render-data allow-new-users? {:contacts (filter-contacts @search-value contacts)
:render-fn toggle-fn}] :render-data allow-new-users?
:render-fn toggle-fn}]
[no-contacts {:no-contacts no-contacts-label}])]]))) [no-contacts {:no-contacts no-contacts-label}])]])))
;; Start group chat ;; Start group chat
(views/defview contact-toggle-list [] (views/defview contact-toggle-list
(views/letsubs [contacts [:contacts/active] []
selected-contacts-count [:selected-contacts-count]] (views/letsubs [contacts [:contacts/active]
[react/keyboard-avoiding-view {:style styles/group-container selected-contacts-count [:selected-contacts-count]]
:ignore-offset true} [react/keyboard-avoiding-view
[topbar/topbar {:use-insets false {:style styles/group-container
:border-bottom false :ignore-offset true}
:title (i18n/label :t/new-group-chat) [topbar/topbar
:subtitle (i18n/label :t/group-chat-members-count {:use-insets false
{:selected (inc selected-contacts-count) :border-bottom false
:max constants/max-group-chat-participants})}] :title (i18n/label :t/new-group-chat)
[searchable-contact-list :subtitle (i18n/label :t/group-chat-members-count
{:contacts contacts {:selected (inc selected-contacts-count)
:no-contacts-label (i18n/label :t/group-chat-no-contacts) :max constants/max-group-chat-participants})}]
:toggle-fn group-toggle-contact [searchable-contact-list
:allow-new-users? (< selected-contacts-count {:contacts contacts
(dec constants/max-group-chat-participants))}] :no-contacts-label (i18n/label :t/group-chat-no-contacts)
[toolbar/toolbar :toggle-fn group-toggle-contact
{:show-border? true :allow-new-users? (< selected-contacts-count
:right (dec constants/max-group-chat-participants))}]
[quo/button {:type :secondary [toolbar/toolbar
:after :main-icon/next {:show-border? true
:accessibility-label :next-button :right
:on-press #(re-frame/dispatch [:navigate-to :new-group])} [quo/button
(i18n/label :t/next)]}]])) {: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 ;; 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] (views/letsubs [contacts [:contacts/all-contacts-not-in-current-chat]
selected-contacts-count [:group-chat/selected-participants-count]] current-chat [:chats/current-chat]
(let [current-participants-count (count (:contacts current-chat))] selected-contacts-count [:selected-participants-count]]
[kb-presentation/keyboard-avoiding-view {:style styles/group-container} (let [current-participants-count (count (:contacts current-chat))]
[topbar/topbar {:use-insets false [kb-presentation/keyboard-avoiding-view {:style styles/group-container}
:border-bottom false [topbar/topbar
:title (i18n/label :t/add-members) {:use-insets false
:subtitle (i18n/label :t/group-chat-members-count :border-bottom false
{:selected (+ current-participants-count selected-contacts-count) :title (i18n/label :t/add-members)
:max constants/max-group-chat-participants})}] :subtitle (i18n/label :t/group-chat-members-count
[searchable-contact-list {:selected (+ current-participants-count selected-contacts-count)
{:contacts contacts :max constants/max-group-chat-participants})}]
:no-contacts-label (i18n/label :t/group-chat-all-contacts-invited) [searchable-contact-list
:toggle-fn group-toggle-participant {:contacts contacts
:allow-new-users? (< (+ current-participants-count :no-contacts-label (i18n/label :t/group-chat-all-contacts-invited)
selected-contacts-count) :toggle-fn group-toggle-participant
constants/max-group-chat-participants)}] :allow-new-users? (< (+ current-participants-count
[toolbar/toolbar selected-contacts-count)
{:show-border? true constants/max-group-chat-participants)}]
:center [toolbar/toolbar
[quo/button {:type :secondary {:show-border? true
:accessibility-label :next-button :center
:disabled (zero? selected-contacts-count) [quo/button
:on-press #(re-frame/dispatch [:group-chats.ui/add-members-pressed])} {:type :secondary
(i18n/label :t/add)]}]]))) :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)] (views/letsubs [{:keys [name chat-id]} [:chats/current-chat]
[kb-presentation/keyboard-avoiding-view {:style styles/group-container} new-group-chat-name (reagent/atom nil)]
[react/scroll-view {:style {:padding 16 [kb-presentation/keyboard-avoiding-view {:style styles/group-container}
:flex 1}} [react/scroll-view
[quo/text-input {:style {:padding 16
{:on-change-text #(reset! new-group-chat-name %) :flex 1}}
:default-value name [quo/text-input
:on-submit-editing #(when (seq @new-group-chat-name) {:on-change-text #(reset! new-group-chat-name %)
(re-frame/dispatch [:group-chats.ui/name-changed chat-id @new-group-chat-name])) :default-value name
:placeholder (i18n/label :t/enter-contact-code) :on-submit-editing #(when (seq @new-group-chat-name)
:accessibility-label :new-chat-name (re-frame/dispatch [:group-chats.ui/name-changed chat-id
:return-key-type :go}]] @new-group-chat-name]))
[react/view {:style {:flex 1}}] :placeholder (i18n/label :t/enter-contact-code)
[toolbar/toolbar :accessibility-label :new-chat-name
{:show-border? true :return-key-type :go}]]
:center [react/view {:style {:flex 1}}]
[quo/button {:type :secondary [toolbar/toolbar
:accessibility-label :done {:show-border? true
:disabled (and (<= (count @new-group-chat-name) 1) :center
(not (nil? @new-group-chat-name))) [quo/button
:on-press #(cond {:type :secondary
(< 1 (count @new-group-chat-name)) :accessibility-label :done
(re-frame/dispatch [:group-chats.ui/name-changed chat-id @new-group-chat-name]) :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])
(nil? @new-group-chat-name) (nil? @new-group-chat-name)
(re-frame/dispatch [:navigate-back]))} (re-frame/dispatch [:navigate-back]))}
(i18n/label :t/done)]}]])) (i18n/label :t/done)]}]]))

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,27 +1,26 @@
(ns status-im2.contexts.chat.messages.view (ns status-im2.contexts.chat.messages.view
(:require [reagent.core :as reagent] (:require [quo2.core :as quo]
[re-frame.db] [re-frame.db]
[i18n.i18n :as i18n]
[react-native.core :as rn] [react-native.core :as rn]
[utils.re-frame :as rf] [reagent.core :as reagent]
[utils.debounce :as debounce] [status-im.ui2.screens.chat.composer.view :as composer]
[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]
;;TODO move to status-im2
[status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover] [status-im.ui2.screens.chat.pin-limit-popover.view :as pin-limit-popover]
[status-im.ui2.screens.chat.composer.view :as composer])) [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.debounce :as debounce]
[utils.re-frame :as rf]))
(defn navigate-back-handler [] (defn navigate-back-handler
[]
(when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat)) (when (and (not @navigation.state/curr-modal) (= (get @re-frame.db/app-db :view-id) :chat))
(rn/hw-back-remove-listener navigate-back-handler) (rn/hw-back-remove-listener navigate-back-handler)
(rf/dispatch [:close-chat]) (rf/dispatch [:close-chat])
(rf/dispatch [:navigate-back]))) (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]) (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) display-name (if (= chat-type constants/one-to-one-chat-type)
(first (rf/sub [:contacts/contact-two-names-by-identity chat-id])) (first (rf/sub [:contacts/contact-two-names-by-identity chat-id]))
@ -30,7 +29,7 @@
contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id])) contact (when-not group-chat (rf/sub [:contacts/contact-by-address chat-id]))
photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path chat-id]))] photo-path (when-not (empty? (:images contact)) (rf/sub [:chats/photo-path chat-id]))]
[quo/page-nav [quo/page-nav
{:align-mid? true {:align-mid? true
:mid-section :mid-section
(if group-chat (if group-chat
@ -56,14 +55,15 @@
:icon :i/options :icon :i/options
:accessibility-label :options-button}]}])) :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 (let [;;we want to react only on these fields, do not use full chat map here
show-input? (not (rf/sub [:group-chat/removed-from-current-chat?])) {:keys [chat-id show-input?] :as chat} (rf/sub [:chats/current-chat-chat-view])
{:keys [chat-id] :as chat} (rf/sub [:chats/current-chat-chat-view]) mutual-contact-requests-enabled? (rf/sub [:mutual-contact-requests/enabled?])]
mutual-contact-requests-enabled? (rf/sub [:mutual-contact-requests/enabled?])]
[rn/keyboard-avoiding-view {:style {:flex 1}} [rn/keyboard-avoiding-view {:style {:flex 1}}
[page-nav] [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-limit-popover/pin-limit-popover chat-id]
[pin.banner/banner chat-id] [pin.banner/banner chat-id]
;;MESSAGES LIST ;;MESSAGES LIST
@ -74,17 +74,13 @@
:bottom-space 15}] :bottom-space 15}]
;;INPUT COMPOSER ;;INPUT COMPOSER
(when show-input? (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 (reagent/create-class
{:component-did-mount (fn [] {:component-did-mount (fn []
(rn/hw-back-remove-listener navigate-back-handler) (rn/hw-back-remove-listener navigate-back-handler)
(rn/hw-back-add-listener navigate-back-handler)) (rn/hw-back-add-listener navigate-back-handler))
:component-will-unmount (fn [] (rn/hw-back-remove-listener navigate-back-handler)) :component-will-unmount (fn [] (rn/hw-back-remove-listener navigate-back-handler))
:reagent-render chat-render})) :reagent-render chat-render}))

View File

@ -1,48 +1,54 @@
(ns status-im2.contexts.quo-preview.avatars.group-avatar (ns status-im2.contexts.quo-preview.avatars.group-avatar
(:require [reagent.core :as reagent] (:require [quo2.components.avatars.group-avatar :as quo2]
[react-native.core :as rn]
[status-im2.contexts.quo-preview.preview :as preview]
[quo2.foundations.colors :as colors] [quo2.foundations.colors :as colors]
[quo2.components.avatars.group-avatar :as quo2])) [react-native.core :as rn]
[reagent.core :as reagent]
[status-im2.contexts.quo-preview.preview :as preview]))
(def descriptor [{:label "Size" (def descriptor
:key :size [{:label "Size"
:type :select :key :size
:options [{:key :small :type :select
:value "Small"} :options [{:key :small
{:key :medium :value "Small"}
:value "Medium"} {:key :medium
{:key :large :value "Medium"}
:value "Large"}]} {:key :large
{:label "Color" :value "Large"}]}
:key :color {:label "Color"
:type :select :key :color
:options :type :select
(map :options
(fn [c] (map
{:key c (fn [c]
:value c}) {:key c
["#ff0000" "#0000ff"])}]) ; TODO: this is temporary only. Issue: https://github.com/status-im/status-mobile/issues/14566 :value c})
(keys colors/customization))}])
(defn cool-preview [] (defn cool-preview
[]
(let [state (reagent/atom {:theme :light (let [state (reagent/atom {:theme :light
:color :purple :color :purple
:size :small})] :size :small})]
(fn [] (fn []
[rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!} [rn/touchable-without-feedback {:on-press rn/dismiss-keyboard!}
[rn/view {:padding-bottom 150} [rn/view {:padding-bottom 150}
[rn/view {:flex 1} [rn/view {:flex 1}
[preview/customizer state descriptor]] [preview/customizer state descriptor]]
[rn/view {:padding-vertical 60 [rn/view
:flex-direction :row {:padding-vertical 60
:justify-content :center} :flex-direction :row
:justify-content :center}
[quo2/group-avatar @state]]]]))) [quo2/group-avatar @state]]]])))
(defn preview-group-avatar [] (defn preview-group-avatar
[rn/view {:background-color (colors/theme-colors colors/white []
colors/neutral-90) [rn/view
:flex 1} {:background-color (colors/theme-colors colors/white
[rn/flat-list {:flex 1 colors/neutral-90)
:keyboardShouldPersistTaps :always :flex 1}
:header [cool-preview] [rn/flat-list
:key-fn str}]]) {:flex 1
:keyboardShouldPersistTaps :always
:header [cool-preview]
:key-fn str}]])

View File

@ -1,45 +1,43 @@
(ns status-im2.setup.db (ns status-im2.setup.db
(:require (:require [react-native.core :as rn] ;; TODO (14/11/22 flexsurfer move to status-im2 namespace
[react-native.core :as rn] [status-im.fleet.core :as fleet]
;; TODO (14/11/22 flexsurfer move to status-im2 namespace [status-im.wallet.db :as wallet.db]))
[status-im.fleet.core :as fleet]
[status-im.wallet.db :as wallet.db]))
;; initial state of app-db ;; initial state of app-db
(def app-db {:contacts/contacts {} (def app-db
:pairing/installations {} {:contacts/contacts {}
:group/selected-contacts #{} :pairing/installations {}
:chats {} :group/selected-contacts #{}
:current-chat-id nil :chats {}
:group-chat/selected-participants #{} :current-chat-id nil
:group-chat/deselected-members #{} :selected-participants #{}
:sync-state :done :sync-state :done
:link-previews-whitelist [] :link-previews-whitelist []
:app-state "active" :app-state "active"
:wallet wallet.db/default-wallet :wallet wallet.db/default-wallet
:wallet/all-tokens {} :wallet/all-tokens {}
:peers-count 0 :peers-count 0
:node-info {} :node-info {}
:peers-summary [] :peers-summary []
:transport/message-envelopes {} :transport/message-envelopes {}
:mailserver/mailservers (fleet/default-mailservers {}) :mailserver/mailservers (fleet/default-mailservers {})
:mailserver/topics {} :mailserver/topics {}
:mailserver/pending-requests 0 :mailserver/pending-requests 0
:chat/cooldowns 0 :chat/cooldowns 0
:chat/inputs {} :chat/inputs {}
:chat/cooldown-enabled? false :chat/cooldown-enabled? false
:chat/last-outgoing-message-sent-at 0 :chat/last-outgoing-message-sent-at 0
:chat/spam-messages-frequency 0 :chat/spam-messages-frequency 0
:chats-home-list #{} :chats-home-list #{}
:home-items-show-number 20 :home-items-show-number 20
:tooltips {} :tooltips {}
:dimensions/window (rn/get-window) :dimensions/window (rn/get-window)
:registry {} :registry {}
:visibility-status-updates {} :visibility-status-updates {}
:stickers/packs-pending #{} :stickers/packs-pending #{}
:keycard {:nfc-enabled? false :keycard {:nfc-enabled? false
:pin {:original [] :pin {:original []
:confirmation [] :confirmation []
:current [] :current []
:puk [] :puk []
:enter-step :original}}}) :enter-step :original}}})

View File

@ -1,413 +1,425 @@
(ns status-im2.subs.chat.chats (ns status-im2.subs.chat.chats
(:require [re-frame.core :as re-frame] (:require [clojure.string :as string]
[clojure.string :as string]
[status-im2.common.constants :as constants]
[quo.design-system.colors :as colors] [quo.design-system.colors :as colors]
[status-im.chat.models :as chat.models] [re-frame.core :as re-frame]
[status-im.communities.core :as communities]
[status-im.utils.image-server :as image-server]
[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.add-new.db :as db]
[status-im.i18n.i18n :as i18n])) [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]))
(re-frame/reg-sub (re-frame/reg-sub
:chats/chat :chats/chat
:<- [:chats/chats] :<- [:chats/chats]
(fn [chats [_ chat-id]] (fn [chats [_ chat-id]]
(get chats chat-id))) (get chats chat-id)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/by-community-id :chats/by-community-id
:<- [:chats/chats] :<- [:chats/chats]
(fn [chats [_ community-id]] (fn [chats [_ community-id]]
(->> chats (->> chats
(keep (fn [[_ chat]] (keep (fn [[_ chat]]
(when (= (:community-id chat) community-id) (when (= (:community-id chat) community-id)
chat))) chat)))
(sort-by :timestamp >)))) (sort-by :timestamp >))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/with-empty-category-by-community-id :chats/with-empty-category-by-community-id
(fn [[_ community-id]] (fn [[_ community-id]]
[(re-frame/subscribe [:chats/by-community-id community-id]) [(re-frame/subscribe [:chats/by-community-id community-id])
(re-frame/subscribe [:communities/community-chats community-id])]) (re-frame/subscribe [:communities/community-chats community-id])])
(fn [[chats comm-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 (re-frame/reg-sub
:chats/sorted-categories-by-community-id :chats/sorted-categories-by-community-id
(fn [[_ community-id]] (fn [[_ community-id]]
[(re-frame/subscribe [:chats/by-community-id community-id]) [(re-frame/subscribe [:chats/by-community-id community-id])
(re-frame/subscribe [:communities/community-chats community-id])]) (re-frame/subscribe [:communities/community-chats community-id])])
(fn [[chats comm-chats] [_ community-id]] (fn [[chats comm-chats] [_ community-id]]
(let [chat-cat (into {} (map (fn [{:keys [id categoryID position]}] (let [chat-cat (into {}
{(str community-id id) {:categoryID categoryID (map (fn [{:keys [id categoryID position]}]
:position position}}) {(str community-id id) {:categoryID categoryID
(vals comm-chats)))] :position position}})
(group-by :categoryID (sort-by :position (vals comm-chats)))]
(map #(cond-> (merge % (chat-cat (:chat-id %))) (group-by :categoryID
(= community-id constants/status-community-id) (sort-by :position
(assoc :color colors/blue)) (map #(cond-> (merge % (chat-cat (:chat-id %)))
chats)))))) (= community-id constants/status-community-id)
(assoc :color colors/blue))
chats))))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/category-by-chat-id :chats/category-by-chat-id
(fn [[_ community-id _]] (fn [[_ community-id _]]
[(re-frame/subscribe [:communities/community community-id])]) [(re-frame/subscribe [:communities/community community-id])])
(fn [[{:keys [chats categories]}] [_ community-id chat-id]] (fn [[{:keys [chats categories]}] [_ community-id chat-id]]
(get categories (get-in chats [(string/replace chat-id community-id "") :categoryID])))) (get categories (get-in chats [(string/replace chat-id community-id "") :categoryID]))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/community-chat-by-id :chats/community-chat-by-id
(fn [[_ community-id _]] (fn [[_ community-id _]]
[(re-frame/subscribe [:communities/community community-id])]) [(re-frame/subscribe [:communities/community community-id])])
(fn [[{:keys [chats]}] [_ community-id chat-id]] (fn [[{:keys [chats]}] [_ community-id chat-id]]
(get chats (string/replace chat-id community-id "")))) (get chats (string/replace chat-id community-id ""))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/home-list-chats :chats/home-list-chats
:<- [:chats/chats] :<- [:chats/chats]
:<- [:chats-home-list] :<- [:chats-home-list]
(fn [[chats active-chats]] (fn [[chats active-chats]]
(reduce #(if-let [item (get chats %2)] (reduce #(if-let [item (get chats %2)]
(conj %1 item) (conj %1 item)
%1) %1)
[] []
active-chats))) active-chats)))
(re-frame/reg-sub (re-frame/reg-sub
:chat-by-id :chat-by-id
:<- [:chats/chats] :<- [:chats/chats]
(fn [chats [_ chat-id]] (fn [chats [_ chat-id]]
(get chats chat-id))) (get chats chat-id)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/synced-from :chats/synced-from
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id])) (re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [synced-from]}] (fn [{:keys [synced-from]}]
synced-from)) synced-from))
(re-frame/reg-sub (re-frame/reg-sub
:chats/muted :chats/muted
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id])) (re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [muted]}] (fn [{:keys [muted]}]
muted)) muted))
(re-frame/reg-sub (re-frame/reg-sub
:chats/chat-type :chats/chat-type
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id])) (re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [chat-type]}] (fn [{:keys [chat-type]}]
chat-type)) chat-type))
(re-frame/reg-sub (re-frame/reg-sub
:chats/joined :chats/joined
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id])) (re-frame/subscribe [:chat-by-id chat-id]))
(fn [{:keys [joined]}] (fn [{:keys [joined]}]
joined)) joined))
(re-frame/reg-sub (re-frame/reg-sub
:chats/synced-to-and-from :chats/synced-to-and-from
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
(re-frame/subscribe [:chat-by-id chat-id])) (re-frame/subscribe [:chat-by-id chat-id]))
(fn [chat] (fn [chat]
(select-keys chat [:synced-to :synced-from]))) (select-keys chat [:synced-to :synced-from])))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-raw-chat :chats/current-raw-chat
:<- [:chats/chats] :<- [:chats/chats]
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]
(fn [[chats current-chat-id]] (fn [[chats current-chat-id]]
(get chats current-chat-id))) (get chats current-chat-id)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat-inputs :chats/current-chat-inputs
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]
:<- [:chat/inputs] :<- [:chat/inputs]
(fn [[chat-id inputs]] (fn [[chat-id inputs]]
(get inputs chat-id))) (get inputs chat-id)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/timeline-chat-input :chats/timeline-chat-input
:<- [:chat/inputs] :<- [:chat/inputs]
:<- [:multiaccount/public-key] :<- [:multiaccount/public-key]
(fn [[inputs public-key]] (fn [[inputs public-key]]
(get inputs (chat.models/profile-chat-topic public-key)))) (get inputs (chat.models/profile-chat-topic public-key))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/timeline-chat-input-text :chats/timeline-chat-input-text
:<- [:chats/timeline-chat-input] :<- [:chats/timeline-chat-input]
(fn [input] (fn [input]
(:input-text input))) (:input-text input)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat-membership :chats/current-chat-membership
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]
:<- [:chat/memberships] :<- [:chat/memberships]
(fn [[chat-id memberships]] (fn [[chat-id memberships]]
(get memberships chat-id))) (get memberships chat-id)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat :chats/current-chat
:<- [:chats/current-raw-chat] :<- [:chats/current-raw-chat]
:<- [:multiaccount/public-key] :<- [:multiaccount/public-key]
:<- [:communities/current-community] :<- [:communities/current-community]
:<- [:contacts/blocked-set] :<- [:contacts/blocked-set]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:chat/inputs] :<- [:chat/inputs]
:<- [:mutual-contact-requests/enabled?] :<- [: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
(when current-chat inputs mutual-contact-requests-enabled?]]
(cond-> current-chat (when current-chat
(chat.models/public-chat? current-chat) (cond-> current-chat
(assoc :show-input? true) (chat.models/public-chat? current-chat)
(assoc :show-input? true)
(and (chat.models/group-chat? current-chat) (and (chat.models/group-chat? current-chat)
(group-chats.db/member? my-public-key current-chat)) (group-chats.db/member? my-public-key current-chat))
(assoc :show-input? true (assoc :show-input? true
:member? true) :member? true)
(and (chat.models/community-chat? current-chat) (and (chat.models/community-chat? current-chat)
(communities/can-post? community my-public-key (:chat-id current-chat))) (communities/can-post? community my-public-key (:chat-id current-chat)))
(assoc :show-input? true) (assoc :show-input? true)
(not group-chat) (not group-chat)
(assoc :show-input? (assoc :show-input?
(and (and
(or (or
(not mutual-contact-requests-enabled?) (not mutual-contact-requests-enabled?)
(get-in inputs [chat-id :metadata :sending-contact-request]) (get-in inputs [chat-id :metadata :sending-contact-request])
(and mutual-contact-requests-enabled? (and mutual-contact-requests-enabled?
(= constants/contact-request-state-mutual (= constants/contact-request-state-mutual
(get-in contacts [chat-id :contact-request-state])))) (get-in contacts [chat-id :contact-request-state]))))
(not (contains? blocked-users-set chat-id)))))))) (not (contains? blocked-users-set chat-id))))))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat-chat-view :chats/current-chat-chat-view
:<- [:chats/current-chat] :<- [:chats/current-chat]
(fn [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 (re-frame/reg-sub
:current-chat/metadata :current-chat/metadata
:<- [:chats/current-raw-chat] :<- [:chats/current-raw-chat]
(fn [current-chat] (fn [current-chat]
(select-keys current-chat (select-keys current-chat
[:community-id [:community-id
:contacts :contacts
:public? :public?
:group-chat :group-chat
:chat-type :chat-type
:chat-id :chat-id
:chat-name :chat-name
:color :color
:invitation-admin]))) :invitation-admin])))
(re-frame/reg-sub (re-frame/reg-sub
:current-chat/one-to-one-chat? :current-chat/one-to-one-chat?
:<- [:chats/current-raw-chat] :<- [:chats/current-raw-chat]
(fn [current-chat] (fn [current-chat]
(not (or (chat.models/group-chat? current-chat) (not (or (chat.models/group-chat? current-chat)
(chat.models/public-chat? current-chat))))) (chat.models/public-chat? current-chat)))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-profile-chat :chats/current-profile-chat
:<- [:contacts/current-contact-identity] :<- [:contacts/current-contact-identity]
(fn [identity] (fn [identity]
(chat.models/profile-chat-topic identity))) (chat.models/profile-chat-topic identity)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/photo-path :chats/photo-path
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:profile/multiaccount] :<- [:profile/multiaccount]
:<- [:mediaserver/port] :<- [:mediaserver/port]
(fn [[contacts {:keys [public-key] :as multiaccount} port] [_ id]] (fn [[contacts {:keys [public-key] :as multiaccount} port] [_ id]]
(let [contact (or (when (= id public-key) (let [contact (or (when (= id public-key)
multiaccount) multiaccount)
(get contacts id))] (get contacts id))]
(if (nil? contact) (if (nil? contact)
(image-server/get-identicons-uri port id) (image-server/get-identicons-uri port id)
(multiaccounts/displayed-photo contact))))) (multiaccounts/displayed-photo contact)))))
(re-frame/reg-sub (re-frame/reg-sub
:chats/unread-messages-number :chats/unread-messages-number
:<- [:chats/home-list-chats] :<- [:chats/home-list-chats]
(fn [chats _] (fn [chats _]
(reduce (fn [{:keys [public other]} {:keys [unviewed-messages-count public?] :as chat}] (reduce (fn [{:keys [public other]} {:keys [unviewed-messages-count public?] :as chat}]
(if (or public? (chat.models/community-chat? chat)) (if (or public? (chat.models/community-chat? chat))
{:public (+ public unviewed-messages-count) {:public (+ public unviewed-messages-count)
:other other} :other other}
{:other (+ other unviewed-messages-count) {:other (+ other unviewed-messages-count)
:public public})) :public public}))
{:public 0 {:public 0
:other 0} :other 0}
chats))) chats)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/current-chat-cooldown-enabled? :chats/current-chat-cooldown-enabled?
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:chats/cooldown-enabled?] :<- [:chats/cooldown-enabled?]
(fn [[{:keys [public?]} cooldown-enabled?]] (fn [[{:keys [public?]} cooldown-enabled?]]
(and public? (and public?
cooldown-enabled?))) cooldown-enabled?)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/reply-message :chats/reply-message
:<- [:chats/current-chat-inputs] :<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(:responding-to-message metadata))) (:responding-to-message metadata)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/edit-message :chats/edit-message
:<- [:chats/current-chat-inputs] :<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(:editing-message metadata))) (:editing-message metadata)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/sending-contact-request :chats/sending-contact-request
:<- [:chats/current-chat-inputs] :<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(:sending-contact-request metadata))) (:sending-contact-request metadata)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/sending-image :chats/sending-image
:<- [:chats/current-chat-inputs] :<- [:chats/current-chat-inputs]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(:sending-image metadata))) (:sending-image metadata)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/timeline-sending-image :chats/timeline-sending-image
:<- [:chats/timeline-chat-input] :<- [:chats/timeline-chat-input]
(fn [{:keys [metadata]}] (fn [{:keys [metadata]}]
(:sending-image metadata))) (:sending-image metadata)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/chat-toolbar :chats/chat-toolbar
:<- [:multiaccounts/login] :<- [:multiaccounts/login]
:<- [:chats/sending-image] :<- [:chats/sending-image]
:<- [:mainnet?] :<- [:mainnet?]
:<- [:current-chat/one-to-one-chat?] :<- [:current-chat/one-to-one-chat?]
:<- [:current-chat/metadata] :<- [:current-chat/metadata]
:<- [:chats/reply-message] :<- [:chats/reply-message]
:<- [:chats/edit-message] :<- [:chats/edit-message]
:<- [:chats/sending-contact-request] :<- [: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
(let [sending-image (seq sending-image)] sending-contact-request]]
{:send (not processing) (let [sending-image (seq sending-image)]
:stickers (and (or config/stickers-test-enabled? mainnet?) {:send (not processing)
(not sending-image) :stickers (and (or config/stickers-test-enabled? mainnet?)
(not sending-contact-request) (not sending-image)
(not reply)) (not sending-contact-request)
:image (and (not reply) (not reply))
(not edit) :image (and (not reply)
(not sending-contact-request) (not edit)
(not public?)) (not sending-contact-request)
:extensions (and one-to-one-chat? (not public?))
(or config/commands-enabled? mainnet?) :extensions (and one-to-one-chat?
(not edit) (or config/commands-enabled? mainnet?)
(not sending-contact-request) (not edit)
(not reply)) (not sending-contact-request)
:audio (and (not sending-image) (not reply))
(not reply) :audio (and (not sending-image)
(not edit) (not reply)
(not sending-contact-request) (not edit)
(not public?)) (not sending-contact-request)
:sending-image sending-image}))) (not public?))
:sending-image sending-image})))
(re-frame/reg-sub (re-frame/reg-sub
:public-chat.new/topic-error-message :public-chat.new/topic-error-message
:<- [:public-group-topic] :<- [:public-group-topic]
(fn [topic] (fn [topic]
(when-not (or (empty? topic) (when-not (or (empty? topic)
(db/valid-topic? topic)) (db/valid-topic? topic))
(i18n/label :topic-name-error)))) (i18n/label :topic-name-error))))
(defn filter-selected-contacts (defn filter-selected-contacts
[selected-contacts contacts] [selected-contacts contacts]
(filter #(:added (contacts %)) selected-contacts)) (filter #(:added (contacts %)) selected-contacts))
(re-frame/reg-sub (re-frame/reg-sub
:selected-contacts-count :selected-contacts-count
:<- [:group/selected-contacts] :<- [:group/selected-contacts]
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [[selected-contacts contacts]] (fn [[selected-contacts contacts]]
(count (filter-selected-contacts selected-contacts contacts)))) (count (filter-selected-contacts selected-contacts contacts))))
(re-frame/reg-sub (re-frame/reg-sub
:group-chat/selected-participants-count :selected-participants-count
:<- [:group-chat/selected-participants] :<- [:selected-participants]
(fn [selected-participants] (fn [selected-participants]
(count 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)) (filter #(selected-contacts (:public-key %)) active-contacts))
(re-frame/reg-sub (re-frame/reg-sub
:selected-group-contacts :selected-group-contacts
:<- [:group/selected-contacts] :<- [:group/selected-contacts]
:<- [:contacts/active] :<- [:contacts/active]
(fn [[selected-contacts active-contacts]] (fn [[selected-contacts active-contacts]]
(filter-contacts selected-contacts active-contacts))) (filter-contacts selected-contacts active-contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:group-chat/inviter-info :group-chat/inviter-info
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
[(re-frame/subscribe [:chat-by-id chat-id]) [(re-frame/subscribe [:chat-by-id chat-id])
(re-frame/subscribe [:multiaccount/public-key])]) (re-frame/subscribe [:multiaccount/public-key])])
(fn [[chat my-public-key]] (fn [[chat my-public-key]]
{:member? (group-chats.db/member? my-public-key chat) {:member? (group-chats.db/member? my-public-key chat)
:inviter-pk (group-chats.db/get-inviter-pk my-public-key chat)})) :inviter-pk (group-chats.db/get-inviter-pk my-public-key chat)}))
(re-frame/reg-sub (re-frame/reg-sub
:group-chat/invitations-by-chat-id :group-chat/invitations-by-chat-id
:<- [:group-chat/invitations] :<- [:group-chat/invitations]
(fn [invitations [_ chat-id]] (fn [invitations [_ chat-id]]
(filter #(= (:chat-id %) chat-id) (vals invitations)))) (filter #(= (:chat-id %) chat-id) (vals invitations))))
(re-frame/reg-sub (re-frame/reg-sub
:group-chat/pending-invitations-by-chat-id :group-chat/pending-invitations-by-chat-id
(fn [[_ chat-id] _] (fn [[_ chat-id] _]
[(re-frame/subscribe [:group-chat/invitations-by-chat-id chat-id])]) [(re-frame/subscribe [:group-chat/invitations-by-chat-id chat-id])])
(fn [[invitations]] (fn [[invitations]]
(filter #(= constants/invitation-state-requested (:state %)) invitations))) (filter #(= constants/invitation-state-requested (:state %)) invitations)))
(re-frame/reg-sub (re-frame/reg-sub
:group-chat/removed-from-current-chat? :group-chat/removed-from-current-chat?
:<- [:chats/current-raw-chat] :<- [:chats/current-raw-chat]
:<- [:multiaccount/public-key] :<- [:multiaccount/public-key]
(fn [[current-chat pk]] (fn [[current-chat pk]]
(group-chat/member-removed? current-chat pk))) (group-chat/member-removed? current-chat pk)))
(re-frame/reg-sub (re-frame/reg-sub
:chats/mentionable-users :chats/mentionable-users
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:contacts/blocked-set] :<- [:contacts/blocked-set]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:multiaccount] :<- [:multiaccount]
(fn [[{:keys [users community-id] :as chat} blocked all-contacts (fn [[{:keys [users community-id] :as chat} blocked all-contacts
{:keys [public-key] :as current-multiaccount}]] {:keys [public-key] :as current-multiaccount}]]
(let [community-members @(re-frame/subscribe [:communities/community-members community-id]) (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
members-left (into #{} (filter #(group-chat/member-removed? chat %) (keys users)))] all-contacts
(apply dissoc mentionable-users (conj (concat blocked members-left) public-key))))) 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)))))
(re-frame/reg-sub (re-frame/reg-sub
:chat/mention-suggestions :chat/mention-suggestions
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]
:<- [:chats/mention-suggestions] :<- [:chats/mention-suggestions]
(fn [[chat-id mentions]] (fn [[chat-id mentions]]
(take 15 (get mentions chat-id)))) (take 15 (get mentions chat-id))))
(re-frame/reg-sub (re-frame/reg-sub
:chat/input-with-mentions :chat/input-with-mentions
:<- [:chats/current-chat-id] :<- [:chats/current-chat-id]
:<- [:chat/inputs-with-mentions] :<- [:chat/inputs-with-mentions]
(fn [[chat-id cursor]] (fn [[chat-id cursor]]
(get cursor chat-id))) (get cursor chat-id)))

View File

@ -1,54 +1,59 @@
(ns status-im2.subs.contact (ns status-im2.subs.contact
(:require [re-frame.core :as re-frame] (:require [clojure.string :as string]
[status-im.contact.db :as contact.db]
[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.ethereum.core :as ethereum]
[clojure.string :as string]
[utils.collection]
[i18n.i18n :as i18n] [i18n.i18n :as i18n]
[utils.re-frame :as rf])) [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.ui.screens.profile.visibility-status.utils :as visibility-status-utils]
[status-im.utils.gfycat.core :as gfycat]
[status-im.utils.image-server :as image-server]))
(re-frame/reg-sub (re-frame/reg-sub
::query-current-chat-contacts ::query-current-chat-contacts
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [[chat contacts] [_ query-fn]] (fn [[chat contacts] [_ query-fn]]
(contact.db/query-chat-contacts chat contacts query-fn))) (contact.db/query-chat-contacts chat contacts query-fn)))
(re-frame/reg-sub (re-frame/reg-sub
:multiaccount/profile-pictures-show-to :multiaccount/profile-pictures-show-to
:<- [:multiaccount] :<- [:multiaccount]
(fn [multiaccount] (fn [multiaccount]
(get multiaccount :profile-pictures-show-to))) (get multiaccount :profile-pictures-show-to)))
(re-frame/reg-sub (re-frame/reg-sub
:mutual-contact-requests/enabled? :mutual-contact-requests/enabled?
:<- [:multiaccount] :<- [:multiaccount]
(fn [settings] (fn [settings]
(boolean (:mutual-contact-enabled? settings)))) (boolean (:mutual-contact-enabled? settings))))
(re-frame/reg-sub (re-frame/reg-sub
::profile-pictures-visibility ::profile-pictures-visibility
:<- [:multiaccount] :<- [:multiaccount]
(fn [multiaccount] (fn [multiaccount]
(get multiaccount :profile-pictures-visibility))) (get multiaccount :profile-pictures-visibility)))
(defn- replace-contact-image-uri [contact port identity] (defn- replace-contact-image-uri
(let [identicon (image-server/get-identicons-uri port identity) [contact port identity]
(let [identicon (image-server/get-identicons-uri port identity)
contact-images (:images contact) contact-images (:images contact)
contact-images (reduce (fn [acc image] (let [image-name (:type image) contact-images (reduce (fn [acc image]
; We pass the clock so that we reload the image if the image is updated (let [image-name (:type image)
clock (:clock image) ; We pass the clock so that we reload the image if the image is
uri (image-server/get-contact-image-uri port identity image-name clock)] ; updated
(assoc-in acc [(keyword image-name) :uri] uri))) clock (:clock image)
uri (image-server/get-contact-image-uri port
identity
image-name
clock)]
(assoc-in acc [(keyword image-name) :uri] uri)))
contact-images contact-images
(vals contact-images))] (vals contact-images))]
(assoc contact :identicon identicon :images 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] (reduce-kv (fn [acc public-key contact]
(let [contact (replace-contact-image-uri contact port public-key)] (let [contact (replace-contact-image-uri contact port public-key)]
(assoc acc public-key contact))) (assoc acc public-key contact)))
@ -56,250 +61,237 @@
contacts)) contacts))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contacts :contacts/contacts
:<- [:contacts/contacts-raw] :<- [:contacts/contacts-raw]
:<- [::profile-pictures-visibility] :<- [::profile-pictures-visibility]
:<- [:multiaccount/public-key] :<- [:multiaccount/public-key]
:<- [:mediaserver/port] :<- [:mediaserver/port]
(fn [[contacts profile-pictures-visibility public-key port]] (fn [[contacts profile-pictures-visibility public-key port]]
(let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)] (let [contacts (contact.db/enrich-contacts contacts profile-pictures-visibility public-key)]
(reduce-contacts-image-uri contacts port)))) (reduce-contacts-image-uri contacts port))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active :contacts/active
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts] (fn [contacts]
(contact.db/get-active-contacts contacts))) (contact.db/get-active-contacts contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-sections :contacts/active-sections
:<- [:contacts/active] :<- [:contacts/active]
(fn [contacts] (fn [contacts]
(-> (reduce (-> (reduce
(fn [acc contact] (fn [acc contact]
(let [first-char (first (:alias contact))] (let [first-char (first (:alias contact))]
(if (get acc first-char) (if (get acc first-char)
(update-in acc [first-char :data] #(conj % contact)) (update-in acc [first-char :data] #(conj % contact))
(assoc acc first-char {:title first-char :data [contact]})))) (assoc acc first-char {:title first-char :data [contact]}))))
{} {}
contacts) contacts)
sort sort
vals))) vals)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/add-members-sections :contacts/sorted-contacts
:<- [:contacts/current-chat-contacts] :<- [:contacts/active]
:<- [:contacts/active] (fn [active-contacts]
(fn [[members contacts]] (->> active-contacts
(-> (reduce (sort-by :alias)
(fn [acc contact] (sort-by
(let [first-char (first (:alias contact))] #(visibility-status-utils/visibility-status-order (:public-key %))))))
(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 (re-frame/reg-sub
:contacts/sorted-contacts :contacts/active-count
:<- [:contacts/active] :<- [:contacts/active]
(fn [active-contacts] (fn [active-contacts]
(->> active-contacts (count active-contacts)))
(sort-by :alias)
(sort-by
#(visibility-status-utils/visibility-status-order (:public-key %))))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-count :contacts/blocked
:<- [:contacts/active] :<- [:contacts/contacts]
(fn [active-contacts] (fn [contacts]
(count active-contacts))) (->> contacts
(filter (fn [[_ contact]]
(:blocked contact)))
(contact.db/sort-contacts))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/blocked :contacts/blocked-count
:<- [:contacts/contacts] :<- [:contacts/blocked]
(fn [contacts] (fn [blocked-contacts]
(->> contacts (count blocked-contacts)))
(filter (fn [[_ contact]]
(:blocked contact)))
(contact.db/sort-contacts))))
(re-frame/reg-sub
:contacts/blocked-count
:<- [:contacts/blocked]
(fn [blocked-contacts]
(count blocked-contacts)))
(defn filter-recipient-contacts (defn filter-recipient-contacts
[search-filter {:keys [names]}] [search-filter {:keys [names]}]
(let [{:keys [nickname three-words-name ens-name]} names] (let [{:keys [nickname three-words-name ens-name]} names]
(or (or
(when ens-name (when ens-name
(string/includes? (string/lower-case (str ens-name)) search-filter)) (string/includes? (string/lower-case (str ens-name)) search-filter))
(string/includes? (string/lower-case three-words-name) search-filter) (string/includes? (string/lower-case three-words-name) search-filter)
(when nickname (when nickname
(string/includes? (string/lower-case nickname) search-filter))))) (string/includes? (string/lower-case nickname) search-filter)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/active-with-ens-names :contacts/active-with-ens-names
:<- [:contacts/active] :<- [:contacts/active]
:<- [:search/recipient-filter] :<- [:search/recipient-filter]
(fn [[contacts search-filter]] (fn [[contacts search-filter]]
(let [contacts (filter :ens-verified contacts)] (let [contacts (filter :ens-verified contacts)]
(if (string/blank? search-filter) (if (string/blank? search-filter)
contacts contacts
(filter (partial filter-recipient-contacts (filter (partial filter-recipient-contacts
(string/lower-case search-filter)) (string/lower-case search-filter))
contacts))))) contacts)))))
(defn- enrich-contact [_ identity ens-name port] (defn- enrich-contact
[_ identity ens-name port]
(let [contact (contact.db/enrich-contact (let [contact (contact.db/enrich-contact
(contact.db/public-key-and-ens-name->new-contact identity ens-name))] (contact.db/public-key-and-ens-name->new-contact identity ens-name))]
(replace-contact-image-uri contact port identity))) (replace-contact-image-uri contact port identity)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/current-contact :contacts/current-contact
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:contacts/current-contact-identity] :<- [:contacts/current-contact-identity]
:<- [:contacts/current-contact-ens-name] :<- [:contacts/current-contact-ens-name]
:<- [:mediaserver/port] :<- [:mediaserver/port]
(fn [[contacts identity ens-name port]] (fn [[contacts identity ens-name port]]
(let [contact (get contacts identity)] (let [contact (get contacts identity)]
(cond-> contact (cond-> contact
(nil? contact) (nil? contact)
(enrich-contact identity ens-name port))))) (enrich-contact identity ens-name port)))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-by-identity :contacts/contact-by-identity
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts [_ identity]] (fn [contacts [_ identity]]
(multiaccounts/contact-by-identity contacts identity))) (multiaccounts/contact-by-identity contacts identity)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-added? :contacts/contact-added?
(fn [[_ identity] _] (fn [[_ identity] _]
[(re-frame/subscribe [:contacts/contact-by-identity identity])]) [(re-frame/subscribe [:contacts/contact-by-identity identity])])
(fn [[contact] _] (fn [[contact] _]
(:added contact))) (:added contact)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-blocked? :contacts/contact-blocked?
(fn [[_ identity] _] (fn [[_ identity] _]
[(re-frame/subscribe [:contacts/contact-by-identity identity])]) [(re-frame/subscribe [:contacts/contact-by-identity identity])])
(fn [[contact] _] (fn [[contact] _]
(:blocked contact))) (:blocked contact)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-two-names-by-identity :contacts/contact-two-names-by-identity
(fn [[_ identity] _] (fn [[_ identity] _]
[(re-frame/subscribe [:contacts/contact-by-identity identity]) [(re-frame/subscribe [:contacts/contact-by-identity identity])
(re-frame/subscribe [:multiaccount])]) (re-frame/subscribe [:multiaccount])])
(fn [[contact current-multiaccount] [_ identity]] (fn [[contact current-multiaccount] [_ identity]]
(multiaccounts/contact-two-names-by-identity contact current-multiaccount (multiaccounts/contact-two-names-by-identity contact
identity))) current-multiaccount
identity)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-name-by-identity :contacts/contact-name-by-identity
(fn [[_ identity] _] (fn [[_ identity] _]
[(re-frame/subscribe [:contacts/contact-two-names-by-identity identity])]) [(re-frame/subscribe [:contacts/contact-two-names-by-identity identity])])
(fn [[names] _] (fn [[names] _]
(first names))) (first names)))
(re-frame/reg-sub (re-frame/reg-sub
:messages/quote-info :messages/quote-info
:<- [:chats/messages] :<- [:chats/messages]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:multiaccount] :<- [:multiaccount]
(fn [[messages contacts current-multiaccount] [_ message-id]] (fn [[messages contacts current-multiaccount] [_ message-id]]
(when-let [message (get messages message-id)] (when-let [message (get messages message-id)]
(let [identity (:from message) (let [identity (:from message)
me? (= (:public-key current-multiaccount) identity)] me? (= (:public-key current-multiaccount) identity)]
(if me? (if me?
{:quote {:from identity {:quote {:from identity
:text (get-in message [:content :text])} :text (get-in message [:content :text])}
:ens-name (:preferred-name current-multiaccount) :ens-name (:preferred-name current-multiaccount)
:alias (gfycat/generate-gfy identity)} :alias (gfycat/generate-gfy identity)}
(let [contact (or (contacts identity) (let [contact (or (contacts identity)
(contact.db/public-key->new-contact identity))] (contact.db/public-key->new-contact identity))]
{:quote {:from identity {:quote {:from identity
:text (get-in message [:content :text])} :text (get-in message [:content :text])}
:ens-name (when (:ens-verified contact) :ens-name (when (:ens-verified contact)
(:name contact)) (:name contact))
:alias (or (:alias contact) :alias (or (:alias contact)
(gfycat/generate-gfy identity))})))))) (gfycat/generate-gfy identity))}))))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/all-contacts-not-in-current-chat :contacts/all-contacts-not-in-current-chat
:<- [::query-current-chat-contacts remove] :<- [::query-current-chat-contacts remove]
(fn [contacts] (fn [contacts]
(filter :added contacts))) (filter :added contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/current-chat-contacts :contacts/current-chat-contacts
:<- [:chats/current-chat] :<- [:chats/current-chat]
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:multiaccount] :<- [:multiaccount]
(fn [[{:keys [contacts admins]} all-contacts current-multiaccount]] (fn [[{:keys [contacts admins]} all-contacts current-multiaccount]]
(contact.db/get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount))) (contact.db/get-all-contacts-in-group-chat contacts admins all-contacts current-multiaccount)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contacts-by-chat :contacts/contacts-by-chat
(fn [[_ _ chat-id] _] (fn [[_ _ chat-id] _]
[(re-frame/subscribe [:chats/chat chat-id]) [(re-frame/subscribe [:chats/chat chat-id])
(re-frame/subscribe [:contacts/contacts])]) (re-frame/subscribe [:contacts/contacts])])
(fn [[chat all-contacts] [_ query-fn]] (fn [[chat all-contacts] [_ query-fn]]
(contact.db/query-chat-contacts chat all-contacts query-fn))) (contact.db/query-chat-contacts chat all-contacts query-fn)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contact-by-address :contacts/contact-by-address
:<- [:contacts/contacts] :<- [:contacts/contacts]
:<- [:multiaccount/contact] :<- [:multiaccount/contact]
(fn [[contacts multiaccount] [_ address]] (fn [[contacts multiaccount] [_ address]]
(if (ethereum/address= address (:public-key multiaccount)) (if (ethereum/address= address (:public-key multiaccount))
multiaccount multiaccount
(contact.db/find-contact-by-address contacts address)))) (contact.db/find-contact-by-address contacts address))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/contacts-by-address :contacts/contacts-by-address
:<- [:contacts/contacts] :<- [:contacts/contacts]
(fn [contacts] (fn [contacts]
(reduce (fn [acc [_ {:keys [address] :as contact}]] (reduce (fn [acc [_ {:keys [address] :as contact}]]
(if address (if address
(assoc acc address contact) (assoc acc address contact)
acc)) acc))
{} {}
contacts))) contacts)))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/filtered-active-sections :contacts/filtered-active-sections
:<- [:contacts/active-sections] :<- [:contacts/active-sections]
:<- [:contacts/search-query] :<- [:contacts/search-query]
(fn [[contacts query]] (fn [[contacts query]]
(if (empty? query) (if (empty? query)
contacts contacts
(->> contacts (->> contacts
(map (fn [item] (map (fn [item]
(update item :data (fn [data] (update item
(filter #(string/includes? :data
(string/lower-case (:alias %)) (fn [data]
(string/lower-case query)) (filter #(string/includes?
data))))) (string/lower-case (:alias %))
(remove #(empty? (:data %))))))) (string/lower-case query))
data)))))
(remove #(empty? (:data %)))))))
(re-frame/reg-sub (re-frame/reg-sub
:contacts/group-members-sections :contacts/group-members-sections
:<- [:contacts/current-chat-contacts] :<- [:contacts/current-chat-contacts]
(fn [members] (fn [members]
(let [admins (filter :admin? members) (let [admins (filter :admin? members)
online (filter #(let [online (rf/sub [:visibility-status-updates/online? (:public-key %)])] online (filter #(and (not (:admin? %)) (:online? %)) members)
(and (not (:admin? %)) online)) members) offline (filter #(and (not (:admin? %)) (not (:online? %))) members)]
offline (filter #(let [online (rf/sub [:visibility-status-updates/online? (:public-key %)])] (vals (cond-> {}
(and (not (:admin? %)) (not online))) members)] (seq admins) (assoc :owner {:title (i18n/label :t/owner) :data admins})
(vals (cond-> {} (seq online) (assoc :online {:title (i18n/label :t/online) :data online})
(seq admins) (assoc :owner {:title (i18n/label :t/owner) :data admins}) (seq offline) (assoc :offline {:title (i18n/label :t/offline) :data offline}))))))
(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 (re-frame/reg-sub
:is-participant-selected? :is-participant-selected?
:<- [:group-chat/selected-participants] :<- [:selected-participants]
(fn [selected-participants [_ element]] (fn [selected-participants [_ element]]
(-> selected-participants (-> selected-participants
(contains? element)))) (contains? element))))

View File

@ -98,8 +98,7 @@
(reg-root-key-sub :new-chat-name :new-chat-name) (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/editing? :group-chat-profile/editing?)
(reg-root-key-sub :group-chat-profile/profile :group-chat-profile/profile) (reg-root-key-sub :group-chat-profile/profile :group-chat-profile/profile)
(reg-root-key-sub :group-chat/selected-participants :group-chat/selected-participants) (reg-root-key-sub :selected-participants :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/inputs :chat/inputs)
(reg-root-key-sub :chat/memberships :chat/memberships) (reg-root-key-sub :chat/memberships :chat/memberships)
(reg-root-key-sub :camera-roll/photos :camera-roll/photos) (reg-root-key-sub :camera-roll/photos :camera-roll/photos)

View File

@ -14,9 +14,3 @@
Similar to group-by except that the map values are single objects (depends on key uniqueness)." Similar to group-by except that the map values are single objects (depends on key uniqueness)."
[key coll] [key coll]
(into {} (map #(vector (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,6 +1912,5 @@
"instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”", "instruction-after-qr-generated": "On your other device, navigate to the Syncing screen and select “Scan sync”",
"show-existing-keys": "Show Existing Keys", "show-existing-keys": "Show Existing Keys",
"scan-sync-code": "Scan Sync Code", "scan-sync-code": "Scan Sync Code",
"confirm-selection": "Confirm selection", "confirm-selection": "Confirm selection"
"online": "Online"
} }