Style header group-chats

Signed-off-by: Andrea Maria Piana <andrea.maria.piana@gmail.com>
This commit is contained in:
Andrea Maria Piana 2019-01-15 09:35:06 +01:00
parent 2430992fb4
commit 52ae2c2bfe
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
19 changed files with 331 additions and 259 deletions

View File

@ -21,11 +21,7 @@
(defn active-chats
[contacts chats {:keys [dev-mode?]}]
(reduce (fn [acc [chat-id {:keys [group-chat public? is-active] :as chat}]]
(if (and is-active
;; not a group chat
(or (not (and group-chat (not public?)))
;; if it's a group chat
utils.config/group-chats-enabled?))
(if is-active
(assoc acc chat-id (if-let [contact (get contacts chat-id)]
(-> chat
(assoc :name (:name contact))

View File

@ -242,7 +242,10 @@
(cond
(and (= :group-user-message message-type)
(and (get-in cofx [:db :chats chat-id :contacts from])
(get-in cofx [:db :chats chat-id :members-joined (accounts.db/current-public-key cofx)]))) chat-id
;; Version 0 does not have a concept of joining, so any message is ok
;; otherwise check we joined
(or (= 0 (get-in cofx [:db :chats chat-id :group-chat-local-version]))
(get-in cofx [:db :chats chat-id :members-joined (accounts.db/current-public-key cofx)])))) chat-id
(and (= :public-group-user-message message-type)
(get-in cofx [:db :chats chat-id :public?])) chat-id
(and (= :user-message message-type)

View File

@ -246,3 +246,8 @@
(def v13
(update v12 :properties assoc
:members-joined {:type "string[]"}))
(def v14
(update v13 :properties assoc
:group-chat-local-version {:type :int
:optional true}))

View File

@ -371,6 +371,20 @@
dapp-permissions/v9
contact-recovery/v1])
(def v34 [chat/v14
transport/v7
contact/v3
message/v9
mailserver/v11
mailserver-topic/v1
user-status/v2
membership-update/v1
installation/v3
local-storage/v1
browser/v8
dapp-permissions/v9
contact-recovery/v1])
;; put schemas ordered by version
(def schemas [{:schema v1
:schemaVersion 1
@ -470,4 +484,7 @@
:migration (constantly nil)}
{:schema v33
:schemaVersion 33
:migration (constantly nil)}])
:migration (constantly nil)}
{:schema v34
:schemaVersion 34
:migration migrations/v34}])

View File

@ -339,3 +339,10 @@
content-type (aget last-message "content-type")]
(aset chat "last-message-content" content)
(aset chat "last-message-content-type" content-type)))))))
(defn v34 [old-realm new-realm]
(let [chats (.objects new-realm "chat")]
(dotimes [i (.-length chats)]
(let [chat (aget chats i)
chat-id (aget chat "chat-id")]
(aset chat "group-chat-local-version" 0)))))

View File

