[ISSUE #3313] Migrated public chat creation flow
Signed-off-by: Julien Eluard <julien.eluard@gmail.com>
This commit is contained in:
parent
cc6414c204
commit
33f1d8d26b
|
@ -2,20 +2,19 @@
|
|||
(:require [clojure.set :as set]
|
||||
[cljs.core.async :as async]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.async :as async-utils]
|
||||
[status-im.chat.models :as model]
|
||||
[status-im.chat.console :as console-chat]
|
||||
[status-im.chat.constants :as chat-const]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.pending-messages :as pending-messages-store]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.models :as models]
|
||||
[status-im.chat.console :as console]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.data-store.pending-messages :as pending-messages]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.async :as utils.async]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
status-im.chat.events.commands
|
||||
status-im.chat.events.requests
|
||||
status-im.chat.events.animation
|
||||
|
@ -31,76 +30,76 @@
|
|||
:stored-unviewed-messages
|
||||
(fn [cofx _]
|
||||
(assoc cofx :stored-unviewed-messages
|
||||
(messages-store/get-unviewed (-> cofx :db :current-public-key)))))
|
||||
(messages/get-unviewed (-> cofx :db :current-public-key)))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:get-stored-message
|
||||
(fn [cofx _]
|
||||
(assoc cofx :get-stored-message messages-store/get-by-id)))
|
||||
(assoc cofx :get-stored-message messages/get-by-id)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:get-stored-messages
|
||||
(fn [cofx _]
|
||||
(assoc cofx :get-stored-messages messages-store/get-by-chat-id)))
|
||||
(assoc cofx :get-stored-messages messages/get-by-chat-id)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:stored-message-ids
|
||||
(fn [cofx _]
|
||||
(assoc cofx :stored-message-ids (messages-store/get-stored-message-ids))))
|
||||
(assoc cofx :stored-message-ids (messages/get-stored-message-ids))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:all-stored-chats
|
||||
(fn [cofx _]
|
||||
(assoc cofx :all-stored-chats (chats-store/get-all))))
|
||||
(assoc cofx :all-stored-chats (chats/get-all))))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:get-stored-chat
|
||||
(fn [cofx _]
|
||||
(assoc cofx :get-stored-chat chats-store/get-by-id)))
|
||||
(assoc cofx :get-stored-chat chats/get-by-id)))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:inactive-chat-ids
|
||||
(fn [cofx _]
|
||||
(assoc cofx :inactive-chat-ids (chats-store/get-inactive-ids))))
|
||||
(assoc cofx :inactive-chat-ids (chats/get-inactive-ids))))
|
||||
|
||||
;;;; Effects
|
||||
|
||||
(def ^:private realm-queue (async-utils/task-queue 2000))
|
||||
(def ^:private realm-queue (utils.async/task-queue 2000))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:update-message
|
||||
(fn [message]
|
||||
(async/go (async/>! realm-queue #(messages-store/update-message message)))))
|
||||
(async/go (async/>! realm-queue #(messages/update-message message)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-message
|
||||
(fn [message]
|
||||
(async/go (async/>! realm-queue #(messages-store/save message)))))
|
||||
(async/go (async/>! realm-queue #(messages/save message)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:delete-messages
|
||||
(fn [chat-id]
|
||||
(async/go (async/>! realm-queue #(messages-store/delete-by-chat-id chat-id)))))
|
||||
(async/go (async/>! realm-queue #(messages/delete-by-chat-id chat-id)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:delete-pending-messages
|
||||
(fn [chat-id]
|
||||
(async/go (async/>! realm-queue #(pending-messages-store/delete-all-by-chat-id chat-id)))))
|
||||
(async/go (async/>! realm-queue #(pending-messages/delete-all-by-chat-id chat-id)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:save-chat
|
||||
(fn [chat]
|
||||
(async/go (async/>! realm-queue #(chats-store/save chat)))))
|
||||
(async/go (async/>! realm-queue #(chats/save chat)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:deactivate-chat
|
||||
(fn [chat-id]
|
||||
(async/go (async/>! realm-queue #(chats-store/set-inactive chat-id)))))
|
||||
(async/go (async/>! realm-queue #(chats/set-inactive chat-id)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:delete-chat
|
||||
(fn [chat-id]
|
||||
(async/go (async/>! realm-queue #(chats-store/delete chat-id)))))
|
||||
(async/go (async/>! realm-queue #(chats/delete chat-id)))))
|
||||
|
||||
(re-frame/reg-fx
|
||||
:protocol-send-seen
|
||||
|
@ -118,20 +117,20 @@
|
|||
:set-chat-ui-props
|
||||
[re-frame/trim-v]
|
||||
(fn [db [kvs]]
|
||||
(model/set-chat-ui-props db kvs)))
|
||||
(models/set-chat-ui-props db kvs)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:toggle-chat-ui-props
|
||||
[re-frame/trim-v]
|
||||
(fn [db [ui-element]]
|
||||
(model/toggle-chat-ui-prop db ui-element)))
|
||||
(models/toggle-chat-ui-prop db ui-element)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:show-message-details
|
||||
[re-frame/trim-v]
|
||||
(fn [db [details]]
|
||||
(model/set-chat-ui-props db {:show-bottom-info? true
|
||||
:bottom-info details})))
|
||||
(models/set-chat-ui-props db {:show-bottom-info? true
|
||||
:bottom-info details})))
|
||||
|
||||
(def index-messages (partial into {} (map (juxt :message-id identity))))
|
||||
|
||||
|
@ -146,7 +145,7 @@
|
|||
(update-in [:chats current-chat-id :messages] merge new-messages)
|
||||
(update-in [:chats current-chat-id :not-loaded-message-ids] #(apply disj % (keys new-messages)))
|
||||
(assoc-in [:chats current-chat-id :all-loaded?]
|
||||
(> const/default-number-of-messages (count new-messages))))}))))
|
||||
(> constants/default-number-of-messages (count new-messages))))}))))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:message-appeared
|
||||
|
@ -156,17 +155,17 @@
|
|||
|
||||
(defn init-console-chat
|
||||
[{:keys [chats] :accounts/keys [current-account-id] :as db}]
|
||||
(if (chats const/console-chat-id)
|
||||
(if (chats constants/console-chat-id)
|
||||
{:db db}
|
||||
(cond-> {:db (-> db
|
||||
(assoc :current-chat-id const/console-chat-id)
|
||||
(update :chats assoc const/console-chat-id console-chat/chat))
|
||||
:dispatch-n [[:add-contacts [console-chat/contact]]]
|
||||
:save-chat console-chat/chat
|
||||
:save-all-contacts [console-chat/contact]}
|
||||
(assoc :current-chat-id constants/console-chat-id)
|
||||
(update :chats assoc constants/console-chat-id console/chat))
|
||||
:dispatch-n [[:add-contacts [console/contact]]]
|
||||
:save-chat console/chat
|
||||
:save-all-contacts [console/contact]}
|
||||
|
||||
(not current-account-id)
|
||||
(update :dispatch-n concat [[:chat-received-message/add-when-commands-loaded console-chat/intro-message1]]))))
|
||||
(update :dispatch-n concat [[:chat-received-message/add-when-commands-loaded console/intro-message1]]))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:init-console-chat
|
||||
|
@ -238,8 +237,8 @@
|
|||
:show-mnemonic
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db]} [mnemonic signing-phrase]]
|
||||
(let [crazy-math-message? (contains? (get-in db [:chats chat-const/console-chat-id]) chat-const/crazy-math-message-id)
|
||||
messages-events (->> (console-chat/passphrase-messages mnemonic signing-phrase crazy-math-message?)
|
||||
(let [crazy-math-message? (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/crazy-math-message-id)
|
||||
messages-events (->> (console/passphrase-messages mnemonic signing-phrase crazy-math-message?)
|
||||
(mapv #(vector :chat-received-message/add %)))]
|
||||
{:dispatch-n messages-events})))
|
||||
|
||||
|
@ -247,30 +246,28 @@
|
|||
(handlers/register-handler-fx
|
||||
:account-generation-message
|
||||
(fn [{:keys [db]} _]
|
||||
(when-not (contains? (get-in db [:chats chat-const/console-chat-id]) chat-const/passphrase-message-id)
|
||||
{:dispatch [:chat-received-message/add console-chat/account-generation-message]})))
|
||||
(when-not (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/passphrase-message-id)
|
||||
{:dispatch [:chat-received-message/add console/account-generation-message]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:move-to-internal-failure-message
|
||||
(fn [{:keys [db]} _]
|
||||
(when-not (contains? (get-in db [:chats chat-const/console-chat-id]) chat-const/move-to-internal-failure-message-id)
|
||||
{:dispatch [:chat-received-message/add console-chat/move-to-internal-failure-message]})))
|
||||
(when-not (contains? (get-in db [:chats chat.constants/console-chat-id]) chat.constants/move-to-internal-failure-message-id)
|
||||
{:dispatch [:chat-received-message/add console/move-to-internal-failure-message]})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:browse-link-from-message
|
||||
(fn [{{:contacts/keys [contacts]} :db} [_ link]]
|
||||
(fn [_ [_ link]]
|
||||
{:browse link}))
|
||||
|
||||
(defn preload-chat-data
|
||||
"Takes coeffects map and chat-id, returns effects necessary when navigating to chat"
|
||||
[{:keys [db]} chat-id]
|
||||
(let [messages (get-in db [:chats chat-id :messages])
|
||||
chat-loaded-event (get-in db [:chats chat-id :chat-loaded-event])
|
||||
jail-loaded? (get-in db [:contacts/contacts chat-id :jail-loaded?])]
|
||||
(let [chat-loaded-event (get-in db [:chats chat-id :chat-loaded-event])]
|
||||
(cond-> {:db (-> db
|
||||
(assoc :current-chat-id chat-id)
|
||||
(assoc-in [:chats chat-id :was-opened?] true)
|
||||
(model/set-chat-ui-props {:validation-messages nil})
|
||||
(models/set-chat-ui-props {:validation-messages nil})
|
||||
(update-in [:chats chat-id] dissoc :chat-loaded-event))}
|
||||
|
||||
chat-loaded-event
|
||||
|
@ -282,7 +279,7 @@
|
|||
(fn [{:keys [db] :as cofx} [chat-id event]]
|
||||
(if (get (:chats db) chat-id)
|
||||
{:db (assoc-in db [:chats chat-id :chat-loaded-event] event)}
|
||||
(-> (model/add-chat cofx chat-id) ; chat not created yet, we have to create it
|
||||
(-> (models/add-chat cofx chat-id) ; chat not created yet, we have to create it
|
||||
(assoc-in [:db :chats chat-id :chat-loaded-event] event)))))
|
||||
|
||||
;; TODO(janherich): remove this unnecessary event in the future (only model function `add-chat` will stay)
|
||||
|
@ -290,7 +287,7 @@
|
|||
:add-chat
|
||||
[(re-frame/inject-cofx :get-stored-chat) re-frame/trim-v]
|
||||
(fn [cofx [chat-id chat-props]]
|
||||
(model/add-chat cofx chat-id chat-props)))
|
||||
(models/add-chat cofx chat-id chat-props)))
|
||||
|
||||
(defn navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
|
@ -316,7 +313,7 @@
|
|||
(when (not= (:current-public-key db) contact-id) ; don't allow to open chat with yourself
|
||||
(if (get (:chats db) contact-id)
|
||||
(navigate-to-chat cofx contact-id navigation-replace?) ; existing chat, just preload and displey
|
||||
(let [add-chat-fx (model/add-chat cofx contact-id)] ; new chat, create before preload & display
|
||||
(let [add-chat-fx (models/add-chat cofx contact-id)] ; new chat, create before preload & display
|
||||
(merge add-chat-fx
|
||||
(navigate-to-chat (assoc cofx :db (:db add-chat-fx))
|
||||
contact-id
|
||||
|
@ -327,7 +324,7 @@
|
|||
:update-chat!
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [chat]]
|
||||
(model/update-chat cofx chat)))
|
||||
(models/update-chat cofx chat)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:remove-chat
|
||||
|
@ -344,3 +341,19 @@
|
|||
(assoc :delete-chat chat-id)
|
||||
(not debug?)
|
||||
(assoc :deactivate-chat chat-id)))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:delete-chat
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [chat-id]]
|
||||
(-> (models/remove-chat cofx chat-id)
|
||||
(update :db navigation/replace-view :home))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:delete-chat?
|
||||
[re-frame/trim-v]
|
||||
(fn [_ [chat-id group?]]
|
||||
{:show-confirmation {:title (i18n/label :t/delete-confirmation)
|
||||
:content (i18n/label (if group? :t/delete-group-chat-confirmation :t/delete-chat-confirmation))
|
||||
:confirm-button-text (i18n/label :t/delete)
|
||||
:on-accept #(re-frame/dispatch [:delete-chat chat-id])}}))
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
(ns status-im.chat.handlers
|
||||
(:require [re-frame.core :refer [after dispatch reg-fx]]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.components.styles :refer [default-chat-color]]
|
||||
[status-im.chat.constants :as chat-consts]
|
||||
[status-im.chat.models :as chat]
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as models]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.constants :refer [text-content-type
|
||||
content-type-command
|
||||
content-type-command-request
|
||||
console-chat-id]]
|
||||
[status-im.ui.components.styles :as components.styles]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.utils.handlers :refer [register-handler register-handler-fx] :as u]
|
||||
status-im.chat.events))
|
||||
|
||||
(register-handler
|
||||
(handlers/register-handler
|
||||
:leave-group-chat
|
||||
;; todo order of operations tbd
|
||||
(after (fn [_ _] (dispatch [:navigation-replace :home])))
|
||||
(u/side-effect!
|
||||
(re-frame/after (fn [_ _] (re-frame/dispatch [:navigation-replace :home])))
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [web3 current-chat-id chats current-public-key]} _]
|
||||
(let [{:keys [public-key private-key public?]} (chats current-chat-id)]
|
||||
(protocol/stop-watching-group!
|
||||
|
@ -32,31 +27,39 @@
|
|||
:private private-key}
|
||||
:message {:from current-public-key
|
||||
:message-id (random/id)}})))
|
||||
(dispatch [:remove-chat current-chat-id]))))
|
||||
(re-frame/dispatch [:remove-chat current-chat-id]))))
|
||||
|
||||
(register-handler :update-group-message
|
||||
(u/side-effect!
|
||||
(handlers/register-handler-fx
|
||||
:leave-group-chat?
|
||||
(fn []
|
||||
{:show-confirmation {:title (i18n/label :t/leave-confirmation)
|
||||
:content (i18n/label :t/leave-group-chat-confirmation)
|
||||
:confirm-button-text (i18n/label :t/leave)
|
||||
:on-accept #(re-frame/dispatch [:leave-group-chat])}}))
|
||||
|
||||
(handlers/register-handler :update-group-message
|
||||
(handlers/side-effect!
|
||||
(fn [{:keys [current-public-key web3 chats]}
|
||||
[_ {:keys [from]
|
||||
{:keys [group-id keypair timestamp]} :payload}]]
|
||||
(let [{:keys [private public]} keypair
|
||||
{:keys [group-admin is-active] :as chat} (get chats group-id)]
|
||||
(when (and (= from group-admin)
|
||||
(when (and (= from group-admin
|
||||
(or (nil? chat)
|
||||
(chat/new-update? chat timestamp)))
|
||||
(dispatch [:update-chat! {:chat-id group-id
|
||||
:public-key public
|
||||
:private-key private
|
||||
:updated-at timestamp}])
|
||||
(models/new-update? chat timestamp))))
|
||||
(re-frame/dispatch [:update-chat! {:chat-id group-id
|
||||
:public-key public
|
||||
:private-key private
|
||||
:updated-at timestamp}])
|
||||
(when is-active
|
||||
(protocol/start-watching-group!
|
||||
{:web3 web3
|
||||
:group-id group-id
|
||||
:identity current-public-key
|
||||
:keypair keypair
|
||||
:callback #(dispatch [:incoming-message %1 %2])})))))))
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])})))))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::start-watching-group
|
||||
(fn [{:keys [group-id web3 current-public-key keypair]}]
|
||||
(protocol/start-watching-group!
|
||||
|
@ -64,15 +67,15 @@
|
|||
:group-id group-id
|
||||
:identity current-public-key
|
||||
:keypair keypair
|
||||
:callback #(dispatch [:incoming-message %1 %2])})))
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])})))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:create-new-public-chat
|
||||
(fn [{:keys [db]} [_ topic]]
|
||||
(let [exists? (boolean (get-in db [:chats topic]))
|
||||
chat {:chat-id topic
|
||||
:name topic
|
||||
:color default-chat-color
|
||||
:color components.styles/default-chat-color
|
||||
:group-chat true
|
||||
:public? true
|
||||
:is-active true
|
||||
|
@ -86,7 +89,7 @@
|
|||
{:dispatch-n [[:navigate-to-clean :home]
|
||||
[:navigate-to-chat topic]]}))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::start-listen-group
|
||||
(fn [{:keys [new-chat web3 current-public-key]}]
|
||||
(let [{:keys [chat-id public-key private-key contacts name]} new-chat
|
||||
|
@ -108,7 +111,7 @@
|
|||
:identity current-public-key
|
||||
:keypair {:public public-key
|
||||
:private private-key}
|
||||
:callback #(dispatch [:incoming-message %1 %2])}))))
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])}))))
|
||||
|
||||
(defn group-name-from-contacts [contacts selected-contacts username]
|
||||
(->> (select-keys contacts selected-contacts)
|
||||
|
@ -130,14 +133,14 @@
|
|||
:public-key public
|
||||
:private-key private
|
||||
:name chat-name
|
||||
:color default-chat-color
|
||||
:color components.styles/default-chat-color
|
||||
:group-chat true
|
||||
:group-admin current-public-key
|
||||
:is-active true
|
||||
:timestamp (random/timestamp)
|
||||
:contacts selected-contacts'}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:create-new-group-chat-and-open
|
||||
(fn [{:keys [db]} [_ group-name]]
|
||||
(let [new-chat (prepare-group-chat (select-keys db [:group/selected-contacts :current-public-key :username
|
||||
|
@ -152,7 +155,7 @@
|
|||
:dispatch-n [[:navigate-to-clean :home]
|
||||
[:navigate-to-chat (:chat-id new-chat)]]})))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:group-chat-invite-received
|
||||
(fn [{{:keys [current-public-key] :as db} :db}
|
||||
[_ {:keys [from]
|
||||
|
@ -173,7 +176,7 @@
|
|||
:timestamp timestamp
|
||||
:is-active true}]
|
||||
(when (or (nil? chat)
|
||||
(chat/new-update? chat timestamp))
|
||||
(models/new-update? chat timestamp))
|
||||
{::start-watching-group (merge {:group-id group-id
|
||||
:keypair keypair}
|
||||
(select-keys db [:web3 :current-public-key]))
|
||||
|
@ -181,7 +184,7 @@
|
|||
[:update-chat! new-chat]
|
||||
[:add-chat group-id new-chat])})))))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:show-profile
|
||||
(fn [{db :db} [_ identity]]
|
||||
{:db (assoc db :contacts/identity identity)
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
(update-in db [:chat-ui-props current-chat-id ui-element] not))
|
||||
|
||||
(defn- create-new-chat
|
||||
[{:keys [db now] :as cofx} chat-id]
|
||||
[{:keys [db now]} chat-id]
|
||||
(let [name (get-in db [:contacts/contacts chat-id :name])]
|
||||
{:chat-id chat-id
|
||||
:name (or name (gfycat/generate-gfy chat-id))
|
||||
|
@ -28,7 +28,7 @@
|
|||
([cofx chat-id]
|
||||
(add-chat cofx chat-id {}))
|
||||
([{:keys [db get-stored-chat] :as cofx} chat-id chat-props]
|
||||
(let [{:keys [chats deleted-chats]} db
|
||||
(let [{:keys [deleted-chats]} db
|
||||
new-chat (merge (if (get deleted-chats chat-id)
|
||||
(assoc (get-stored-chat chat-id) :is-active true)
|
||||
(create-new-chat cofx chat-id))
|
||||
|
@ -64,3 +64,16 @@
|
|||
(and (> timestamp added-to-at)
|
||||
(> timestamp removed-at)
|
||||
(> timestamp removed-from-at)))
|
||||
|
||||
(defn remove-chat [{:keys [db]} chat-id]
|
||||
(let [{:keys [chat-id group-chat debug?]} (get-in db [:chats chat-id])]
|
||||
(cond-> {:db (-> db
|
||||
(update :chats dissoc chat-id)
|
||||
(update :deleted-chats (fnil conj #{}) chat-id))
|
||||
:delete-pending-messages chat-id}
|
||||
(or group-chat debug?)
|
||||
(assoc :delete-messages chat-id)
|
||||
debug?
|
||||
(assoc :delete-chat chat-id)
|
||||
(not debug?)
|
||||
(assoc :deactivate-chat chat-id))))
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
(ns status-im.chat.new-public-chat.db
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
status-im.utils.db
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
[clojure.string :as string]
|
||||
[status-im.utils.homoglyph :as utils]))
|
||||
|
||||
(defn legal-name? [username]
|
||||
(let [username (some-> username string/trim)]
|
||||
(not (utils/matches username console-chat-id))))
|
||||
|
||||
(spec/def ::legal-name legal-name?)
|
||||
|
||||
(spec/def ::name (spec/and :global/not-empty-string
|
||||
::legal-name))
|
||||
|
||||
(spec/def ::topic (spec/and :global/not-empty-string
|
||||
::legal-name
|
||||
(partial re-matches #"[a-z0-9\-]+")))
|
|
@ -1,46 +0,0 @@
|
|||
(ns status-im.chat.new-public-chat.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(def group-chat-name-input
|
||||
{:font-size 17
|
||||
:padding-bottom 0
|
||||
:letter-spacing -0.2
|
||||
:color common/text1-color})
|
||||
|
||||
(defstyle group-chat-topic-input
|
||||
{:font-size 14
|
||||
:line-height 16
|
||||
:color common/text1-color
|
||||
:padding-left 13
|
||||
:ios {:padding-bottom 0}})
|
||||
|
||||
(defstyle topic-hash-style
|
||||
{:width 10
|
||||
:position :absolute
|
||||
:android {:top 8 :left 3}
|
||||
:ios {:top 6 :left 3}})
|
||||
|
||||
(def topic-hash
|
||||
(merge group-chat-name-input
|
||||
topic-hash-style))
|
||||
|
||||
(def group-chat-name-wrapper
|
||||
{:padding-top 0
|
||||
:height 40
|
||||
:padding-bottom 0})
|
||||
|
||||
(def group-container
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:background-color common/color-white})
|
||||
|
||||
(def chat-name-container
|
||||
{:padding-left 16
|
||||
:margin-top 10})
|
||||
|
||||
(defstyle members-text
|
||||
{:color common/color-gray4
|
||||
:ios {:letter-spacing -0.2
|
||||
:font-size 16}
|
||||
:android {:font-size 14}})
|
|
@ -1,57 +0,0 @@
|
|||
(ns status-im.chat.new-public-chat.view
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :refer [dispatch]]
|
||||
status-im.utils.db
|
||||
[status-im.ui.components.react :as react :refer [text]]
|
||||
[status-im.ui.components.text-field.view :refer [text-field]]
|
||||
[status-im.ui.components.styles :as components.styles]
|
||||
[status-im.ui.components.status-bar.view :refer [status-bar]]
|
||||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.chat.new-public-chat.styles :as styles]
|
||||
[status-im.chat.new-public-chat.db :as v]
|
||||
[status-im.i18n :refer [label]]
|
||||
[cljs.spec.alpha :as spec]))
|
||||
|
||||
(defview new-public-chat-toolbar []
|
||||
(letsubs [topic [:get :public-group-topic]]
|
||||
(let [create-btn-enabled? (spec/valid? ::v/topic topic)]
|
||||
[react/view
|
||||
[status-bar]
|
||||
[toolbar/toolbar {}
|
||||
toolbar/default-nav-back
|
||||
[toolbar/content-title (label :t/new-public-group-chat)]
|
||||
[toolbar/actions [{:icon :icons/ok
|
||||
:icon-opts {:color (if create-btn-enabled? components.styles/color-blue4 components.styles/color-gray11)}
|
||||
:handler (when create-btn-enabled?
|
||||
#(dispatch [:create-new-public-chat topic]))}]]]])))
|
||||
|
||||
(defview chat-name-input []
|
||||
(letsubs [topic [:get :public-group-topic]]
|
||||
[react/view
|
||||
[text-field
|
||||
{:error (cond
|
||||
(not (spec/valid? :global/not-empty-string topic))
|
||||
(label :t/empty-topic)
|
||||
|
||||
(not (spec/valid? ::v/topic topic))
|
||||
(label :t/topic-format))
|
||||
:wrapper-style styles/group-chat-name-wrapper
|
||||
:error-color components.styles/color-blue
|
||||
:line-color components.styles/color-gray4
|
||||
:label-hidden? true
|
||||
:input-style styles/group-chat-topic-input
|
||||
:auto-focus true
|
||||
:on-change-text #(dispatch [:set :public-group-topic %])
|
||||
:value topic
|
||||
:validator #(re-matches #"[a-z\-]*" %)
|
||||
:auto-capitalize :none}]
|
||||
[react/text {:style styles/topic-hash} "#"]]))
|
||||
|
||||
(defn new-public-chat []
|
||||
[react/view styles/group-container
|
||||
[new-public-chat-toolbar]
|
||||
[react/view styles/chat-name-container
|
||||
[react/text {:style styles/members-text
|
||||
:font :medium}
|
||||
(label :t/public-group-topic)]
|
||||
[chat-name-input]]])
|
|
@ -29,11 +29,11 @@
|
|||
[react/text {:style style/add-contact-text}
|
||||
(i18n/label :t/add-to-contacts)]]])))
|
||||
|
||||
(defn- on-options [chat-id chat-name group-chat?]
|
||||
(list-selection/show {:title chat-name
|
||||
:options (actions/actions group-chat? chat-id)}))
|
||||
(defn- on-options [chat-id chat-name group-chat? public?]
|
||||
(list-selection/show {:title (if public? (str "#" chat-name) chat-name)
|
||||
:options (actions/actions group-chat? chat-id public?)}))
|
||||
|
||||
(defview chat-toolbar []
|
||||
(defview chat-toolbar [public?]
|
||||
(letsubs [accounts [:get-accounts]
|
||||
creating? [:get :accounts/creating-account?]
|
||||
{:keys [group-chat name chat-id]} [:get-current-chat]]
|
||||
|
@ -48,7 +48,7 @@
|
|||
[toolbar-content/toolbar-content-view]
|
||||
[toolbar/actions [{:icon :icons/options
|
||||
:icon-opts {:color :black}
|
||||
:handler #(on-options chat-id name group-chat)}]]]
|
||||
:handler #(on-options chat-id name group-chat public?)}]]]
|
||||
[add-contact-bar]]))
|
||||
|
||||
(defmulti message-row (fn [{{:keys [type]} :row}] type))
|
||||
|
@ -95,12 +95,12 @@
|
|||
:keyboardShouldPersistTaps (if platform/android? :always :handled)}]))
|
||||
|
||||
(defview chat []
|
||||
(letsubs [{:keys [group-chat input-text]} [:get-current-chat]
|
||||
(letsubs [{:keys [group-chat public? input-text]} [:get-current-chat]
|
||||
show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?]
|
||||
layout-height [:get :layout-height]
|
||||
current-view [:get :view-id]]
|
||||
[react/view {:style style/chat-view}
|
||||
[chat-toolbar]
|
||||
[chat-toolbar public?]
|
||||
(when (= :chat current-view)
|
||||
[messages-view-animation
|
||||
[messages-view group-chat]])
|
||||
|
|
|
@ -4,27 +4,37 @@
|
|||
|
||||
(defn view-profile [chat-id group?]
|
||||
{:label (i18n/label :t/view-profile)
|
||||
:action #(re-frame/dispatch [ (if group? :show-group-chat-profile :show-profile) chat-id])})
|
||||
:action #(re-frame/dispatch [(if group? :show-group-chat-profile :show-profile) chat-id])})
|
||||
|
||||
(defn delete-chat [chat-id]
|
||||
{:label (i18n/label :t/delete-chat)
|
||||
;; TODO(jeluard) Refactor this or Jan will have an heart attack
|
||||
:action #(do (re-frame/dispatch [:remove-chat chat-id])
|
||||
(re-frame/dispatch [:navigation-replace :home]))})
|
||||
(defn- clear-history []
|
||||
{:label (i18n/label :t/clear-history)
|
||||
:action #(re-frame/dispatch [:clear-history?])})
|
||||
|
||||
(defn leave-group-chat [chat-id]
|
||||
{:label (i18n/label :t/leave-group-chat)
|
||||
:action #(re-frame/dispatch [:leave-group-chat chat-id])})
|
||||
(defn- delete-chat [chat-id group?]
|
||||
{:label (i18n/label :t/delete-chat)
|
||||
:action #(re-frame/dispatch [:delete-chat? chat-id group?])})
|
||||
|
||||
(defn- user-chat-actions [chat-id group?]
|
||||
[(view-profile chat-id group?)
|
||||
(delete-chat chat-id)])
|
||||
(defn- leave-group-chat [chat-id public?]
|
||||
{:label (i18n/label (if public? :t/leave-public-chat :t/leave-group-chat))
|
||||
:action #(re-frame/dispatch [:leave-group-chat? chat-id])})
|
||||
|
||||
(defn- chat-actions [chat-id]
|
||||
[(view-profile chat-id false)
|
||||
(delete-chat chat-id false)])
|
||||
|
||||
(defn- group-chat-actions [chat-id]
|
||||
(into (user-chat-actions chat-id true)
|
||||
[(leave-group-chat chat-id)]))
|
||||
[(view-profile chat-id true)
|
||||
(clear-history)
|
||||
(delete-chat chat-id true)
|
||||
(leave-group-chat chat-id false)])
|
||||
|
||||
(defn actions [group-chat? chat-id]
|
||||
(if group-chat?
|
||||
(group-chat-actions chat-id)
|
||||
(user-chat-actions chat-id false)))
|
||||
(defn- public-chat-actions [chat-id]
|
||||
[(clear-history)
|
||||
(delete-chat chat-id true)
|
||||
(leave-group-chat chat-id true)])
|
||||
|
||||
(defn actions [group-chat? chat-id public?]
|
||||
(cond
|
||||
public? (public-chat-actions chat-id)
|
||||
group-chat? (group-chat-actions chat-id)
|
||||
:else (chat-actions chat-id)))
|
||||
|
|
|
@ -393,7 +393,7 @@
|
|||
|
||||
(handlers/register-handler-fx
|
||||
:check-sync
|
||||
(fn [{{:keys [web3] :as db} :db} _]
|
||||
(fn [{{:keys [web3]} :db} _]
|
||||
{::web3-get-syncing web3
|
||||
:dispatch-later [{:ms 10000 :dispatch [:check-sync]}]}))
|
||||
|
||||
|
@ -547,7 +547,7 @@
|
|||
[re-frame/trim-v]
|
||||
(fn [{{:keys [web3 contacts/contacts] :as db} :db}
|
||||
[{:keys [from]
|
||||
{:keys [group-id timestamp message-id] :as payload} :payload}]]
|
||||
{:keys [group-id timestamp message-id]} :payload}]]
|
||||
(let [chat (get-in db [:chats group-id])
|
||||
new-update? (chat/new-update? chat timestamp)]
|
||||
(when new-update?
|
||||
|
|
|
@ -151,8 +151,11 @@
|
|||
:chats "Chats"
|
||||
:delete-chat "Delete chat"
|
||||
:group-chat "Group chat"
|
||||
:delete-chat-confirmation "Are you sure you want to delete this chat?"
|
||||
:delete-group-chat-confirmation "Are you sure you want to delete this group chat?"
|
||||
:new-group-chat "New group chat"
|
||||
:new-public-group-chat "Join public chat"
|
||||
:public-chat "Public chat"
|
||||
:edit-chats "Edit chats"
|
||||
:search-chats "Search chats"
|
||||
:empty-topic "Empty topic"
|
||||
|
@ -204,10 +207,18 @@
|
|||
:save "Save"
|
||||
:create "Create"
|
||||
:delete "Delete"
|
||||
:delete-confirmation "Delete?"
|
||||
:leave "Leave"
|
||||
:leave-confirmation "Leave?"
|
||||
:clear "Clear"
|
||||
:clear-history "Clear history"
|
||||
:clear-history-confirmation "Clear history?"
|
||||
:clear-group-history-confirmation "Are you sure you want to clear history in this group chat?"
|
||||
:mute-notifications "Mute notifications"
|
||||
:leave-chat "Leave chat"
|
||||
:leave-group-chat-confirmation "Are you sure you want to leave this group?"
|
||||
:leave-group-chat "Leave group chat"
|
||||
:leave-public-chat "Leave public chat"
|
||||
:chat-settings "Chat settings"
|
||||
:edit "Edit"
|
||||
:add-members "Add members"
|
||||
|
@ -415,4 +426,5 @@
|
|||
:browser "Browser"
|
||||
:enter-dapp-url "Enter a ÐApp URL"
|
||||
:dapp "ÐApp"
|
||||
:selected "Selected"
|
||||
:selected-dapps "Selected ÐApps"})
|
||||
|
|
|
@ -17,12 +17,6 @@
|
|||
:height 40
|
||||
:border-radius 20}))
|
||||
|
||||
(defn default-chat-icon-menu-item [color]
|
||||
(merge (default-chat-icon color)
|
||||
{:width 24
|
||||
:height 24
|
||||
:border-radius 12}))
|
||||
|
||||
(defn default-chat-icon-profile [color]
|
||||
(merge (default-chat-icon color)
|
||||
{:width 64
|
||||
|
@ -144,13 +138,6 @@
|
|||
(def online-dot-left (merge online-dot {:left 2.8}))
|
||||
(def online-dot-right (merge online-dot {:left 7.2}))
|
||||
|
||||
(def photo-pencil
|
||||
{:margin-left 8
|
||||
:margin-right 2
|
||||
:margin-top 6
|
||||
:font-size 12
|
||||
:color :white})
|
||||
|
||||
(def online-dot-menu-item
|
||||
(merge online-dot
|
||||
{:top 4
|
||||
|
|
|
@ -12,3 +12,5 @@
|
|||
(def blue "#4360df") ;; Used as main wallet color
|
||||
(def red "#ff2d55") ;; Used to highlight errors or "dangerous" actions
|
||||
(def text-light-gray "#212121") ;; Used for labels (home items)
|
||||
|
||||
(def text black)
|
||||
|
|
|
@ -44,9 +44,7 @@
|
|||
(def icon-wrapper-size (+ icon-size (* 2 8)))
|
||||
|
||||
(def item-icon-wrapper
|
||||
{:width icon-wrapper-size
|
||||
:height icon-wrapper-size
|
||||
:align-items :center
|
||||
{:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def item-icon
|
||||
|
@ -68,7 +66,7 @@
|
|||
|
||||
(def right-item-wrapper
|
||||
{:justify-content :center
|
||||
:margin-right horizontal-margin})
|
||||
:margin-right 12})
|
||||
|
||||
(def base-separator
|
||||
{:height 1
|
||||
|
|
|
@ -83,8 +83,7 @@
|
|||
[checkbox/checkbox props]])
|
||||
|
||||
(def item-icon-forward
|
||||
[item-icon {:style styles/item-icon
|
||||
:icon :icons/forward
|
||||
[item-icon {:icon :icons/forward
|
||||
:icon-opts {:color colors/white-light-transparent}}])
|
||||
|
||||
(defn- wrap-render-fn [f]
|
||||
|
|
|
@ -35,18 +35,18 @@
|
|||
(let [duration (:label-animation-duration config)
|
||||
animation (animation/parallel (into []
|
||||
(concat
|
||||
(when (or (nil? value-blank?) value-blank?)
|
||||
[(animation/timing top {:toValue to-top
|
||||
:duration duration})
|
||||
(animation/timing font-size {:toValue to-font-size
|
||||
:duration duration})])
|
||||
[(animation/timing line-width {:toValue to-line-width
|
||||
:duration duration})
|
||||
(animation/timing line-height {:toValue to-line-height
|
||||
:duration duration})])))]
|
||||
(when (or (nil? value-blank?) value-blank?)
|
||||
[(animation/timing top {:toValue to-top
|
||||
:duration duration})
|
||||
(animation/timing font-size {:toValue to-font-size
|
||||
:duration duration})])
|
||||
[(animation/timing line-width {:toValue to-line-width
|
||||
:duration duration})
|
||||
(animation/timing line-height {:toValue to-line-height
|
||||
:duration duration})])))]
|
||||
(animation/start animation (fn [arg]
|
||||
(when (.-finished arg)
|
||||
(log/debug "Field animation finished"))))))
|
||||
(when (.-finished arg)
|
||||
(log/debug "Field animation finished"))))))
|
||||
|
||||
; Invoked once before the component is mounted. The return value will be used
|
||||
; as the initial value of this.state.
|
||||
|
@ -65,11 +65,11 @@
|
|||
(defn component-will-mount [component]
|
||||
(let [{:keys [value]} (reagent/props component)
|
||||
data {:label-top (animation/create-value (if (string/blank? value)
|
||||
(:label-bottom config)
|
||||
(:label-top config)))
|
||||
(:label-bottom config)
|
||||
(:label-top config)))
|
||||
:label-font-size (animation/create-value (if (string/blank? value)
|
||||
(:label-font-large config)
|
||||
(:label-font-small config)))
|
||||
(:label-font-large config)
|
||||
(:label-font-small config)))
|
||||
:float-label? (if (string/blank? value) false true)}]
|
||||
;(log/debug "component-will-mount")
|
||||
(reagent/set-state component data)))
|
||||
|
@ -78,7 +78,7 @@
|
|||
(do
|
||||
(log/debug "input focused")
|
||||
(reagent/set-state component {:has-focus true
|
||||
:float-label? true})
|
||||
:float-label? true})
|
||||
(field-animation (merge animation
|
||||
{:to-line-width (:max-line-width (reagent/state component))}))
|
||||
(when onFocus (onFocus))))
|
||||
|
@ -86,7 +86,7 @@
|
|||
(defn on-input-blur [{:keys [component value animation onBlur]}]
|
||||
(log/debug "Input blurred")
|
||||
(reagent/set-state component {:has-focus false
|
||||
:float-label? (if (string/blank? value) false true)})
|
||||
:float-label? (if (string/blank? value) false true)})
|
||||
(field-animation animation (string/blank? value))
|
||||
(when onBlur (onBlur)))
|
||||
|
||||
|
@ -107,7 +107,7 @@
|
|||
max-length]} (reagent/state component)
|
||||
{:keys [wrapper-style input-style label-hidden? line-color focus-line-color focus-line-height
|
||||
secure-text-entry label-color error-color error label value on-focus on-blur validator
|
||||
auto-focus on-change-text on-change on-end-editing editable placeholder
|
||||
auto-focus on-change-text on-change on-end-editing on-submit-editing editable placeholder
|
||||
placeholder-text-color auto-capitalize multiline number-of-lines]}
|
||||
(merge default-props (reagent/props component))
|
||||
valid-value (or valid-value "")
|
||||
|
@ -120,52 +120,52 @@
|
|||
(when-not label-hidden?
|
||||
[react/animated-text {:style (styles/label label-top label-font-size label-color)} label])
|
||||
[react/text-input {:ref #(reset! input-ref %)
|
||||
:style (merge styles/text-input input-style)
|
||||
:placeholder (or placeholder "")
|
||||
:placeholder-text-color placeholder-text-color
|
||||
:editable editable
|
||||
:multiline multiline
|
||||
:number-of-lines number-of-lines
|
||||
:secure-text-entry secure-text-entry
|
||||
:auto-capitalize auto-capitalize
|
||||
:on-focus #(on-input-focus {:component component
|
||||
:animation {:top label-top
|
||||
:to-top (:label-top config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-small config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-height focus-line-height}
|
||||
:onFocus on-focus})
|
||||
:on-blur #(on-input-blur {:component component
|
||||
:value (or current-value value)
|
||||
:animation {:top label-top
|
||||
:to-top (:label-bottom config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-large config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-width 0
|
||||
:to-line-height 1}
|
||||
:onBlur on-blur})
|
||||
:on-change-text (fn [text]
|
||||
(reagent/set-state component {:current-value text})
|
||||
(if (or (not validator) (validator text))
|
||||
(do
|
||||
(reagent/set-state component {:valid-value text
|
||||
:temp-value nil})
|
||||
(on-change-text text))
|
||||
(reagent/set-state component {:temp-value valid-value
|
||||
:max-length (count valid-value)})))
|
||||
:on-change on-change
|
||||
:default-value value
|
||||
:value temp-value
|
||||
:max-length max-length
|
||||
:on-submit-editing #(.blur @input-ref)
|
||||
:on-end-editing (when on-end-editing on-end-editing)
|
||||
:auto-focus (true? auto-focus)}]
|
||||
:style (merge styles/text-input input-style)
|
||||
:placeholder (or placeholder "")
|
||||
:placeholder-text-color placeholder-text-color
|
||||
:editable editable
|
||||
:multiline multiline
|
||||
:number-of-lines number-of-lines
|
||||
:secure-text-entry secure-text-entry
|
||||
:auto-capitalize auto-capitalize
|
||||
:on-focus #(on-input-focus {:component component
|
||||
:animation {:top label-top
|
||||
:to-top (:label-top config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-small config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-height focus-line-height}
|
||||
:onFocus on-focus})
|
||||
:on-blur #(on-input-blur {:component component
|
||||
:value (or current-value value)
|
||||
:animation {:top label-top
|
||||
:to-top (:label-bottom config)
|
||||
:font-size label-font-size
|
||||
:to-font-size (:label-font-large config)
|
||||
:line-width line-width
|
||||
:line-height line-height
|
||||
:to-line-width 0
|
||||
:to-line-height 1}
|
||||
:onBlur on-blur})
|
||||
:on-change-text (fn [text]
|
||||
(reagent/set-state component {:current-value text})
|
||||
(if (or (not validator) (validator text))
|
||||
(do
|
||||
(reagent/set-state component {:valid-value text
|
||||
:temp-value nil})
|
||||
(on-change-text text))
|
||||
(reagent/set-state component {:temp-value valid-value
|
||||
:max-length (count valid-value)})))
|
||||
:on-change on-change
|
||||
:default-value value
|
||||
:value temp-value
|
||||
:max-length max-length
|
||||
:on-submit-editing #(do (.blur @input-ref) (when on-submit-editing (on-submit-editing)))
|
||||
:on-end-editing (when on-end-editing on-end-editing)
|
||||
:auto-focus (true? auto-focus)}]
|
||||
[react/view {:style (styles/underline-container line-color)
|
||||
:onLayout #(reagent/set-state component {:max-line-width (get-width %)})}
|
||||
:onLayout #(reagent/set-state component {:max-line-width (get-width %)})}
|
||||
[react/animated-view {:style (styles/underline focus-line-color line-width line-height)}]]
|
||||
[react/text {:style (styles/error-text error-color)} error]]))
|
||||
|
||||
|
@ -178,6 +178,6 @@
|
|||
(let [{:keys [temp-value]} (reagent/state comp)]
|
||||
(when temp-value
|
||||
(reagent/set-state comp {:temp-value nil
|
||||
:max-length nil}))))}]
|
||||
:max-length nil}))))}]
|
||||
;(log/debug "Creating text-field component: " data)
|
||||
(reagent/create-class component-data)))
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
(ns status-im.ui.screens.add-new.new-public-chat.db
|
||||
(:require [clojure.string :as string]
|
||||
[cljs.spec.alpha :as spec]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.homoglyph :as utils]
|
||||
status-im.utils.db))
|
||||
|
||||
(defn- legal-name? [username]
|
||||
(let [username (some-> username string/trim)]
|
||||
(not (utils/matches username constants/console-chat-id))))
|
||||
|
||||
(spec/def ::legal-name legal-name?)
|
||||
|
||||
(spec/def ::name (spec/and :global/not-empty-string
|
||||
::legal-name))
|
||||
|
||||
(spec/def ::topic (spec/and :global/not-empty-string
|
||||
::legal-name
|
||||
(partial re-matches #"[a-z0-9\-]+")))
|
|
@ -0,0 +1,70 @@
|
|||
(ns status-im.ui.screens.add-new.new-public-chat.styles
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.styles :as styles]))
|
||||
|
||||
(def group-chat-name-input
|
||||
{:font-size 17
|
||||
:padding-bottom 0
|
||||
:letter-spacing -0.2
|
||||
:color colors/text})
|
||||
|
||||
(defstyle group-chat-topic-input
|
||||
{:font-size 14
|
||||
:line-height 16
|
||||
:color colors/text
|
||||
:padding-left -1
|
||||
:ios {:padding-bottom 0}})
|
||||
|
||||
(defstyle topic-hash-style
|
||||
{:width 10
|
||||
:position :absolute
|
||||
:android {:top 8 :left 3}
|
||||
:ios {:top 6 :left 3}})
|
||||
|
||||
(def topic-hash
|
||||
(merge group-chat-name-input
|
||||
{:margin-left 14}))
|
||||
|
||||
(def group-chat-name-wrapper
|
||||
{:flex 1
|
||||
:padding-top 0
|
||||
:height 40
|
||||
:padding-bottom 0})
|
||||
|
||||
(def group-container
|
||||
{:flex 1
|
||||
:flex-direction :column})
|
||||
|
||||
(def chat-name-container
|
||||
{:margin-top 10})
|
||||
|
||||
(defstyle members-text
|
||||
{:color colors/gray
|
||||
:ios {:letter-spacing -0.2
|
||||
:font-size 16}
|
||||
:android {:font-size 14}})
|
||||
|
||||
(def section-title
|
||||
(merge members-text
|
||||
{:padding-horizontal 16}))
|
||||
|
||||
(def input-container
|
||||
{:flex-direction :row
|
||||
:align-items :center
|
||||
:border-radius styles/border-radius
|
||||
:height 52
|
||||
:background-color colors/gray-light
|
||||
:margin-top 24})
|
||||
|
||||
(def public-chat-icon
|
||||
{:background-color colors/blue
|
||||
:border-radius 50
|
||||
:width 40
|
||||
:height 40
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def public-chat-icon-symbol
|
||||
{:font-size 20
|
||||
:color colors/white})
|
|
@ -0,0 +1,75 @@
|
|||
(ns status-im.ui.screens.add-new.new-public-chat.view
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.styles :as components.styles]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
[status-im.ui.components.text-field.view :as text-field]
|
||||
[status-im.ui.components.toolbar.view :as toolbar]
|
||||
[status-im.ui.screens.add-new.styles :as add-new.styles]
|
||||
[status-im.ui.screens.add-new.new-public-chat.styles :as styles]
|
||||
[status-im.ui.screens.add-new.new-public-chat.db :as v]
|
||||
status-im.utils.db))
|
||||
|
||||
(defn- topic-error-label [topic]
|
||||
(cond
|
||||
(not (spec/valid? :global/not-empty-string topic))
|
||||
(i18n/label :t/empty-topic)
|
||||
|
||||
(not (spec/valid? ::v/topic topic))
|
||||
(i18n/label :t/topic-format)))
|
||||
|
||||
(defn- chat-name-input [topic]
|
||||
[react/view (merge add-new.styles/input-container {:margin-top 8})
|
||||
[react/text {:style styles/topic-hash} "#"]
|
||||
[text-field/text-field
|
||||
{:wrapper-style styles/group-chat-name-wrapper
|
||||
:line-color components.styles/color-transparent
|
||||
:focus-line-color components.styles/color-transparent
|
||||
:label-hidden? true
|
||||
:input-style styles/group-chat-topic-input
|
||||
:on-change-text #(re-frame/dispatch [:set :public-group-topic %])
|
||||
:on-submit-editing #(when topic (re-frame/dispatch [:create-new-public-chat topic]))
|
||||
:value topic
|
||||
:validator #(re-matches #"[a-z\-]+" %)
|
||||
:auto-capitalize :none}]])
|
||||
|
||||
(defn- public-chat-icon [topic]
|
||||
[react/view styles/public-chat-icon
|
||||
[react/text {:uppercase? true
|
||||
:style styles/public-chat-icon-symbol}
|
||||
(first topic)]])
|
||||
|
||||
(defn- render-topic [topic]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:create-new-public-chat topic])}
|
||||
[react/view
|
||||
[list/item
|
||||
[public-chat-icon topic]
|
||||
[list/item-primary-only
|
||||
topic]
|
||||
[list/item-icon {:icon :icons/forward
|
||||
:icon-opts {:color :gray}}]]]])
|
||||
|
||||
(def default-public-chats ["status" "openbounty" "ethereum"])
|
||||
|
||||
(views/defview new-public-chat []
|
||||
(views/letsubs [topic [:get :public-group-topic]]
|
||||
[react/view styles/group-container
|
||||
[status-bar/status-bar]
|
||||
[toolbar/simple-toolbar
|
||||
(i18n/label :t/public-chat)]
|
||||
[react/view styles/chat-name-container
|
||||
[react/text {:style styles/section-title
|
||||
:font :medium}
|
||||
(i18n/label :t/public-group-topic)]
|
||||
[chat-name-input topic]]
|
||||
[react/view styles/chat-name-container
|
||||
[react/text {:style styles/section-title
|
||||
:font :medium}
|
||||
(i18n/label :t/selected)]]
|
||||
[list/flat-list {:data default-public-chats
|
||||
:render-fn render-topic
|
||||
:default-separator? true}]]))
|
|
@ -8,14 +8,14 @@
|
|||
status-im.ui.screens.qr-scanner.db
|
||||
status-im.ui.screens.group.db
|
||||
status-im.chat.specs
|
||||
status-im.chat.new-public-chat.db
|
||||
status-im.commands.specs
|
||||
status-im.ui.screens.profile.db
|
||||
status-im.ui.screens.discover.db
|
||||
status-im.ui.screens.network-settings.db
|
||||
status-im.ui.screens.offline-messaging-settings.db
|
||||
status-im.ui.screens.browser.db
|
||||
status-im.ui.screens.add-new.db))
|
||||
status-im.ui.screens.add-new.db
|
||||
status-im.ui.screens.add-new.new-public-chat.db))
|
||||
|
||||
;; initial state of app-db
|
||||
(def app-db {:current-public-key nil
|
||||
|
|
|
@ -1,28 +1,27 @@
|
|||
(ns status-im.ui.screens.group.chat-settings.events
|
||||
(:require [re-frame.core :refer [dispatch reg-fx]]
|
||||
[status-im.utils.handlers :refer [register-handler-fx]]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.chat.handlers :as chat-events]
|
||||
[status-im.data-store.messages :as messages]
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.constants :refer [text-content-type]]))
|
||||
|
||||
;;;; COFX
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.random :as random]))
|
||||
|
||||
;;;; FX
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::save-chat-property
|
||||
(fn [[current-chat-id property-name value]]
|
||||
(chats/save-property current-chat-id property-name value)))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::add-members-to-chat
|
||||
(fn [{:keys [current-chat-id selected-participants]}]
|
||||
(chats/add-contacts current-chat-id selected-participants)))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::remove-members-from-chat
|
||||
(fn [[current-chat-id participants]]
|
||||
(chats/remove-contacts current-chat-id participants)))
|
||||
|
@ -31,7 +30,7 @@
|
|||
{:from "system"
|
||||
:message-id message-id
|
||||
:content content
|
||||
:content-type text-content-type})
|
||||
:content-type constants/text-content-type})
|
||||
|
||||
(defn removed-participant-message [chat-id identity contact-name]
|
||||
(let [message-text (str "You've removed " (or contact-name identity))]
|
||||
|
@ -39,14 +38,14 @@
|
|||
(assoc :chat-id chat-id)
|
||||
(messages/save))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::create-removing-messages
|
||||
(fn [{:keys [current-chat-id participants contacts/contacts]}]
|
||||
(doseq [participant participants]
|
||||
(let [contact-name (get-in contacts [participant :name])]
|
||||
(removed-participant-message current-chat-id participant contact-name)))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::notify-about-new-members
|
||||
(fn [{:keys [current-chat-id selected-participants
|
||||
current-public-key chats web3]}]
|
||||
|
@ -63,14 +62,14 @@
|
|||
:admin current-public-key}
|
||||
:message {:from current-public-key
|
||||
:message-id (random/id)}}]
|
||||
(dispatch [:update-chat! {:chat-id current-chat-id
|
||||
:public-key public
|
||||
:private-key private}])
|
||||
(re-frame/dispatch [:update-chat! {:chat-id current-chat-id
|
||||
:public-key public
|
||||
:private-key private}])
|
||||
(protocol/start-watching-group! {:web3 web3
|
||||
:group-id current-chat-id
|
||||
:identity current-public-key
|
||||
:keypair new-keypair
|
||||
:callback #(dispatch [:incoming-message %1 %2])})
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])})
|
||||
(protocol/invite-to-group!
|
||||
(-> group-message
|
||||
(assoc-in [:group :keypair] new-keypair)
|
||||
|
@ -87,7 +86,7 @@
|
|||
:message {:from current-public-key
|
||||
:message-id (random/id)}})))))
|
||||
|
||||
(reg-fx
|
||||
(re-frame/reg-fx
|
||||
::notify-about-removing
|
||||
(fn [{:keys [web3 current-chat-id participants chats current-public-key]}]
|
||||
(let [{:keys [private public] :as new-keypair} (protocol/new-keypair!)
|
||||
|
@ -99,9 +98,9 @@
|
|||
identities (-> (map :identity contacts)
|
||||
set
|
||||
(clojure.set/difference participants))]
|
||||
(dispatch [:update-chat! {:chat-id current-chat-id
|
||||
:private-key private
|
||||
:public-key public}])
|
||||
(re-frame/dispatch [:update-chat! {:chat-id current-chat-id
|
||||
:private-key private
|
||||
:public-key public}])
|
||||
(doseq [participant participants]
|
||||
(let [id (random/id)]
|
||||
(doseq [keypair [old-keypair new-keypair]]
|
||||
|
@ -117,7 +116,7 @@
|
|||
:group-id current-chat-id
|
||||
:identity current-public-key
|
||||
:keypair new-keypair
|
||||
:callback #(dispatch [:incoming-message %1 %2])})
|
||||
:callback #(re-frame/dispatch [:incoming-message %1 %2])})
|
||||
(protocol/update-group!
|
||||
{:web3 web3
|
||||
:group {:id current-chat-id
|
||||
|
@ -131,14 +130,14 @@
|
|||
|
||||
;;;; Handlers
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:show-group-chat-profile
|
||||
(fn [{db :db} [_ chat-id]]
|
||||
{:db (assoc db :new-chat-name (get-in db [:chats chat-id :name])
|
||||
:group/group-type :chat-group)
|
||||
:dispatch [:navigate-to :chat-group-settings]}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:add-new-group-chat-participants
|
||||
(fn [{{:keys [current-chat-id selected-participants] :as db} :db} _]
|
||||
(let [new-identities (map #(hash-map :identity %) selected-participants)]
|
||||
|
@ -149,10 +148,10 @@
|
|||
::notify-about-new-members (select-keys db [:current-chat-id :selected-participants
|
||||
:current-public-key :chats :web3])})))
|
||||
|
||||
(defn remove-identities [collection identities]
|
||||
(defn- remove-identities [collection identities]
|
||||
(remove #(identities (:identity %)) collection))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:remove-group-chat-participants
|
||||
(fn [{{:keys [current-chat-id] :as db} :db} [_ participants]]
|
||||
{:db (update-in db [:chats current-chat-id :contacts] remove-identities participants)
|
||||
|
@ -162,14 +161,22 @@
|
|||
::create-removing-messages (merge {:participants participants}
|
||||
(select-keys db [:current-chat-id :contacts/contacts]))}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:set-chat-name
|
||||
(fn [{{:keys [current-chat-id new-chat-name] :as db} :db} _]
|
||||
{:db (assoc-in db [:chats current-chat-id :name] new-chat-name)
|
||||
::save-chat-property [current-chat-id :name new-chat-name]}))
|
||||
|
||||
(register-handler-fx
|
||||
(handlers/register-handler-fx
|
||||
:clear-history
|
||||
(fn [{{:keys [current-chat-id] :as db} :db} _]
|
||||
{:db (assoc-in db [:chats current-chat-id :messages] {})
|
||||
:delete-messages current-chat-id}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:clear-history?
|
||||
(fn [_ _]
|
||||
{:show-confirmation {:title (i18n/label :t/clear-history-confirmation)
|
||||
:content (i18n/label :t/clear-group-history-confirmation)
|
||||
:confirm-button-text (i18n/label :t/clear)
|
||||
:on-accept #(re-frame/dispatch [:clear-history])}}))
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
(pop stack))]
|
||||
(conj stack' view-id)))
|
||||
|
||||
(defn- replace-view [db view-id]
|
||||
(defn replace-view [db view-id]
|
||||
(-> db
|
||||
(update :navigation-stack replace-top-element view-id)
|
||||
(assoc :view-id view-id)))
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(-> (accounts-events/account-update {:db db}
|
||||
{:wnode wnode :last-updated now})
|
||||
(merge {:dispatch [:navigate-to-clean :accounts]
|
||||
:stop-whisper nil}))))
|
||||
:stop-whisper nil}))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:connect-wnode
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[status-im.chat.screen :refer [chat]]
|
||||
[status-im.ui.screens.add-new.views :refer [add-new]]
|
||||
[status-im.ui.screens.add-new.new-chat.views :refer [new-chat]]
|
||||
[status-im.chat.new-public-chat.view :refer [new-public-chat]]
|
||||
[status-im.ui.screens.add-new.new-public-chat.view :refer [new-public-chat]]
|
||||
|
||||
[status-im.ui.screens.contacts.contact-list-modal.views :refer [contact-list-modal]]
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.ethereum.tokens :as tokens]))
|
||||
|
||||
|
||||
(defn- render-token [{:keys [symbol name icon]} visible-tokens]
|
||||
[list/item
|
||||
[list/item-image icon]
|
||||
|
|
|
@ -92,6 +92,8 @@
|
|||
|
||||
(def action
|
||||
{:background-color colors/white-transparent
|
||||
:width 40
|
||||
:height 40
|
||||
:border-radius 50})
|
||||
|
||||
(def action-label
|
||||
|
|
Loading…
Reference in New Issue