@ -52,12 +52,6 @@
js/JSON.parse
(js->clj :keywordize-keys true)))
(defn joined? [public-key {:keys [members-joined]}]
(contains? members-joined public-key))
(defn invited? [my-public-key {:keys [contacts]}]
(contains? contacts my-public-key))
(defn extract-creator
"Takes a chat as an input, returns the creator"
[{:keys [membership-updates]}]
@ -67,6 +61,20 @@
first
:from))
(defn joined-event? [public-key {:keys [members-joined] :as chat}]
(contains? members-joined public-key))
(defn joined? [public-key {:keys [group-chat-local-version] :as chat}]
;; We consider group chats with local version of 0 as joined for local events
(or (zero? group-chat-local-version)
(joined-event? public-key chat)))
(defn creator? [public-key chat]
(= public-key (extract-creator chat)))
(defn invited? [my-public-key {:keys [contacts]}]
(contains? contacts my-public-key))
(defn signature-material
"Transform an update into a signable string"
[chat-id events]
@ -130,13 +138,14 @@
;; If a member has joined is listening to the shared topic and we send there
;; to ourselves we send always on contact-discovery to make sure all devices
;; are informed, in case of dropped messages.
;; We send on the discovery topic to the creator as it's automatically
;; joined or for contact that have not joined yet,
;; for backward compatibility
;; We check that it has explicitly joined, regardless of the local
;; version of the group chat, for backward compatibility
destinations (map (fn [member]
(if (and (joined? member chat)
(not= creator member)
(not= current-public-key member))
(if (and
config/group-chats-publish-to-topic?
(joined-event? member chat)
(not= creator member)
(not= current-public-key member))
{:public-key member
:chat chat-id}
{:public-key member
@ -476,14 +485,11 @@
(fx/defn set-up-topic [cofx chat-id previous-chat]
(let [my-public-key (accounts.db/current-public-key cofx)
new-chat (get-in cofx [:db :chats chat-id])]
(cond
(and (not (joined? my-public-key previous-chat))
(joined? my-public-key new-chat))
(transport.public-chat/join-group-chat cofx chat-id)
(and (joined? my-public-key previous-chat)
(not (joined? my-public-key new-chat)))
(transport.chat/unsubscribe-from-chat cofx chat-id))))
;; If we left the chat, teardown, otherwise upsert
(if (and (joined? my-public-key previous-chat)
(not (joined? my-public-key new-chat)))
(transport.chat/unsubscribe-from-chat cofx chat-id)
(transport.public-chat/join-group-chat cofx chat-id))))
(fx/defn handle-membership-update
"Upsert chat and receive message if valid"
@ -495,8 +501,7 @@
raw-payload
sender-signature]
(let [dev-mode? (get-in cofx [:db :account/account :dev-mode?])]
(when (and config/group-chats-enabled?
(valid-chat-id? chat-id (extract-creator membership-update)))
(when (valid-chat-id? chat-id (extract-creator membership-update))
(let [previous-chat (get-in cofx [:db :chats chat-id])
all-updates (clojure.set/union (set (:membership-updates previous-chat))
(set (:membership-updates membership-update)))
@ -505,15 +510,16 @@
new-group (build-group unwrapped-events)
member? (contains? (:contacts new-group) my-public-key)]
(fx/merge cofx
(models.chat/upsert-chat {:chat-id chat-id
:name (:name new-group)
:is-active (or member?
(get previous-chat :is-active true))
:group-chat true
:membership-updates (into [] all-updates)
:admins (:admins new-group)
:members-joined (:members-joined new-group)
:contacts (:contacts new-group)})
(models.chat/upsert-chat {:chat-id chat-id
:name (:name new-group)
:group-chat-local-version (get previous-chat :group-chat-local-version 1)
:is-active (or member?
(get previous-chat :is-active true))
:group-chat true
:membership-updates (into [] all-updates)
:admins (:admins new-group)
:members-joined (:members-joined new-group)
:contacts (:contacts new-group)})
(add-system-messages chat-id previous-chat new-group)
(set-up-topic chat-id previous-chat)
#(when (and message

View File

@ -113,12 +113,7 @@
:ShhextConfig {:BackupDisabledDataDir (utils.platform/no-backup-directory)
:InstallationID installation-id
:MailServerConfirmations config/mailserver-confirmations-enabled?
:PFSEnabled (or config/pfs-encryption-enabled?
;; We don't check dev-mode? here as
;; otherwise we would have to restart the node
;; when the user enables it
config/group-chats-enabled?
(config/pairing-enabled? true))}
:PFSEnabled true}
:RequireTopics (get-topics network))
(and

View File

@ -160,15 +160,15 @@
:default-chat-icon (styles/default-chat-icon-profile colors/default-chat-color size)
:default-chat-icon-text styles/default-chat-icon-text}])
(defn profile-icon-view [photo-path name color edit? size]
(let [styles {:container {:width size :height size}
:online-view styles/online-view-profile
:online-dot-left styles/online-dot-left-profile
:online-dot-right styles/online-dot-right-profile
:size size
:chat-icon styles/chat-icon-profile
:default-chat-icon (styles/default-chat-icon-profile color size)
:default-chat-icon-text styles/default-chat-icon-text}]
(defn profile-icon-view [photo-path name color edit? size override-styles]
(let [styles (merge {:container {:width size :height size}
:online-view styles/online-view-profile
:online-dot-left styles/online-dot-left-profile
:online-dot-right styles/online-dot-right-profile
:size size
:chat-icon styles/chat-icon-profile
:default-chat-icon (styles/default-chat-icon-profile color size)
:default-chat-icon-text styles/default-chat-icon-text} override-styles)]
[react/view (:container styles)
(when edit?
[react/view (styles/profile-icon-mask size)])
@ -183,4 +183,4 @@
edit? :edit?}]
(let [color colors/default-chat-color
size 56]
[profile-icon-view photo-path name color edit? size]))
[profile-icon-view photo-path name color edit? size {}]))

View File

@ -22,16 +22,13 @@
:icon-opts {:color colors/blue}
:on-press #(re-frame/dispatch [:navigate-to :new-chat])}]
[action-button/action-separator]
;; Hide behind flag (false by default), till everything is fixed in group chats
(when config/group-chats-enabled?
[action-button/action-button
{:label (i18n/label :t/start-group-chat)
:accessibility-label :start-group-chat-button
:icon :icons/contacts
:icon-opts {:color colors/blue}
:on-press #(re-frame/dispatch [:contact.ui/start-group-chat-pressed])}])
(when config/group-chats-enabled?
[action-button/action-separator])
[action-button/action-button
{:label (i18n/label :t/start-group-chat)
:accessibility-label :start-group-chat-button
:icon :icons/contacts
:icon-opts {:color colors/blue}
:on-press #(re-frame/dispatch [:contact.ui/start-group-chat-pressed])}]
[action-button/action-separator]
[action-button/action-button
{:label (i18n/label :t/new-public-group-chat)
:accessibility-label :join-public-chat-button

View File

@ -233,7 +233,34 @@
:text-align :center})
(def empty-chat-text-name
{:color colors/black})
{:margin-bottom 5
:color colors/black})
(def join-button
{:margin-bottom 5})
{:margin-top 24
:margin-bottom 15})
(def group-chat-icon
{:color colors/white
:font-size 40
:font-weight :bold
:line-height 55})
(def group-chat-join-footer
{:position :absolute
:justify-content :center
:margin-bottom 30
:bottom 0})
(def group-chat-join-name
{:color :black
:font-weight :bold
:font-size 22})
(def group-chat-join-container
{:flex 1
:align-items :center
:justify-content :center})
(def decline-chat
{:color colors/blue})

View File

@ -14,6 +14,7 @@
[status-im.ui.screens.chat.message.message :as message]
[status-im.ui.screens.chat.message.options :as message-options]
[status-im.ui.screens.chat.message.datemark :as message-datemark]
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
[status-im.ui.screens.chat.toolbar-content :as toolbar-content]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.button.view :as buttons]
@ -121,18 +122,35 @@
(i18n/label :t/empty-chat-description))]])))
(defn join-chat-button [chat-id]
[buttons/primary-button {:style style/join-button
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
[buttons/secondary-button {:style style/join-button
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
(i18n/label :t/join-group-chat)])
(defview group-chat-join-section [my-public-key {:keys [name chat-id] :as chat}]
(defn decline-chat [chat-id]
[react/touchable-highlight
{:on-press
#(re-frame/dispatch [:group-chats.ui/remove-chat-confirmed chat-id])}
[react/text {:style style/decline-chat}
(i18n/label :t/group-chat-decline-invitation)]])
(defview group-chat-join-section [my-public-key {:keys [name
group-chat
color
chat-id] :as chat}]
(letsubs [contact [:contacts/contact-by-identity (models.group-chats/get-inviter-pk my-public-key chat)]]
[react/view style/empty-chat-container
[join-chat-button chat-id]
[react/text {:style style/empty-chat-text}
[react/text style/empty-chat-container-one-to-one
(i18n/label :t/join-group-chat-description {:username (:name contact)
:group-name name})]]]))
[react/view {:style {:margin-bottom 170}}
[chat-icon.screen/profile-icon-view nil name color false 100 {:default-chat-icon-text style/group-chat-icon}]]
[react/view {:style style/group-chat-join-footer}
[react/view {:style style/group-chat-join-container}
[react/view
[react/text {:style style/group-chat-join-name} name]]
[react/text {:style style/empty-chat-text}
[react/text style/empty-chat-container-one-to-one
(i18n/label :t/join-group-chat-description {:username (:name contact)
:group-name name})]]
[join-chat-button chat-id]
[decline-chat chat-id]]]]))
(defview messages-view [{:keys [group-chat] :as chat} modal?]
(letsubs [messages [:chats/current-chat-messages-stream]

View File

@ -3,9 +3,9 @@
(:require [status-im.ui.screens.desktop.main.views :as main.views]
[status-im.ui.components.react :as react]
[status-im.ui.screens.intro.views :as intro.views]
[status-im.ui.screens.group.add-contacts.views :refer [contact-toggle-list
add-participants-toggle-list]]
[status-im.ui.screens.group.views :refer [new-group]]
[status-im.ui.screens.group.views :refer [contact-toggle-list
new-group
add-participants-toggle-list]]
[status-im.ui.screens.profile.group-chat.views :refer [group-chat-profile]]
[status-im.ui.screens.accounts.create.views :as create.views]
[status-im.ui.screens.accounts.login.views :as login.views]

View File

@ -1,131 +0,0 @@
(ns status-im.ui.screens.group.add-contacts.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.utils.platform :as utils.platform]
[status-im.ui.components.button.view :as buttons]
[status-im.constants :as constants]
[status-im.ui.components.contact.contact :refer [toggle-contact-view]]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :refer [status-bar]]
[status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.screens.group.styles :as styles]))
(defn- on-toggle [allow-new-users? checked? public-key]
(cond
checked?
(re-frame/dispatch [:deselect-contact public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(re-frame/dispatch [:select-contact public-key allow-new-users?])))
(defn- on-toggle-participant [allow-new-users? checked? public-key]
(cond
checked?
(re-frame/dispatch [:deselect-participant public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(re-frame/dispatch [:select-participant public-key allow-new-users?])))
(defn- group-toggle-contact [allow-new-users? contact]
[toggle-contact-view
contact
:is-contact-selected?
(partial on-toggle allow-new-users?)
(and (not (:is-contact-selected? contact))
(not allow-new-users?))])
(defn- group-toggle-participant [allow-new-users? contact]
[toggle-contact-view
contact
:is-participant-selected?
(partial on-toggle-participant allow-new-users?)
;; Disable if not-checked and we don't allow new users
(and (not (:is-participant-selected? contact))
(not allow-new-users?))])
(defn- handle-invite-friends-pressed []
(if utils.platform/desktop?
(re-frame/dispatch [:navigate-to :new-contact])
(list-selection/open-share {:message (i18n/label :t/get-status-at)})))
(defn- toggle-list-toolbar [{:keys [handler count label]} title]
[toolbar/toolbar {}
toolbar/default-nav-back
[toolbar/content-title title]
(when (pos? count)
[toolbar/text-action {:handler handler
:accessibility-label :next-button}
label])])
(defn toggle-list [contacts render-function]
[react/scroll-view {:flex 1}
(if utils.platform/desktop?
(for [contact contacts]
^{:key (:public-key contact)}
(render-function contact))
[list/flat-list {:style styles/contacts-list
:data contacts
:key-fn :address
:render-fn render-function
:keyboardShouldPersistTaps :always}])])
(defn no-contacts []
[react/view {:style {:flex 1
:justify-content :center
:align-items :center}}
[react/text
{:style styles/no-contact-text}
(i18n/label :t/group-chat-no-contacts)]
[buttons/secondary-button {:on-press handle-invite-friends-pressed} (i18n/label :t/invite-friends)]])
(defn number-of-participants-disclaimer [number-of-participants-available]
[react/view {:style styles/number-of-participants-disclaimer}
[react/text (if (> number-of-participants-available
0)
(i18n/label-pluralize number-of-participants-available :t/available-participants)
(i18n/label :t/no-more-participants-available))]])
;; Start group chat
(defview contact-toggle-list []
(letsubs [contacts [:contacts/all-added-people-contacts]
selected-contacts-count [:selected-contacts-count]]
[react/keyboard-avoiding-view {:style styles/group-container}
[status-bar]
[toggle-list-toolbar {:handler #(re-frame/dispatch [:navigate-to :new-group])
:label (i18n/label :t/next)
:count (pos? selected-contacts-count)}
(i18n/label :t/group-chat)]
(when (seq contacts)
[number-of-participants-disclaimer (- (dec constants/max-group-chat-participants) selected-contacts-count)])
(if (seq contacts)
[toggle-list contacts (partial group-toggle-contact (< selected-contacts-count (dec constants/max-group-chat-participants)))]
[no-contacts])]))
;; Add participants to existing group chat
(defview add-participants-toggle-list []
(letsubs [contacts [:contacts/all-contacts-not-in-current-chat]
{:keys [name] :as current-chat} [:chats/current-chat]
selected-contacts-count [:selected-participants-count]]
(let [current-participants-count (count (:contacts current-chat))]
[react/keyboard-avoiding-view {:style styles/group-container}
[status-bar]
[toggle-list-toolbar {:count selected-contacts-count
:handler #(do
(re-frame/dispatch [:group-chats.ui/add-members-pressed])
(re-frame/dispatch [:navigate-back]))
:label (i18n/label :t/add)}
name]
[number-of-participants-disclaimer (- constants/max-group-chat-participants current-participants-count)]
(when (seq contacts)
[toggle-list contacts (partial group-toggle-participant (< (+ current-participants-count
selected-contacts-count) constants/max-group-chat-participants))])])))

View File

@ -30,3 +30,22 @@
:font-size 12
:margin-horizontal 17})
(def bottom-container
{:padding-horizontal 12
:padding-vertical 15})
(def toolbar-header-container
{:align-items :center})
(def toolbar-header
{:font-size 15
:color colors/black})
(def toolbar-sub-header
{:font-size 15
:color colors/gray})
(def no-contacts
{:flex 1
:justify-content :center
:align-items :center})

View File

@ -1,8 +1,17 @@
(ns status-im.ui.screens.group.views
(:require-macros [status-im.utils.views :as views])
(:require [cljs.spec.alpha :as spec]
[clojure.string :as string]
[re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.screens.main-tabs.styles :as main-tabs.styles]
[status-im.ui.components.styles :as components.styles]
[status-im.constants :as constants]
[status-im.utils.platform :as utils.platform]
[status-im.ui.components.contact.contact :refer [toggle-contact-view]]
[status-im.ui.components.button.view :as buttons]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.react :as react]
[status-im.ui.components.list.views :as list]
[status-im.ui.components.status-bar.view :as status-bar]
@ -12,38 +21,123 @@
[status-im.ui.screens.add-new.styles :as add-new.styles]
[status-im.ui.screens.group.styles :as styles]))
(views/defview group-name-view []
(views/letsubs [new-group-name [:get :new-chat-name]]
[react/view add-new.styles/input-container
[react/text-input
{:auto-focus true
:on-change-text #(re-frame/dispatch [:set :new-chat-name %])
:default-value new-group-name
:placeholder (i18n/label :t/set-a-topic)
:style add-new.styles/input
:accessibility-label :chat-name-input}]]))
(views/defview group-name-view [new-group-name]
[react/view add-new.styles/input-container
[react/text-input
{:auto-focus true
:on-change-text #(re-frame/dispatch [:set :new-chat-name %])
:default-value new-group-name
:placeholder (i18n/label :t/set-a-topic)
:style add-new.styles/input
:accessibility-label :chat-name-input}]])
(defn- render-contact [contact]
[contact/contact-view {:contact contact
:style styles/contact
:accessibility-label :chat-member-item}])
(defn- toolbar [group-name save-btn-enabled?]
(defn- toolbar [header sub-header]
[toolbar/toolbar {}
toolbar/default-nav-back
[toolbar/content-title (i18n/label :t/group-chat)]
(when save-btn-enabled?
(let [handler #(re-frame/dispatch [:group-chats.ui/create-pressed group-name])]
(if platform/android?
[toolbar/actions [{:icon :icons/ok
:icon-opts {:color :blue
:accessibility-label :create-button}
:handler handler}]]
[toolbar/text-action {:handler handler
:accessibility-label :create-button}
(i18n/label :t/create)])))])
[react/view {:style styles/toolbar-header-container}
[react/view
[react/text {:style styles/toolbar-header} header]]
[react/view
[react/text {:style styles/toolbar-sub-header} sub-header]]]])
;; New Group Chat
(defn- on-toggle [allow-new-users? checked? public-key]
(cond
checked?
(re-frame/dispatch [:deselect-contact public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(re-frame/dispatch [:select-contact public-key allow-new-users?])))
(defn- on-toggle-participant [allow-new-users? checked? public-key]
(cond
checked?
(re-frame/dispatch [:deselect-participant public-key allow-new-users?])
;; Only allow new users if not reached the maximum
(and (not checked?)
allow-new-users?)
(re-frame/dispatch [:select-participant public-key allow-new-users?])))
(defn- group-toggle-contact [allow-new-users? contact]
[toggle-contact-view
contact
:is-contact-selected?
(partial on-toggle allow-new-users?)
(and (not (:is-contact-selected? contact))
(not allow-new-users?))])
(defn- group-toggle-participant [allow-new-users? contact]
[toggle-contact-view
contact
:is-participant-selected?
(partial on-toggle-participant allow-new-users?)
;; Disable if not-checked and we don't allow new users
(and (not (:is-participant-selected? contact))
(not allow-new-users?))])
(defn- handle-invite-friends-pressed []
(if utils.platform/desktop?
(re-frame/dispatch [:navigate-to :new-contact])
(list-selection/open-share {:message (i18n/label :t/get-status-at)})))
(defn toggle-list [contacts render-function]
[react/scroll-view {:flex 1}
(if utils.platform/desktop?
(for [contact contacts]
^{:key (:public-key contact)}
(render-function contact))
[list/flat-list {:style styles/contacts-list
:data contacts
:key-fn :address
:render-fn render-function
:keyboardShouldPersistTaps :always}])])
(defn no-contacts []
[react/view {:style styles/no-contacts}
[react/text
{:style styles/no-contact-text}
(i18n/label :t/group-chat-no-contacts)]
[buttons/secondary-button {:on-press handle-invite-friends-pressed} (i18n/label :t/invite-friends)]])
(views/defview bottom-container [{:keys [on-press disabled label]}]
[react/view {:style main-tabs.styles/tabs-container}
[react/view {:style components.styles/flex}]
[react/view {:style styles/bottom-container}
[components.common/bottom-button
{:forward? true
:accessibility-label :next-button
:label label
:disabled? disabled
:on-press on-press}]]])
;; Start group chat
(views/defview contact-toggle-list []
(views/letsubs [contacts [:contacts/all-added-people-contacts]
selected-contacts-count [:selected-contacts-count]]
[react/keyboard-avoiding-view {:style styles/group-container}
[status-bar/status-bar]
[toolbar
(i18n/label :t/new-group-chat)
(i18n/label :t/group-chat-members-count
{:selected selected-contacts-count
:max (dec constants/max-group-chat-participants)})]
(if (seq contacts)
[toggle-list contacts (partial group-toggle-contact (< selected-contacts-count (dec constants/max-group-chat-participants)))]
[no-contacts])
[bottom-container {:on-press #(re-frame/dispatch [:navigate-to :new-group])
:disabled (zero? selected-contacts-count)
:label (i18n/label :t/next)}]]))
;; Set name of new group-chat
(views/defview new-group []
(views/letsubs [contacts [:selected-group-contacts]
group-name [:get :new-chat-name]]
@ -51,13 +145,42 @@
[react/keyboard-avoiding-view (merge {:behavior :padding}
styles/group-container)
[status-bar/status-bar]
[toolbar group-name save-btn-enabled?]
[toolbar
(i18n/label :t/new-group-chat)
(i18n/label :t/group-chat-members-count
{:selected (count contacts)
:max (dec constants/max-group-chat-participants)})]
[group-name-view]
[list/list-with-label {:flex 1}
(i18n/label :t/members-title)
[list/flat-list {:data contacts
:key-fn :address
:render-fn render-contact
:bounces false
:keyboard-should-persist-taps :always
:enable-empty-sections true}]]])))
[react/scroll-view
[list/list-with-label {:flex 1}
(i18n/label :t/members-title)
[list/flat-list {:data contacts
:key-fn :address
:render-fn render-contact
:bounces false
:keyboard-should-persist-taps :always
:enable-empty-sections true}]]]
[bottom-container {:on-press #(re-frame/dispatch [:group-chats.ui/create-pressed group-name])
:disabled (string/blank? group-name)
:label (i18n/label :t/create-group-chat)}]])))
;; Add participants to existing group chat
(views/defview add-participants-toggle-list []
(views/letsubs [contacts [:contacts/all-contacts-not-in-current-chat]
{:keys [name] :as current-chat} [:chats/current-chat]
selected-contacts-count [:selected-participants-count]]
(let [current-participants-count (count (:contacts current-chat))]
[react/keyboard-avoiding-view {:style styles/group-container}
[status-bar/status-bar]
[toolbar
name
(i18n/label :t/group-chat-members-count
{:selected (dec (+ current-participants-count selected-contacts-count))
:max (dec constants/max-group-chat-participants)})]
(when (seq contacts)
[toggle-list contacts (partial group-toggle-participant (< (+ current-participants-count
selected-contacts-count) constants/max-group-chat-participants))])
[bottom-container {:on-press
#(re-frame/dispatch [:group-chats.ui/add-members-pressed])
:disabled (zero? selected-contacts-count)
:label (i18n/label :t/add)}]])))

View File

@ -20,9 +20,9 @@
[status-im.ui.screens.qr-scanner.views :refer [qr-scanner]]
[status-im.ui.screens.group.views :refer [new-group]]
[status-im.ui.screens.group.add-contacts.views :refer [contact-toggle-list
add-participants-toggle-list]]
[status-im.ui.screens.group.views :refer [new-group
contact-toggle-list
add-participants-toggle-list]]
[status-im.ui.screens.profile.user.views :as profile.user]
[status-im.ui.screens.profile.contact.views :as profile.contact]
[status-im.ui.screens.profile.group-chat.views :as profile.group-chat]

View File

@ -17,7 +17,7 @@
(def bootnodes-settings-enabled? (enabled? (get-config :BOOTNODES_SETTINGS_ENABLED "1")))
(def rpc-networks-only? (enabled? (get-config :RPC_NETWORKS_ONLY "1")))
(def group-chats-enabled? (enabled? (get-config :GROUP_CHATS_ENABLED "0")))
(def group-chats-publish-to-topic? (enabled? (get-config :GROUP_CHATS_PUBLISH_TO_TOPIC "0")))
(defn pairing-enabled? [dev-mode?]
(and (enabled? (get-config :PAIRING_ENABLED "0"))
(or dev-mode? platform/desktop?)))

View File

@ -15,17 +15,4 @@
cofx {:db {:accounts/accounts {address {:installation-id "id"}}}}]
(testing "installation-id"
(let [actual (parse-node-config (node/start cofx address))]
(is (= "id" (:InstallationID actual)))))
(testing "pfs & group chats disabled"
(with-redefs [config/pfs-encryption-enabled? false
config/group-chats-enabled? false]
(let [actual (parse-node-config (node/start cofx address))]
(is (not (:PFSEnabled actual)))))
(testing "pfs is enabled"
(with-redefs [config/pfs-encryption-enabled? true]
(let [actual (parse-node-config (node/start cofx address))]
(is (:PFSEnabled actual)))))
(testing "group chats is enabled"
(with-redefs [config/group-chats-enabled? true]
(let [actual (parse-node-config (node/start cofx address))]
(is (:PFSEnabled actual))))))))
(is (= "id" (:InstallationID actual)))))))

View File

@ -47,7 +47,10 @@
},
"no-more-participants-available": "You can't add anymore participants",
"join-group-chat-description": "{{username}} invited you to join the group {{group-name}}",
"join-group-chat": "Join chat",
"join-group-chat": "Join group",
"create-group-chat": "Create group chat",
"group-chat-decline-invitation": "Decline invitation",
"group-chat-members-count": "{{selected}}/{{max}} members",
"group-chat-created": "*{{member}}* created the group *{{name}}*",
"group-chat-admin": "Admin",
"group-chat-name-changed": "*{{member}}* changed the group's name to *{{name}}*",