mirror of
https://github.com/status-im/status-mobile.git
synced 2025-02-26 07:15:53 +00:00
Chat refactoring
Move chat views to ui.screens
This commit is contained in:
parent
195b70fcdd
commit
8913dee762
@ -1,17 +1,12 @@
|
||||
(ns status-im.chat.commands.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[clojure.set :as set]
|
||||
[clojure.string :as string]
|
||||
[pluto.host :as host]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.chat.constants :as chat-constants]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.impl.transactions :as transactions]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.message :as message-model]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||
[status-im.utils.handlers :as handlers]))
|
||||
|
||||
(def register
|
||||
"Register of all commands. Whenever implementing a new command,
|
||||
@ -183,94 +178,3 @@
|
||||
{}
|
||||
(concat (get access-scope->command-id global-access-scope)
|
||||
(get access-scope->command-id chat-access-scope)))))
|
||||
|
||||
(defn- current-param-position [input-text selection]
|
||||
(when selection
|
||||
(when-let [subs-input-text (subs input-text 0 selection)]
|
||||
(let [input-params (input-model/split-command-args subs-input-text)
|
||||
param-index (dec (count input-params))
|
||||
wrapping-count (get (frequencies subs-input-text) chat-constants/arg-wrapping-char 0)]
|
||||
(if (and (string/ends-with? subs-input-text chat-constants/spacing-char)
|
||||
(even? wrapping-count))
|
||||
param-index
|
||||
(dec param-index))))))
|
||||
|
||||
(defn- command-completion [input-params params]
|
||||
(let [input-params-count (count input-params)
|
||||
params-count (count params)]
|
||||
(cond
|
||||
(= input-params-count params-count) :complete
|
||||
(< input-params-count params-count) :less-then-needed
|
||||
(> input-params-count params-count) :more-than-needed)))
|
||||
|
||||
(defn selected-chat-command
|
||||
"Takes input text, text-selection and `protocol/id->command-props` map (result of
|
||||
the `chat-commands` fn) and returns the corresponding `command-props` entry,
|
||||
or nothing if input text doesn't match any available command.
|
||||
Besides keys `:params` and `:type`, the returned map contains:
|
||||
* `:input-params` - parsed parameters from the input text as map of `param-id->entered-value`
|
||||
# `:current-param-position` - index of the parameter the user is currently focused on (cursor position
|
||||
in relation to parameters), could be nil if the input is not selected
|
||||
# `:command-completion` - indication of command completion, possible values are `:complete`,
|
||||
`:less-then-needed` and `more-then-needed`"
|
||||
[input-text text-selection id->command-props]
|
||||
(when (input-model/starts-as-command? input-text)
|
||||
(let [[command-name & input-params] (input-model/split-command-args input-text)]
|
||||
(when-let [{:keys [params] :as command-props} (get id->command-props (subs command-name 1))] ;; trim leading `/` for lookup
|
||||
command-props
|
||||
(let [input-params (into {}
|
||||
(keep-indexed (fn [idx input-value]
|
||||
(when (not (string/blank? input-value))
|
||||
(when-let [param-name (get-in params [idx :id])]
|
||||
[param-name input-value]))))
|
||||
input-params)]
|
||||
(assoc command-props
|
||||
:input-params input-params
|
||||
:current-param-position (current-param-position input-text text-selection)
|
||||
:command-completion (command-completion input-params params)))))))
|
||||
|
||||
(defn set-command-parameter
|
||||
"Set value as command parameter for the current chat"
|
||||
[last-param? param-index value {:keys [db]}]
|
||||
(let [{:keys [current-chat-id chats]} db
|
||||
[command & params] (-> (get-in chats [current-chat-id :input-text])
|
||||
input-model/split-command-args)
|
||||
param-count (count params)
|
||||
;; put the new value at the right place in parameters array
|
||||
new-params (cond-> (into [] params)
|
||||
(< param-index param-count) (assoc param-index value)
|
||||
(>= param-index param-count) (conj value))
|
||||
;; if the parameter is not the last one for the command, add space
|
||||
input-text (cond-> (str command chat-constants/spacing-char
|
||||
(input-model/join-command-args
|
||||
new-params))
|
||||
(and (not last-param?)
|
||||
(or (= 0 param-count)
|
||||
(= param-index (dec param-count))))
|
||||
(str chat-constants/spacing-char))]
|
||||
{:db (-> db
|
||||
(chat-model/set-chat-ui-props {:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text] input-text))}))
|
||||
|
||||
(defn select-chat-input-command
|
||||
"Takes command and (optional) map of input-parameters map and sets it as current-chat input"
|
||||
[{:keys [type params]} input-params {:keys [db]}]
|
||||
(let [{:keys [current-chat-id chat-ui-props]} db]
|
||||
{:db (-> db
|
||||
(chat-model/set-chat-ui-props {:show-suggestions? false
|
||||
:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text]
|
||||
(str (command-name type)
|
||||
chat-constants/spacing-char
|
||||
(input-model/join-command-args input-params))))}))
|
||||
|
||||
(defn parse-parameters
|
||||
"Parses parameters from input for defined command params,
|
||||
returns map of `param-name->param-value`"
|
||||
[params input-text]
|
||||
(let [input-params (->> (input-model/split-command-args input-text) rest (into []))]
|
||||
(into {}
|
||||
(keep-indexed (fn [idx {:keys [id]}]
|
||||
(when-let [value (get input-params idx)]
|
||||
[id value])))
|
||||
params)))
|
||||
|
97
src/status_im/chat/commands/input.cljs
Normal file
97
src/status_im/chat/commands/input.cljs
Normal file
@ -0,0 +1,97 @@
|
||||
(ns status-im.chat.commands.input
|
||||
(:require [clojure.string :as string]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.constants :as chat-constants]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.input :as input-model]))
|
||||
|
||||
(defn- current-param-position [input-text selection]
|
||||
(when selection
|
||||
(when-let [subs-input-text (subs input-text 0 selection)]
|
||||
(let [input-params (input-model/split-command-args subs-input-text)
|
||||
param-index (dec (count input-params))
|
||||
wrapping-count (get (frequencies subs-input-text) chat-constants/arg-wrapping-char 0)]
|
||||
(if (and (string/ends-with? subs-input-text chat-constants/spacing-char)
|
||||
(even? wrapping-count))
|
||||
param-index
|
||||
(dec param-index))))))
|
||||
|
||||
(defn- command-completion [input-params params]
|
||||
(let [input-params-count (count input-params)
|
||||
params-count (count params)]
|
||||
(cond
|
||||
(= input-params-count params-count) :complete
|
||||
(< input-params-count params-count) :less-then-needed
|
||||
(> input-params-count params-count) :more-than-needed)))
|
||||
|
||||
(defn selected-chat-command
|
||||
"Takes input text, text-selection and `protocol/id->command-props` map (result of
|
||||
the `chat-commands` fn) and returns the corresponding `command-props` entry,
|
||||
or nothing if input text doesn't match any available command.
|
||||
Besides keys `:params` and `:type`, the returned map contains:
|
||||
* `:input-params` - parsed parameters from the input text as map of `param-id->entered-value`
|
||||
# `:current-param-position` - index of the parameter the user is currently focused on (cursor position
|
||||
in relation to parameters), could be nil if the input is not selected
|
||||
# `:command-completion` - indication of command completion, possible values are `:complete`,
|
||||
`:less-then-needed` and `more-then-needed`"
|
||||
[input-text text-selection id->command-props]
|
||||
(when (input-model/starts-as-command? input-text)
|
||||
(let [[command-name & input-params] (input-model/split-command-args input-text)]
|
||||
(when-let [{:keys [params] :as command-props} (get id->command-props (subs command-name 1))] ;; trim leading `/` for lookup
|
||||
command-props
|
||||
(let [input-params (into {}
|
||||
(keep-indexed (fn [idx input-value]
|
||||
(when (not (string/blank? input-value))
|
||||
(when-let [param-name (get-in params [idx :id])]
|
||||
[param-name input-value]))))
|
||||
input-params)]
|
||||
(assoc command-props
|
||||
:input-params input-params
|
||||
:current-param-position (current-param-position input-text text-selection)
|
||||
:command-completion (command-completion input-params params)))))))
|
||||
|
||||
(defn set-command-parameter
|
||||
"Set value as command parameter for the current chat"
|
||||
[last-param? param-index value {:keys [db]}]
|
||||
(let [{:keys [current-chat-id chats]} db
|
||||
[command & params] (-> (get-in chats [current-chat-id :input-text])
|
||||
input-model/split-command-args)
|
||||
param-count (count params)
|
||||
;; put the new value at the right place in parameters array
|
||||
new-params (cond-> (into [] params)
|
||||
(< param-index param-count) (assoc param-index value)
|
||||
(>= param-index param-count) (conj value))
|
||||
;; if the parameter is not the last one for the command, add space
|
||||
input-text (cond-> (str command chat-constants/spacing-char
|
||||
(input-model/join-command-args
|
||||
new-params))
|
||||
(and (not last-param?)
|
||||
(or (= 0 param-count)
|
||||
(= param-index (dec param-count))))
|
||||
(str chat-constants/spacing-char))]
|
||||
{:db (-> db
|
||||
(chat-model/set-chat-ui-props {:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text] input-text))}))
|
||||
|
||||
(defn select-chat-input-command
|
||||
"Takes command and (optional) map of input-parameters map and sets it as current-chat input"
|
||||
[{:keys [type params]} input-params {:keys [db]}]
|
||||
(let [{:keys [current-chat-id chat-ui-props]} db]
|
||||
{:db (-> db
|
||||
(chat-model/set-chat-ui-props {:show-suggestions? false
|
||||
:validation-messages nil})
|
||||
(assoc-in [:chats current-chat-id :input-text]
|
||||
(str (commands/command-name type)
|
||||
chat-constants/spacing-char
|
||||
(input-model/join-command-args input-params))))}))
|
||||
|
||||
(defn parse-parameters
|
||||
"Parses parameters from input for defined command params,
|
||||
returns map of `param-name->param-value`"
|
||||
[params input-text]
|
||||
(let [input-params (->> (input-model/split-command-args input-text) rest (into []))]
|
||||
(into {}
|
||||
(keep-indexed (fn [idx {:keys [id]}]
|
||||
(when-let [value (get input-params idx)]
|
||||
[id value])))
|
||||
params)))
|
@ -2,6 +2,7 @@
|
||||
(:require [status-im.constants :as constants]
|
||||
[status-im.chat.commands.protocol :as protocol]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands-input]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.message :as message-model]
|
||||
@ -46,7 +47,7 @@
|
||||
"Validates and sends command in current chat"
|
||||
[input-text {:keys [type params] :as command} {:keys [db now random-id] :as cofx}]
|
||||
(let [chat-id (:current-chat-id db)
|
||||
parameter-map (commands/parse-parameters params input-text)]
|
||||
parameter-map (commands-input/parse-parameters params input-text)]
|
||||
(if-let [validation-error (protocol/validate type parameter-map cofx)]
|
||||
;; errors during validation
|
||||
{:db (chat-model/set-chat-ui-props db {:validation-messages validation-error
|
||||
|
@ -7,8 +7,6 @@
|
||||
(def input-height 56)
|
||||
(def input-spacing-top 16)
|
||||
|
||||
(def console-chat-id "console")
|
||||
|
||||
(def spam-message-frequency-threshold 4)
|
||||
(def spam-interval-ms 1000)
|
||||
(def default-cooldown-period-ms 10000)
|
||||
|
@ -5,13 +5,13 @@
|
||||
[clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.models :as models]
|
||||
[status-im.chat.models.loading :as chat-loading]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.transport.message.v1.group-chat :as group-chat]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.v1.public-chat :as public-chat]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
@ -36,12 +36,6 @@
|
||||
(fn [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]]
|
||||
(models/toggle-chat-ui-prop db ui-element)))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:show-message-details
|
||||
[re-frame/trim-v]
|
||||
@ -56,14 +50,6 @@
|
||||
(models/set-chat-ui-props db {:show-message-options? true
|
||||
:message-options options})))
|
||||
|
||||
(def index-messages (partial into {} (map (juxt :message-id identity))))
|
||||
|
||||
(handlers/register-handler-db
|
||||
:message-appeared
|
||||
[re-frame/trim-v]
|
||||
(fn [db [{:keys [chat-id message-id]}]]
|
||||
(update-in db [:chats chat-id :messages message-id] assoc :appearing? false)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:update-message-status
|
||||
[re-frame/trim-v]
|
||||
@ -77,130 +63,24 @@
|
||||
new-status)
|
||||
:data-store/tx [(user-statuses-store/save-status-tx new-status)]})))
|
||||
|
||||
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}]
|
||||
(when (and (not (get-in db [:chats chat-id :public?]))
|
||||
(not (models/bot-only-chat? db chat-id)))
|
||||
(transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
|
||||
|
||||
;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future
|
||||
(defn mark-messages-seen
|
||||
[chat-id {:keys [db] :as cofx}]
|
||||
(when-let [all-unviewed-ids (seq (get-in db [:chats chat-id :unviewed-messages]))]
|
||||
(let [me (:current-public-key db)
|
||||
updated-statuses (keep (fn [message-id]
|
||||
(some-> db
|
||||
(get-in [:chats chat-id :message-statuses
|
||||
message-id me])
|
||||
(assoc :status :seen)))
|
||||
all-unviewed-ids)
|
||||
loaded-unviewed-ids (map :message-id updated-statuses)]
|
||||
(when (seq loaded-unviewed-ids)
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
{:db (-> (reduce (fn [acc {:keys [message-id status]}]
|
||||
(assoc-in acc [:chats chat-id :message-statuses
|
||||
message-id me :status]
|
||||
status))
|
||||
db
|
||||
updated-statuses)
|
||||
(update-in [:chats chat-id :unviewed-messages]
|
||||
#(apply disj % loaded-unviewed-ids)))
|
||||
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
|
||||
(send-messages-seen chat-id loaded-unviewed-ids))))))
|
||||
|
||||
(defn- fire-off-chat-loaded-event
|
||||
[chat-id {:keys [db]}]
|
||||
(when-let [event (get-in db [:chats chat-id :chat-loaded-event])]
|
||||
{:db (update-in db [:chats chat-id] dissoc :chat-loaded-event)
|
||||
:dispatch event}))
|
||||
|
||||
(defn- preload-chat-data
|
||||
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
||||
[chat-id {:keys [db] :as cofx}]
|
||||
(handlers-macro/merge-fx cofx
|
||||
{:db (-> (assoc db :current-chat-id chat-id)
|
||||
(models/set-chat-ui-props {:validation-messages nil}))}
|
||||
(fire-off-chat-loaded-event chat-id)
|
||||
(mark-messages-seen chat-id)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:add-chat-loaded-event
|
||||
[re-frame/trim-v]
|
||||
(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)}
|
||||
(-> (models/upsert-chat {:chat-id chat-id} cofx) ; chat not created yet, we have to create it
|
||||
(assoc-in [:db :chats chat-id :chat-loaded-event] event)))))
|
||||
|
||||
(defn- navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
[chat-id {:keys [navigation-replace?]} cofx]
|
||||
(if navigation-replace?
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
(navigation/navigate-reset
|
||||
{:index 1
|
||||
:actions [{:routeName :home}
|
||||
{:routeName :chat}]})
|
||||
(preload-chat-data chat-id))
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
(navigation/navigate-to-cofx :chat {})
|
||||
(preload-chat-data chat-id))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:navigate-to-chat
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [chat-id opts]]
|
||||
(navigate-to-chat chat-id opts cofx)))
|
||||
(models/navigate-to-chat chat-id opts cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:load-more-messages
|
||||
[(re-frame/inject-cofx :data-store/get-messages)
|
||||
(re-frame/inject-cofx :data-store/get-user-statuses)]
|
||||
(fn [{{:keys [current-chat-id] :as db} :db
|
||||
get-stored-messages :get-stored-messages
|
||||
get-stored-user-statuses :get-stored-user-statuses :as cofx} _]
|
||||
(when-not (get-in db [:chats current-chat-id :all-loaded?])
|
||||
(let [loaded-count (count (get-in db [:chats current-chat-id :messages]))
|
||||
new-messages (get-stored-messages current-chat-id loaded-count)
|
||||
indexed-messages (index-messages new-messages)
|
||||
new-message-ids (keys indexed-messages)
|
||||
new-statuses (get-stored-user-statuses current-chat-id new-message-ids)]
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update-in [:chats current-chat-id :messages] merge indexed-messages)
|
||||
(update-in [:chats current-chat-id :message-statuses] merge new-statuses)
|
||||
(update-in [:chats current-chat-id :not-loaded-message-ids]
|
||||
#(apply disj % new-message-ids))
|
||||
(assoc-in [:chats current-chat-id :all-loaded?]
|
||||
(> constants/default-number-of-messages (count new-messages))))}
|
||||
(models.message/group-messages current-chat-id new-messages)
|
||||
(mark-messages-seen current-chat-id))))))
|
||||
|
||||
(defn start-chat
|
||||
"Start a chat, making sure it exists"
|
||||
[chat-id opts {:keys [db] :as cofx}]
|
||||
;; don't allow to open chat with yourself
|
||||
(when (not= (:current-public-key db) chat-id)
|
||||
(handlers-macro/merge-fx cofx
|
||||
(models/upsert-chat {:chat-id chat-id
|
||||
:is-active true})
|
||||
(navigate-to-chat chat-id opts))))
|
||||
(fn [cofx _]
|
||||
(chat-loading/load-more-messages cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:start-chat
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [contact-id opts]]
|
||||
(start-chat contact-id opts cofx)))
|
||||
|
||||
;; TODO(janherich): remove this unnecessary event in the future (only model function `update-chat` will stay)
|
||||
(handlers/register-handler-fx
|
||||
:update-chat!
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [chat]]
|
||||
(models/upsert-chat chat cofx)))
|
||||
(models/start-chat contact-id opts cofx)))
|
||||
|
||||
(defn remove-chat-and-navigate-home [cofx [chat-id]]
|
||||
(handlers-macro/merge-fx cofx
|
||||
@ -235,11 +115,10 @@
|
||||
:on-accept #(re-frame/dispatch [:clear-history])}}))
|
||||
|
||||
(defn create-new-public-chat [topic cofx]
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
(models/add-public-chat topic)
|
||||
(navigate-to-chat topic {:navigation-replace? true})
|
||||
(public-chat/join-public-chat topic)))
|
||||
(handlers-macro/merge-fx cofx
|
||||
(models/add-public-chat topic)
|
||||
(models/navigate-to-chat topic {:navigation-replace? true})
|
||||
(public-chat/join-public-chat topic)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:create-new-public-chat
|
||||
@ -268,12 +147,11 @@
|
||||
{:db (assoc db :group/selected-contacts #{})}
|
||||
(models/add-group-chat random-id chat-name (:current-public-key db) selected-contacts)
|
||||
(navigation/navigate-to-cofx :home nil)
|
||||
(navigate-to-chat random-id {})
|
||||
(models/navigate-to-chat random-id {})
|
||||
(transport.message/send (group-chat/GroupAdminUpdate. chat-name selected-contacts) random-id)))))
|
||||
|
||||
(defn show-profile [identity {:keys [db]}]
|
||||
(navigation/navigate-to-cofx
|
||||
:profile nil {:db (assoc db :contacts/identity identity)}))
|
||||
(navigation/navigate-to-cofx :profile nil {:db (assoc db :contacts/identity identity)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:show-profile
|
||||
|
@ -8,6 +8,7 @@
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.models.message :as message-model]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands-input]
|
||||
[status-im.chat.commands.sending :as commands-sending]
|
||||
[status-im.ui.components.react :as react-comp]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
@ -63,14 +64,14 @@
|
||||
(fn [{:keys [db] :as cofx} [command params metadata]]
|
||||
(handlers-macro/merge-fx cofx
|
||||
(input-model/set-chat-input-metadata metadata)
|
||||
(commands/select-chat-input-command command params)
|
||||
(commands-input/select-chat-input-command command params)
|
||||
(chat-input-focus :input-ref))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:set-command-parameter
|
||||
[re-frame/trim-v]
|
||||
(fn [cofx [last-param? index value]]
|
||||
(commands/set-command-parameter last-param? index value cofx)))
|
||||
(commands-input/set-command-parameter last-param? index value cofx)))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat-input-focus
|
||||
@ -119,7 +120,7 @@
|
||||
(fn [{{:keys [current-chat-id id->command access-scope->command-id] :as db} :db :as cofx} _]
|
||||
(when-not (get-in db [:chat-ui-props current-chat-id :sending-in-progress?])
|
||||
(let [input-text (get-in db [:chats current-chat-id :input-text])
|
||||
command (commands/selected-chat-command
|
||||
command (commands-input/selected-chat-command
|
||||
input-text nil (commands/chat-commands id->command
|
||||
access-scope->command-id
|
||||
(get-in db [:chats current-chat-id])))]
|
||||
|
@ -1,14 +1,17 @@
|
||||
(ns status-im.chat.models
|
||||
(:require [status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.transport.message.core :as transport.message]
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.transport.message.v1.group-chat :as transport.group-chat]
|
||||
[status-im.transport.utils :as transport.utils]
|
||||
[status-im.ui.components.styles :as styles]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||
|
||||
(defn multi-user-chat? [chat-id cofx]
|
||||
(get-in cofx [:db :chats chat-id :group-chat]))
|
||||
@ -76,7 +79,9 @@
|
||||
:group-admin admin
|
||||
:contacts participants} cofx))
|
||||
|
||||
(defn clear-history [chat-id {:keys [db] :as cofx}]
|
||||
(defn clear-history
|
||||
"Clears history of the particular chat"
|
||||
[chat-id {:keys [db] :as cofx}]
|
||||
(let [{:keys [messages
|
||||
deleted-at-clock-value]} (get-in db [:chats chat-id])
|
||||
last-message-clock-value (or (->> messages
|
||||
@ -102,11 +107,10 @@
|
||||
(transport.utils/unsubscribe-from-chat chat-id cofx)))
|
||||
|
||||
(defn- deactivate-chat [chat-id {:keys [db now] :as cofx}]
|
||||
(cond-> (assoc-in {:db db
|
||||
:data-store/tx [(chats-store/deactivate-chat-tx chat-id now)]}
|
||||
[:db :chats chat-id :is-active] false)
|
||||
platform/desktop?
|
||||
(assoc-in [:db :current-chat-id] nil)))
|
||||
{:db (-> db
|
||||
(assoc-in [:chats chat-id :is-active] false)
|
||||
(assoc-in [:current-chat-id] nil))
|
||||
:data-store/tx [(chats-store/deactivate-chat-tx chat-id now)]})
|
||||
|
||||
;; TODO: There's a race condition here, as the removal of the filter (async)
|
||||
;; is done at the same time as the removal of the chat, so a message
|
||||
@ -114,7 +118,9 @@
|
||||
;; (remove chat only after the filter has been removed, probably the safest,
|
||||
;; flag the chat to ignore new messages, change receive method for public/group chats)
|
||||
;; For now to keep the code simplier and avoid significant changes, best to leave as it is.
|
||||
(defn remove-chat [chat-id {:keys [db now] :as cofx}]
|
||||
(defn remove-chat
|
||||
"Removes chat completely from app, producing all necessary effects for that"
|
||||
[chat-id {:keys [db now] :as cofx}]
|
||||
(letfn [(remove-transport-fx [chat-id cofx]
|
||||
(when (multi-user-chat? chat-id cofx)
|
||||
(remove-transport chat-id cofx)))]
|
||||
@ -124,7 +130,64 @@
|
||||
(deactivate-chat chat-id)
|
||||
(clear-history chat-id))))
|
||||
|
||||
(defn bot-only-chat? [db chat-id]
|
||||
(let [{:keys [group-chat contacts]} (get-in db [:chats chat-id])]
|
||||
(and (not group-chat)
|
||||
(get-in db [:contacts/contacts (first contacts) :dapp?]))))
|
||||
(defn- send-messages-seen [chat-id message-ids {:keys [db] :as cofx}]
|
||||
(when (not (get-in db [:chats chat-id :public?]))
|
||||
(transport.message/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx)))
|
||||
|
||||
;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future
|
||||
(defn mark-messages-seen
|
||||
"Marks all unviewed loaded messages as seen in particular chat"
|
||||
[chat-id {:keys [db] :as cofx}]
|
||||
(when-let [all-unviewed-ids (seq (get-in db [:chats chat-id :unviewed-messages]))]
|
||||
(let [me (:current-public-key db)
|
||||
updated-statuses (keep (fn [message-id]
|
||||
(some-> db
|
||||
(get-in [:chats chat-id :message-statuses
|
||||
message-id me])
|
||||
(assoc :status :seen)))
|
||||
all-unviewed-ids)
|
||||
loaded-unviewed-ids (map :message-id updated-statuses)]
|
||||
(when (seq loaded-unviewed-ids)
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
{:db (-> (reduce (fn [acc {:keys [message-id status]}]
|
||||
(assoc-in acc [:chats chat-id :message-statuses
|
||||
message-id me :status]
|
||||
status))
|
||||
db
|
||||
updated-statuses)
|
||||
(update-in [:chats chat-id :unviewed-messages]
|
||||
#(apply disj % loaded-unviewed-ids)))
|
||||
:data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]}
|
||||
(send-messages-seen chat-id loaded-unviewed-ids))))))
|
||||
|
||||
(defn- preload-chat-data
|
||||
"Takes chat-id and coeffects map, returns effects necessary when navigating to chat"
|
||||
[chat-id {:keys [db] :as cofx}]
|
||||
(handlers-macro/merge-fx cofx
|
||||
{:db (-> (assoc db :current-chat-id chat-id)
|
||||
(set-chat-ui-props {:validation-messages nil}))}
|
||||
(mark-messages-seen chat-id)))
|
||||
|
||||
(defn navigate-to-chat
|
||||
"Takes coeffects map and chat-id, returns effects necessary for navigation and preloading data"
|
||||
[chat-id {:keys [navigation-replace?]} cofx]
|
||||
(if navigation-replace?
|
||||
(handlers-macro/merge-fx cofx
|
||||
(navigation/navigate-reset {:index 1
|
||||
:actions [{:routeName :home}
|
||||
{:routeName :chat}]})
|
||||
(preload-chat-data chat-id))
|
||||
(handlers-macro/merge-fx cofx
|
||||
(navigation/navigate-to-cofx :chat {})
|
||||
(preload-chat-data chat-id))))
|
||||
|
||||
(defn start-chat
|
||||
"Start a chat, making sure it exists"
|
||||
[chat-id opts {:keys [db] :as cofx}]
|
||||
;; don't allow to open chat with yourself
|
||||
(when (not= (:current-public-key db) chat-id)
|
||||
(handlers-macro/merge-fx cofx
|
||||
(upsert-chat {:chat-id chat-id
|
||||
:is-active true})
|
||||
(navigate-to-chat chat-id opts))))
|
||||
|
@ -1,10 +1,12 @@
|
||||
(ns status-im.models.chat
|
||||
(ns status-im.chat.models.loading
|
||||
(:require [clojure.set :as set]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.data-store.contacts :as contacts-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.utils.contacts :as utils.contacts]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||
|
||||
(def index-messages (partial into {} (map (juxt :message-id identity))))
|
||||
@ -33,20 +35,42 @@
|
||||
{:db (update db :contacts/contacts merge contacts-to-add)
|
||||
:data-store/tx [(contacts-store/save-contacts-tx (vals contacts-to-add))]}))
|
||||
|
||||
(defn- group-chat-messages
|
||||
(defn- sort-references
|
||||
"Sorts message-references sequence primary by clock value,
|
||||
breaking ties by `:message-id`"
|
||||
[messages message-references]
|
||||
(sort-by (juxt (comp :clock-value (partial get messages) :message-id)
|
||||
:message-id)
|
||||
message-references))
|
||||
|
||||
(defn group-chat-messages
|
||||
"Takes chat-id, new messages + cofx and properly groups them
|
||||
into the `:message-groups`index in db"
|
||||
[chat-id messages {:keys [db]}]
|
||||
{:db (reduce (fn [db [datemark grouped-messages]]
|
||||
(update-in db [:chats chat-id :message-groups datemark]
|
||||
(fn [message-references]
|
||||
(->> grouped-messages
|
||||
(map (fn [{:keys [message-id timestamp]}]
|
||||
{:message-id message-id
|
||||
:timestamp-str (time/timestamp->time timestamp)}))
|
||||
(into (or message-references '()))
|
||||
(sort-references (get-in db [:chats chat-id :messages]))))))
|
||||
db
|
||||
(group-by (comp time/day-relative :timestamp)
|
||||
(filter :show? messages)))})
|
||||
|
||||
(defn- group-messages
|
||||
[{:keys [db]}]
|
||||
(reduce-kv (fn [fx chat-id {:keys [messages]}]
|
||||
(models.message/group-messages chat-id (vals messages) fx))
|
||||
(group-chat-messages chat-id (vals messages) fx))
|
||||
{:db db}
|
||||
(:chats db)))
|
||||
|
||||
(defn initialize-chats [{:keys [db
|
||||
default-dapps
|
||||
all-stored-chats
|
||||
get-stored-messages
|
||||
get-stored-user-statuses
|
||||
get-stored-unviewed-messages
|
||||
stored-message-ids] :as cofx}]
|
||||
(defn initialize-chats
|
||||
"Initialize all persisted chats on startup"
|
||||
[{:keys [db default-dapps all-stored-chats get-stored-messages get-stored-user-statuses
|
||||
get-stored-unviewed-messages stored-message-ids] :as cofx}]
|
||||
(let [stored-unviewed-messages (get-stored-unviewed-messages (:current-public-key db))
|
||||
chats (reduce (fn [acc {:keys [chat-id] :as chat}]
|
||||
(let [chat-messages (index-messages (get-stored-messages chat-id))
|
||||
@ -65,11 +89,11 @@
|
||||
{:db (assoc db
|
||||
:chats chats
|
||||
:contacts/dapps default-dapps)}
|
||||
(group-chat-messages)
|
||||
(group-messages)
|
||||
(add-default-contacts)
|
||||
(commands/load-commands commands/register))))
|
||||
|
||||
(defn process-pending-messages
|
||||
(defn initialize-pending-messages
|
||||
"Change status of own messages which are still in `sending` status to `not-sent`
|
||||
(If signal from status-go has not been received)"
|
||||
[{:keys [db]}]
|
||||
@ -89,3 +113,26 @@
|
||||
status))
|
||||
db
|
||||
updated-statuses)}))
|
||||
|
||||
(defn load-more-messages
|
||||
"Loads more messages for current chat"
|
||||
[{{:keys [current-chat-id] :as db} :db
|
||||
get-stored-messages :get-stored-messages
|
||||
get-stored-user-statuses :get-stored-user-statuses :as cofx}]
|
||||
(when-not (get-in db [:chats current-chat-id :all-loaded?])
|
||||
(let [loaded-count (count (get-in db [:chats current-chat-id :messages]))
|
||||
new-messages (get-stored-messages current-chat-id loaded-count)
|
||||
indexed-messages (index-messages new-messages)
|
||||
new-message-ids (keys indexed-messages)
|
||||
new-statuses (get-stored-user-statuses current-chat-id new-message-ids)]
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
{:db (-> db
|
||||
(update-in [:chats current-chat-id :messages] merge indexed-messages)
|
||||
(update-in [:chats current-chat-id :message-statuses] merge new-statuses)
|
||||
(update-in [:chats current-chat-id :not-loaded-message-ids]
|
||||
#(apply disj % new-message-ids))
|
||||
(assoc-in [:chats current-chat-id :all-loaded?]
|
||||
(> constants/default-number-of-messages (count new-messages))))}
|
||||
(group-chat-messages current-chat-id new-messages)
|
||||
(chat-model/mark-messages-seen current-chat-id)))))
|
@ -7,6 +7,7 @@
|
||||
[status-im.utils.ethereum.core :as ethereum]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.models.loading :as chat-loading]
|
||||
[status-im.chat.models.input :as input]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
@ -18,7 +19,6 @@
|
||||
[status-im.transport.message.v1.protocol :as protocol]
|
||||
[status-im.data-store.messages :as messages-store]
|
||||
[status-im.data-store.user-statuses :as user-statuses-store]
|
||||
[status-im.utils.datetime :as datetime]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(def receive-interceptors
|
||||
@ -57,31 +57,6 @@
|
||||
(assoc groups new-datemark message-refs))))
|
||||
{}))}))
|
||||
|
||||
(defn- sort-references
|
||||
"Sorts message-references sequence primary by clock value,
|
||||
breaking ties by `:message-id`"
|
||||
[messages message-references]
|
||||
(sort-by (juxt (comp :clock-value (partial get messages) :message-id)
|
||||
:message-id)
|
||||
message-references))
|
||||
|
||||
(defn- group-messages
|
||||
"Takes chat-id, new messages + cofx and properly groups them
|
||||
into the `:message-groups`index in db"
|
||||
[chat-id messages {:keys [db]}]
|
||||
{:db (reduce (fn [db [datemark grouped-messages]]
|
||||
(update-in db [:chats chat-id :message-groups datemark]
|
||||
(fn [message-references]
|
||||
(->> grouped-messages
|
||||
(map (fn [{:keys [message-id timestamp]}]
|
||||
{:message-id message-id
|
||||
:timestamp-str (time/timestamp->time timestamp)}))
|
||||
(into (or message-references '()))
|
||||
(sort-references (get-in db [:chats chat-id :messages]))))))
|
||||
db
|
||||
(group-by (comp time/day-relative :timestamp)
|
||||
(filter :show? messages)))})
|
||||
|
||||
(defn- add-own-status
|
||||
[chat-id message-id status {:keys [db]}]
|
||||
(let [me (:current-public-key db)
|
||||
@ -115,7 +90,7 @@
|
||||
(handlers-macro/merge-fx cofx
|
||||
fx
|
||||
(re-index-message-groups chat-id)
|
||||
(group-messages chat-id [message]))))))
|
||||
(chat-loading/group-chat-messages chat-id [message]))))))
|
||||
|
||||
(def ^:private- add-single-message (partial add-message false))
|
||||
(def ^:private- add-batch-message (partial add-message true))
|
||||
@ -175,7 +150,6 @@
|
||||
(display-notification chat-id)
|
||||
(send-message-seen chat-id message-id (and (not public?)
|
||||
current-chat?
|
||||
(not (chat-model/bot-only-chat? db chat-id))
|
||||
(not (= constants/system from))
|
||||
(not (:outgoing message)))))))
|
||||
|
||||
@ -211,7 +185,7 @@
|
||||
(fn [chat-id cofx]
|
||||
(handlers-macro/merge-fx cofx
|
||||
(re-index-message-groups chat-id)
|
||||
(group-messages chat-id (get chat->message chat-id))))
|
||||
(chat-loading/group-chat-messages chat-id (get chat->message chat-id))))
|
||||
chat-ids)))
|
||||
|
||||
(defn system-message [chat-id message-id timestamp content]
|
||||
|
@ -11,7 +11,6 @@
|
||||
(s/def :chat/chat-list-ui-props (s/nilable map?))
|
||||
(s/def :chat/layout-height (s/nilable number?)) ; height of chat's view layout
|
||||
(s/def :chat/selected-participants (s/nilable set?))
|
||||
(s/def :chat/chat-loaded-callbacks (s/nilable map?))
|
||||
(s/def :chat/public-group-topic (s/nilable string?))
|
||||
(s/def :chat/public-group-topic-error (s/nilable string?))
|
||||
(s/def :chat/messages (s/nilable map?)) ; messages indexed by message-id
|
||||
|
@ -4,11 +4,11 @@
|
||||
[status-im.chat.constants :as chat-constants]
|
||||
[status-im.chat.models.input :as input-model]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.input :as commands-input]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.gfycat.core :as gfycat]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.constants :as const]
|
||||
[status-im.models.transactions :as transactions]))
|
||||
|
||||
(reg-sub :get-chats :chats)
|
||||
@ -76,12 +76,8 @@
|
||||
platform/ios? kb-height
|
||||
:default 0)))
|
||||
|
||||
(defn- active-chat? [[_ chat]]
|
||||
(and (:is-active chat)
|
||||
(not= const/console-chat-id (:chat-id chat))))
|
||||
|
||||
(defn active-chats [chats]
|
||||
(into {} (filter active-chat? chats)))
|
||||
(into {} (filter (comp :is-active second) chats)))
|
||||
|
||||
(reg-sub
|
||||
:get-active-chats
|
||||
@ -257,7 +253,7 @@
|
||||
:<- [:get-current-chat-ui-prop :selection]
|
||||
:<- [:get-commands-for-chat]
|
||||
(fn [[{:keys [input-text]} selection commands]]
|
||||
(commands/selected-chat-command input-text selection commands)))
|
||||
(commands-input/selected-chat-command input-text selection commands)))
|
||||
|
||||
(reg-sub
|
||||
:chat-input-placeholder
|
||||
|
@ -1,10 +0,0 @@
|
||||
(ns status-im.chat.views.message.datemark
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[clojure.string :as str]
|
||||
[status-im.chat.styles.message.datemark :as st]))
|
||||
|
||||
(defn chat-datemark [value]
|
||||
[react/view st/datemark-wrapper
|
||||
[react/view st/datemark
|
||||
[react/text {:style st/datemark-text}
|
||||
(str/capitalize value)]]])
|
@ -27,8 +27,6 @@
|
||||
(def default-number-of-messages 20)
|
||||
(def blocks-per-hour 120)
|
||||
|
||||
(def console-chat-id "console")
|
||||
|
||||
(def inbox-password "status-offline-inbox")
|
||||
|
||||
(def default-network config/default-network)
|
||||
|
@ -1,5 +1,6 @@
|
||||
(ns status-im.init.core
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.models.loading :as chat-loading]
|
||||
[status-im.accounts.login.core :as accounts.login]
|
||||
[status-im.accounts.update.core :as accounts.update]
|
||||
[status-im.constants :as constants]
|
||||
@ -7,7 +8,6 @@
|
||||
[status-im.data-store.realm.core :as realm]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.models.browser :as browser]
|
||||
[status-im.models.chat :as chat]
|
||||
[status-im.models.contacts :as models.contacts]
|
||||
[status-im.models.dev-server :as models.dev-server]
|
||||
[status-im.protocol.core :as protocol]
|
||||
@ -143,7 +143,6 @@
|
||||
network network-status peers-count peers-summary view-id navigation-stack
|
||||
status-module-initialized? status-node-started? device-UUID semaphores]
|
||||
:or {network (get app-db :network)}} db
|
||||
console-contact (get contacts constants/console-chat-id)
|
||||
current-account (get accounts address)
|
||||
account-network-id (get current-account :network network)
|
||||
account-network (get-in current-account [:networks account-network-id])]
|
||||
@ -166,9 +165,7 @@
|
||||
:semaphores semaphores
|
||||
:web3 web3)
|
||||
(= view-id :create-account)
|
||||
(assoc-in [:accounts/create :step] :enter-name)
|
||||
console-contact
|
||||
(assoc :contacts/contacts {constants/console-chat-id console-contact}))}))
|
||||
(assoc-in [:accounts/create :step] :enter-name))}))
|
||||
|
||||
(defn initialize-wallet [cofx]
|
||||
(when-not platform/desktop?
|
||||
@ -196,8 +193,8 @@
|
||||
(protocol/initialize-protocol address)
|
||||
(models.contacts/load-contacts)
|
||||
(models.dev-server/start-if-needed)
|
||||
(chat/initialize-chats)
|
||||
(chat/process-pending-messages)
|
||||
(chat-loading/initialize-chats)
|
||||
(chat-loading/initialize-pending-messages)
|
||||
(browser/initialize-browsers)
|
||||
(browser/initialize-dapp-permissions)
|
||||
(initialize-wallet)
|
||||
|
@ -3,7 +3,9 @@
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.react-native.js-dependencies :as rn]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.utils.platform :as platform]))
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||
|
||||
;; Work in progress namespace responsible for push notifications and interacting
|
||||
;; with Firebase Cloud Messaging.
|
||||
@ -86,8 +88,9 @@
|
||||
;; TODO(yenda) why do we ignore the notification if
|
||||
;; it is not for the current account ?
|
||||
(when (= to current-public-key)
|
||||
{:db (update db :push-notifications/stored dissoc to)
|
||||
:dispatch [:navigate-to-chat from]})
|
||||
(handlers-macro/merge-fx cofx
|
||||
{:db (update db :push-notifications/stored dissoc to)}
|
||||
(chat-model/navigate-to-chat from nil)))
|
||||
(store-event event cofx))))
|
||||
|
||||
(defn parse-notification-payload [s]
|
||||
|
@ -5,7 +5,7 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.chat-icon.styles :as styles]
|
||||
[status-im.ui.components.styles :as components.styles]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.react-native.resources :as resources]))
|
||||
|
||||
(defn default-chat-icon [name styles]
|
||||
|
@ -13,7 +13,7 @@
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.react :as components]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[re-frame.core :as re-frame]
|
||||
[cljs.spec.alpha :as spec]
|
||||
[status-im.utils.platform :as platform]
|
||||
|
@ -2,7 +2,7 @@
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.accounts.styles :as styles]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.status-bar.view :as status-bar]
|
||||
|
@ -1,19 +1,10 @@
|
||||
(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 ::name :global/not-empty-string)
|
||||
|
||||
(spec/def ::topic (spec/and :global/not-empty-string
|
||||
::legal-name
|
||||
(partial re-matches #"[a-z0-9\-]+")))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.views.actions
|
||||
(ns status-im.ui.screens.chat.actions
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
@ -1,14 +1,14 @@
|
||||
(ns status-im.chat.views.bottom-info
|
||||
(ns status-im.ui.screens.chat.bottom-info
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.screen :as styles]
|
||||
[status-im.ui.screens.chat.styles.main :as styles]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.animation :as anim]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.utils.core :as utils]
|
||||
[status-im.utils.identicon :as identicon]))
|
||||
|
@ -1,10 +1,10 @@
|
||||
(ns status-im.chat.views.input.animations.expandable
|
||||
(ns status-im.ui.screens.chat.input.animations.expandable
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [reagent.core :as reagent]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.animations :as style]
|
||||
[status-im.chat.styles.input.input :as input-style]
|
||||
[status-im.ui.screens.chat.styles.animations :as style]
|
||||
[status-im.ui.screens.chat.styles.input.input :as input-style]
|
||||
[status-im.utils.platform :as platform]))
|
||||
|
||||
(def top-offset 100)
|
@ -1,14 +1,14 @@
|
||||
(ns status-im.chat.views.input.input
|
||||
(ns status-im.ui.screens.chat.input.input
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[reagent.core :as reagent]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.constants :as constants]
|
||||
[status-im.chat.styles.input.input :as style]
|
||||
[status-im.chat.views.input.parameter-box :as parameter-box]
|
||||
[status-im.chat.views.input.send-button :as send-button]
|
||||
[status-im.chat.views.input.suggestions :as suggestions]
|
||||
[status-im.chat.views.input.validation-messages :as validation-messages]
|
||||
[status-im.ui.screens.chat.styles.input.input :as style]
|
||||
[status-im.ui.screens.chat.input.parameter-box :as parameter-box]
|
||||
[status-im.ui.screens.chat.input.send-button :as send-button]
|
||||
[status-im.ui.screens.chat.input.suggestions :as suggestions]
|
||||
[status-im.ui.screens.chat.input.validation-messages :as validation-messages]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.colors :as colors]
|
@ -1,9 +1,8 @@
|
||||
(ns status-im.chat.views.input.parameter-box
|
||||
(ns status-im.ui.screens.chat.input.parameter-box
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.chat.views.input.animations.expandable :as expandable]
|
||||
[status-im.chat.styles.input.parameter-box :as style]
|
||||
[status-im.ui.components.react :as react]
|
||||
[taoensso.timbre :as log]))
|
||||
(:require [status-im.ui.screens.chat.input.animations.expandable :as expandable]
|
||||
[status-im.ui.screens.chat.styles.input.parameter-box :as style]
|
||||
[status-im.ui.components.react :as react]))
|
||||
|
||||
(defview parameter-box-container []
|
||||
(letsubs [parameter-box [:chat-parameter-box]]
|
@ -1,12 +1,11 @@
|
||||
(ns status-im.chat.views.input.send-button
|
||||
(ns status-im.ui.screens.chat.input.send-button
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.chat.styles.input.send-button :as style]
|
||||
[status-im.ui.screens.chat.styles.input.send-button :as style]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.icons.vector-icons :as vi]
|
||||
[status-im.utils.utils :as utils]))
|
||||
[status-im.ui.components.icons.vector-icons :as vi]))
|
||||
|
||||
(defn send-button-view-on-update [{:keys [spin-value command-completion]}]
|
||||
(fn [_]
|
@ -1,12 +1,10 @@
|
||||
(ns status-im.chat.views.input.suggestions
|
||||
(ns status-im.ui.screens.chat.input.suggestions
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.input.suggestions :as style]
|
||||
[status-im.chat.views.input.animations.expandable :as expandable]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.i18n :as i18n]
|
||||
[taoensso.timbre :as log]))
|
||||
[status-im.ui.screens.chat.styles.input.suggestions :as style]
|
||||
[status-im.ui.screens.chat.input.animations.expandable :as expandable]
|
||||
[status-im.chat.commands.core :as commands]))
|
||||
|
||||
(defn suggestion-item [{:keys [on-press name description last? accessibility-label]}]
|
||||
[react/touchable-highlight (cond-> {:on-press on-press}
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.views.input.utils
|
||||
(ns status-im.ui.screens.chat.input.utils
|
||||
(:require [taoensso.timbre :as log]
|
||||
[status-im.ui.components.toolbar.styles :as toolbar-st]
|
||||
[status-im.utils.platform :as p]))
|
@ -1,8 +1,8 @@
|
||||
(ns status-im.chat.views.input.validation-messages
|
||||
(ns status-im.ui.screens.chat.input.validation-messages
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.input.validation-message :as style]
|
||||
[status-im.ui.screens.chat.styles.input.validation-message :as style]
|
||||
[status-im.i18n :as i18n]))
|
||||
|
||||
(defn validation-message [{:keys [title description]}]
|
10
src/status_im/ui/screens/chat/message/datemark.cljs
Normal file
10
src/status_im/ui/screens/chat/message/datemark.cljs
Normal file
@ -0,0 +1,10 @@
|
||||
(ns status-im.ui.screens.chat.message.datemark
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.screens.chat.styles.message.datemark :as style]))
|
||||
|
||||
(defn chat-datemark [value]
|
||||
[react/view style/datemark-wrapper
|
||||
[react/view style/datemark
|
||||
[react/text {:style style/datemark-text}
|
||||
(string/capitalize value)]]])
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.views.message.message
|
||||
(ns status-im.ui.screens.chat.message.message
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
@ -9,9 +9,9 @@
|
||||
[status-im.ui.components.action-sheet :as action-sheet]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.chat.styles.message.message :as style]
|
||||
[status-im.chat.styles.message.command-pill :as pill-style]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.styles.message.message :as style]
|
||||
[status-im.ui.screens.chat.styles.message.command-pill :as pill-style]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.utils.core :as utils]
|
@ -1,18 +1,11 @@
|
||||
(ns status-im.chat.views.message.options
|
||||
(ns status-im.ui.screens.chat.message.options
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[reagent.core :as reagent]
|
||||
[clojure.string :as string]
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.chat.views.bottom-info :as bottom-info]
|
||||
[status-im.chat.styles.screen :as styles]
|
||||
[status-im.chat.styles.message.options :as options.styles]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.animation :as anim]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.utils.core :as utils]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[status-im.ui.screens.chat.bottom-info :as bottom-info]
|
||||
[status-im.ui.screens.chat.styles.main :as styles]
|
||||
[status-im.ui.screens.chat.styles.message.options :as options.styles]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]))
|
||||
|
||||
(defn action-item [{:keys [label icon style on-press]}]
|
@ -1,7 +1,7 @@
|
||||
(ns status-im.chat.views.photos
|
||||
(ns status-im.ui.screens.chat.photos
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [status-im.ui.components.react :as react]
|
||||
[status-im.chat.styles.photos :as style]
|
||||
[status-im.ui.screens.chat.styles.photos :as style]
|
||||
[status-im.utils.identicon :as identicon]
|
||||
[clojure.string :as string]
|
||||
[status-im.react-native.resources :as resources]))
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.animations
|
||||
(ns status-im.ui.screens.chat.styles.animations
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(def header-draggable-icon "rgba(73, 84, 93, 0.23)")
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.input.input
|
||||
(ns status-im.ui.screens.chat.styles.input.input
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.input.parameter-box
|
||||
(ns status-im.ui.screens.chat.styles.input.parameter-box
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.input.send-button
|
||||
(ns status-im.ui.screens.chat.styles.input.send-button
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defn send-message-container [rotation]
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.input.suggestions
|
||||
(ns status-im.ui.screens.chat.styles.input.suggestions
|
||||
(:require-macros [status-im.utils.styles :refer [defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]
|
||||
[status-im.ui.components.colors :as colors]
|
@ -1,6 +1,5 @@
|
||||
(ns status-im.chat.styles.input.validation-message
|
||||
(:require [status-im.chat.constants :as constants]
|
||||
[status-im.ui.components.styles :as common]))
|
||||
(ns status-im.ui.screens.chat.styles.input.validation-message
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
||||
(defn root [bottom]
|
||||
{:flex-direction :column
|
||||
@ -20,4 +19,4 @@
|
||||
(def message-description
|
||||
{:color common/color-white
|
||||
:font-size 12
|
||||
:opacity 0.9})
|
||||
:opacity 0.9})
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.screen
|
||||
(ns status-im.ui.screens.chat.styles.main
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as component.styles]
|
||||
[status-im.ui.components.colors :as colors]))
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.message.command-pill
|
||||
(ns status-im.ui.screens.chat.styles.message.command-pill
|
||||
(:require [status-im.utils.platform :as p]
|
||||
[status-im.ui.components.styles :refer [color-white]]))
|
||||
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.message.datemark
|
||||
(ns status-im.ui.screens.chat.styles.message.datemark
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle]])
|
||||
(:require [status-im.ui.components.styles :as common]))
|
||||
|
@ -1,8 +1,8 @@
|
||||
(ns status-im.chat.styles.message.message
|
||||
(ns status-im.ui.screens.chat.styles.message.message
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as styles]
|
||||
[status-im.chat.styles.photos :as photos]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.screens.chat.styles.photos :as photos]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.constants :as constants]))
|
||||
|
@ -1,8 +1,7 @@
|
||||
(ns status-im.chat.styles.message.options
|
||||
(ns status-im.ui.screens.chat.styles.message.options
|
||||
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
|
||||
(:require [status-im.ui.components.styles :as styles]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.constants :as constants]))
|
||||
[status-im.ui.components.colors :as colors]))
|
||||
|
||||
(defstyle row
|
||||
{:flex-direction :row
|
@ -1,4 +1,4 @@
|
||||
(ns status-im.chat.styles.photos
|
||||
(ns status-im.ui.screens.chat.styles.photos
|
||||
(:require [status-im.ui.components.colors :as colors]))
|
||||
|
||||
(def default-size 36)
|
@ -1,31 +1,26 @@
|
||||
(ns status-im.chat.views.toolbar-content
|
||||
(ns status-im.ui.screens.chat.toolbar-content
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[cljs-time.core :as t]
|
||||
[status-im.ui.components.react :as react]
|
||||
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.chat.styles.screen :as st]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.screens.chat.styles.main :as st]
|
||||
[status-im.utils.datetime :as time]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.utils.gfycat.core :refer [generate-gfy]]
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
[status-im.ui.components.chat-icon.screen :as chat-icon.screen]
|
||||
[status-im.ui.components.common.common :as components.common]
|
||||
[status-im.ui.components.styles :as common.styles]))
|
||||
|
||||
(defn- online-text [contact chat-id]
|
||||
(cond
|
||||
(= console-chat-id chat-id) (i18n/label :t/available)
|
||||
contact (let [last-online (get contact :last-online)
|
||||
last-online-date (time/to-date last-online)
|
||||
now-date (t/now)]
|
||||
(if (and (pos? last-online)
|
||||
(<= last-online-date now-date))
|
||||
(time/time-ago last-online-date)
|
||||
(i18n/label :t/active-unknown)))
|
||||
:else (i18n/label :t/active-unknown)))
|
||||
(if contact
|
||||
(let [last-online (get contact :last-online)
|
||||
last-online-date (time/to-date last-online)
|
||||
now-date (t/now)]
|
||||
(if (and (pos? last-online)
|
||||
(<= last-online-date now-date))
|
||||
(time/time-ago last-online-date)
|
||||
(i18n/label :t/active-unknown)))
|
||||
(i18n/label :t/active-unknown)))
|
||||
|
||||
(defn- in-progress-text [{:keys [highestBlock currentBlock startBlock]}]
|
||||
(let [total (- highestBlock startBlock)
|
@ -1,23 +1,18 @@
|
||||
(ns status-im.chat.screen
|
||||
(ns status-im.ui.screens.chat.views
|
||||
(:require-macros [status-im.utils.views :refer [defview letsubs]])
|
||||
(:require [clojure.string :as string]
|
||||
[re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.models.contact :as models.contact]
|
||||
[status-im.chat.styles.screen :as style]
|
||||
[status-im.ui.screens.chat.styles.main :as style]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.chat.views.toolbar-content :as toolbar-content]
|
||||
[status-im.chat.views.message.message :as message]
|
||||
[status-im.chat.views.message.datemark :as message-datemark]
|
||||
[status-im.chat.views.input.input :as input]
|
||||
[status-im.chat.views.actions :as actions]
|
||||
[status-im.chat.views.bottom-info :as bottom-info]
|
||||
[status-im.chat.views.message.options :as message-options]
|
||||
[status-im.chat.views.message.datemark :as message-datemark]
|
||||
[status-im.chat.views.message.message :as message]
|
||||
[status-im.chat.views.toolbar-content :as toolbar-content]
|
||||
[status-im.ui.screens.chat.input.input :as input]
|
||||
[status-im.ui.screens.chat.actions :as actions]
|
||||
[status-im.ui.screens.chat.bottom-info :as bottom-info]
|
||||
[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.screens.chat.toolbar-content :as toolbar-content]
|
||||
[status-im.ui.components.animation :as animation]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
@ -56,19 +51,17 @@
|
||||
{:keys [group-chat chat-id contacts]} [:get-current-chat]]
|
||||
[react/view
|
||||
[status-bar/status-bar]
|
||||
(if (= chat-id constants/console-chat-id)
|
||||
[toolbar/simple-toolbar name]
|
||||
[toolbar/platform-agnostic-toolbar {}
|
||||
(toolbar/nav-back-count {:home? true})
|
||||
[toolbar-content/toolbar-content-view]
|
||||
[toolbar/actions [{:icon :icons/wallet
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :wallet-modal-button}
|
||||
:handler #(re-frame/dispatch [:navigate-to :wallet-modal])}
|
||||
{:icon :icons/options
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id name group-chat public?)}]]])
|
||||
[toolbar/platform-agnostic-toolbar {}
|
||||
(toolbar/nav-back-count {:home? true})
|
||||
[toolbar-content/toolbar-content-view]
|
||||
[toolbar/actions [{:icon :icons/wallet
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :wallet-modal-button}
|
||||
:handler #(re-frame/dispatch [:navigate-to :wallet-modal])}
|
||||
{:icon :icons/options
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id name group-chat public?)}]]]
|
||||
(when-not (or public? group-chat) [add-contact-bar (first contacts)])]))
|
||||
|
||||
(defmulti message-row (fn [{{:keys [type]} :row}] type))
|
||||
@ -113,16 +106,10 @@
|
||||
(when one-to-one
|
||||
[vector-icons/icon :icons/lock])
|
||||
[react/text {:style style/empty-chat-text}
|
||||
(cond
|
||||
(= chat-id constants/console-chat-id)
|
||||
(i18n/label :t/empty-chat-description-console)
|
||||
|
||||
one-to-one
|
||||
(if one-to-one
|
||||
[react/text style/empty-chat-container-one-to-one
|
||||
(i18n/label :t/empty-chat-description-one-to-one)
|
||||
[react/text {:style style/empty-chat-text-name} (:name contact)]]
|
||||
|
||||
:else
|
||||
(i18n/label :t/empty-chat-description))]])))
|
||||
|
||||
(defview messages-view [group-chat]
|
@ -1,6 +1,6 @@
|
||||
(ns status-im.ui.screens.contacts.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.chat.events :as chat.events]
|
||||
[status-im.chat.models :as chat.models]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.models.contact :as models.contact]
|
||||
[status-im.ui.screens.add-new.new-chat.db :as new-chat.db]
|
||||
@ -15,7 +15,7 @@
|
||||
(handlers-macro/merge-fx
|
||||
cofx
|
||||
(models.contact/add-contact whisper-id)
|
||||
(chat.events/start-chat whisper-id {:navigation-replace? true})))
|
||||
(chat.models/start-chat whisper-id {:navigation-replace? true})))
|
||||
|
||||
(re-frame/reg-cofx
|
||||
:get-default-contacts
|
||||
|
@ -272,7 +272,6 @@
|
||||
:chat/message-data
|
||||
:chat/message-status
|
||||
:chat/selected-participants
|
||||
:chat/chat-loaded-callbacks
|
||||
:chat/public-group-topic
|
||||
:chat/public-group-topic-error
|
||||
:chat/messages
|
||||
|
@ -3,8 +3,8 @@
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.components.icons.vector-icons :as icons]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.styles.message.message :as message.style]
|
||||
[status-im.chat.views.message.message :as message]
|
||||
[status-im.ui.screens.chat.styles.message.message :as message.style]
|
||||
[status-im.ui.screens.chat.message.message :as message]
|
||||
[status-im.utils.gfycat.core :as gfycat.core]
|
||||
[taoensso.timbre :as log]
|
||||
[reagent.core :as reagent]
|
||||
@ -16,7 +16,7 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.components.connectivity.view :as connectivity]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.chat.views.message.datemark :as message.datemark]
|
||||
[status-im.ui.screens.chat.message.datemark :as message.datemark]
|
||||
[status-im.ui.screens.desktop.main.tabs.profile.views :as profile.views]
|
||||
[status-im.ui.components.icons.vector-icons :as vector-icons]
|
||||
[status-im.ui.screens.desktop.main.chat.styles :as styles]
|
||||
|
@ -2,14 +2,12 @@
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.chat.models.message :as models.message]
|
||||
[status-im.chat.models :as models.chat]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.transport.message.v1.group-chat :as group-chat]
|
||||
[status-im.transport.message.core :as transport]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]
|
||||
[status-im.data-store.chats :as chats-store]
|
||||
[status-im.data-store.messages :as messages-store]))
|
||||
[status-im.data-store.chats :as chats-store]))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:show-group-chat-profile
|
||||
|
@ -1,7 +1,6 @@
|
||||
(ns status-im.ui.screens.home.views
|
||||
(:require-macros [status-im.utils.views :as views])
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.ui.components.colors :as colors]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.react :as react]
|
||||
@ -44,20 +43,18 @@
|
||||
inner-item-view (if (:chat-id home-item)
|
||||
inner-item/home-list-chat-item-inner-view
|
||||
inner-item/home-list-browser-item-inner-view)
|
||||
is-deletable? (not= (:chat-id home-item) constants/console-chat-id)
|
||||
offset-x (animation/create-value (if (and is-deletable? swiped?) styles/delete-button-width 0))
|
||||
offset-x (animation/create-value (if swiped? styles/delete-button-width 0))
|
||||
swipe-pan-responder (responder/swipe-pan-responder offset-x styles/delete-button-width home-item-id swiped?)
|
||||
swipe-pan-handler (if is-deletable? (responder/pan-handlers swipe-pan-responder) {})]
|
||||
swipe-pan-handler (responder/pan-handlers swipe-pan-responder)]
|
||||
[react/view (assoc swipe-pan-handler :accessibility-label :chat-item)
|
||||
[react/animated-view {:style {:flex 1 :right offset-x}}
|
||||
[inner-item-view home-item]
|
||||
(when is-deletable?
|
||||
[react/touchable-highlight {:style styles/delete-icon-highlight
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:set-swipe-position home-item-id false])
|
||||
(re-frame/dispatch [delete-action home-item-id]))}
|
||||
[react/view {:style styles/delete-icon-container}
|
||||
[vector-icons/icon :icons/delete {:color colors/red}]]])]])))
|
||||
[react/touchable-highlight {:style styles/delete-icon-highlight
|
||||
:on-press #(do
|
||||
(re-frame/dispatch [:set-swipe-position home-item-id false])
|
||||
(re-frame/dispatch [delete-action home-item-id]))}
|
||||
[react/view {:style styles/delete-icon-container}
|
||||
[vector-icons/icon :icons/delete {:color colors/red}]]]]])))
|
||||
|
||||
;;do not remove view-id and will-update or will-unmount handlers, this is how it works
|
||||
(views/defview welcome [view-id]
|
||||
|
@ -90,12 +90,11 @@
|
||||
timestamp]}]
|
||||
(letsubs [last-message [:get-last-message chat-id]
|
||||
chat-name [:get-chat-name chat-id]]
|
||||
(let [hide-dapp? (= chat-id const/console-chat-id)
|
||||
truncated-chat-name (utils/truncate-str chat-name 30)]
|
||||
(let [truncated-chat-name (utils/truncate-str chat-name 30)]
|
||||
[react/touchable-highlight {:on-press #(re-frame/dispatch [:navigate-to-chat chat-id])}
|
||||
[react/view styles/chat-container
|
||||
[react/view styles/chat-icon-container
|
||||
[chat-icon.screen/chat-icon-view-chat-list chat-id group-chat truncated-chat-name color online hide-dapp?]]
|
||||
[chat-icon.screen/chat-icon-view-chat-list chat-id group-chat truncated-chat-name color online false]]
|
||||
[react/view styles/chat-info-container
|
||||
[react/view styles/item-upper-container
|
||||
[chat-list-item-name truncated-chat-name group-chat public? public-key]
|
||||
|
@ -2,14 +2,12 @@
|
||||
(:require [cljs.spec.alpha :as spec]
|
||||
[clojure.string :as string]
|
||||
[status-im.chat.constants :as chat.constants]
|
||||
[status-im.constants :as constants]
|
||||
[status-im.utils.homoglyph :as homoglyph]))
|
||||
|
||||
(defn correct-name? [username]
|
||||
(when-let [username (some-> username (string/trim))]
|
||||
(every? false?
|
||||
[(string/blank? username)
|
||||
(homoglyph/matches username constants/console-chat-id)
|
||||
(string/includes? username chat.constants/command-char)])))
|
||||
|
||||
(defn base64-encoded-image-path? [photo-path]
|
||||
|
@ -4,8 +4,8 @@
|
||||
[status-im.ui.components.react :as react]
|
||||
[status-im.ui.screens.profile.navigation]
|
||||
[status-im.accounts.update.core :as accounts.update]
|
||||
[status-im.chat.events :as chat-events]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.chat.models :as chat-models]
|
||||
[status-im.chat.commands.input :as commands-input]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]
|
||||
[status-im.utils.image-processing :as image-processing]
|
||||
[taoensso.timbre :as log]))
|
||||
@ -24,8 +24,8 @@
|
||||
(defn send-transaction [chat-id {:keys [db] :as cofx}]
|
||||
(let [send-command (get-in db [:id->command ["send" #{:personal-chats}]])]
|
||||
(handlers-macro/merge-fx cofx
|
||||
(chat-events/start-chat chat-id {:navigation-replace? true})
|
||||
(commands/select-chat-input-command send-command nil))))
|
||||
(chat-models/start-chat chat-id {:navigation-replace? true})
|
||||
(commands-input/select-chat-input-command send-command nil))))
|
||||
|
||||
(defn- valid-name? [name]
|
||||
(spec/valid? :profile/name name))
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
[status-im.ui.screens.progress.views :refer [progress]]
|
||||
|
||||
[status-im.chat.screen :refer [chat]]
|
||||
[status-im.ui.screens.chat.views :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.ui.screens.add-new.new-public-chat.view :refer [new-public-chat]]
|
||||
|
@ -6,7 +6,7 @@
|
||||
[status-im.i18n :as i18n]
|
||||
[status-im.ui.components.bottom-buttons.view :as bottom-buttons]
|
||||
[status-im.ui.components.button.view :as button]
|
||||
[status-im.chat.views.photos :as photos]
|
||||
[status-im.ui.screens.chat.photos :as photos]
|
||||
[status-im.ui.components.list.views :as list]
|
||||
[status-im.ui.components.list.styles :as list.styles]
|
||||
[status-im.ui.components.list-selection :as list-selection]
|
||||
|
@ -1,31 +1,25 @@
|
||||
(ns status-im.ui.screens.wallet.request.events
|
||||
(:require [re-frame.core :as re-frame]
|
||||
[status-im.ui.screens.wallet.db :as wallet-db]
|
||||
[status-im.ui.screens.navigation :as navigation]
|
||||
[status-im.utils.handlers :as handlers]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]
|
||||
[status-im.chat.commands.core :as commands]
|
||||
[status-im.utils.money :as money]))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
::wallet-send-chat-request
|
||||
[re-frame/trim-v]
|
||||
(fn [{:keys [db] :as cofx} [asset amount]]
|
||||
(handlers-macro/merge-fx cofx
|
||||
{:dispatch [:send-current-message]}
|
||||
(commands/select-chat-input-command
|
||||
(get-in db [:id->command ["request" #{:personal-chats}]]) [asset amount]))))
|
||||
[status-im.chat.models :as chat-model]
|
||||
[status-im.chat.commands.sending :as commands-sending]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.handlers-macro :as handlers-macro]))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet-send-request
|
||||
[re-frame/trim-v]
|
||||
(fn [_ [whisper-identity amount symbol decimals]]
|
||||
(fn [{:keys [db] :as cofx} [_ whisper-identity amount symbol decimals]]
|
||||
(assert whisper-identity)
|
||||
;; TODO(janherich) remove this dispatch sequence, there is absolutely no need for that :/
|
||||
{:dispatch-n [[:navigate-back]
|
||||
[:navigate-to :home]
|
||||
[:add-chat-loaded-event whisper-identity
|
||||
[::wallet-send-chat-request (name symbol) (str (money/internal->formatted amount symbol decimals))]]
|
||||
[:start-chat whisper-identity]]}))
|
||||
(let [request-command (get-in db [:id->command ["request" #{:personal-chats}]])]
|
||||
(handlers-macro/merge-fx cofx
|
||||
(navigation/navigate-to-clean :home)
|
||||
(chat-model/start-chat whisper-identity nil)
|
||||
(commands-sending/send whisper-identity
|
||||
request-command
|
||||
{:asset (name symbol)
|
||||
:amount (str (money/internal->formatted amount symbol decimals))})))))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:wallet.request/set-and-validate-amount
|
||||
|
@ -117,62 +117,3 @@
|
||||
(core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "contact"})))))))
|
||||
|
||||
(deftest selected-chat-command-test
|
||||
(let [fx (core/load-commands #{TestCommandInstance AnotherTestCommandInstance} {:db {}})
|
||||
commands (core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "contact"})]
|
||||
(testing "Text not beggining with the command special charactes `/` is recognised"
|
||||
(is (not (core/selected-chat-command "test-command 1" nil commands))))
|
||||
(testing "Command not matching any available commands is not recognised as well"
|
||||
(is (not (core/selected-chat-command "/another-test-command" nil commands))))
|
||||
(testing "Available correctly entered command is recognised"
|
||||
(is (= TestCommandInstance
|
||||
(get (core/selected-chat-command "/test-command" nil commands) :type))))
|
||||
(testing "Command completion and param position are determined as well"
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(core/selected-chat-command "/test-command 1 " 17 commands)]
|
||||
(is (= 1 current-param-position))
|
||||
(is (= :less-then-needed command-completion)))
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(core/selected-chat-command "/test-command 1 2 3" 20 commands)]
|
||||
(is (= 2 current-param-position))
|
||||
(is (= :complete command-completion))))))
|
||||
|
||||
(deftest set-command-parameter-test
|
||||
(testing "Setting command parameter correctly updates the text input"
|
||||
(let [create-cofx (fn [input-text]
|
||||
{:db {:chats {"test" {:input-text input-text}}
|
||||
:current-chat-id "test"}})]
|
||||
(is (= "/test-command first-value "
|
||||
(get-in (core/set-command-parameter
|
||||
false 0 "first-value"
|
||||
(create-cofx "/test-command"))
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (core/set-command-parameter
|
||||
false 1 "second-value"
|
||||
(create-cofx "/test-command first-value edited \"last value\""))
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (core/set-command-parameter
|
||||
false 2 "last value"
|
||||
(create-cofx "/test-command first-value second-value"))
|
||||
[:db :chats "test" :input-text]))))))
|
||||
|
||||
(deftest parse-parameters-test
|
||||
(testing "testing that parse-parameters work correctly"
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"
|
||||
:last-param "3"}
|
||||
(core/parse-parameters test-command-parameters "/test-command 1 2 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2 2"
|
||||
:last-param "3"}
|
||||
(core/parse-parameters test-command-parameters "/test-command 1 \"2 2\" 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"}
|
||||
(core/parse-parameters test-command-parameters "/test-command 1 2")))
|
||||
(is (= {}
|
||||
(core/parse-parameters test-command-parameters "/test-command ")))))
|
||||
|
64
test/cljs/status_im/test/chat/commands/input.cljs
Normal file
64
test/cljs/status_im/test/chat/commands/input.cljs
Normal file
@ -0,0 +1,64 @@
|
||||
(ns status-im.test.chat.commands.input
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.test.chat.commands.core :as test-core]
|
||||
[status-im.chat.commands.core :as core]
|
||||
[status-im.chat.commands.input :as input]))
|
||||
|
||||
(deftest selected-chat-command-test
|
||||
(let [fx (core/load-commands #{test-core/TestCommandInstance test-core/AnotherTestCommandInstance} {:db {}})
|
||||
commands (core/chat-commands (get-in fx [:db :id->command])
|
||||
(get-in fx [:db :access-scope->command-id])
|
||||
{:chat-id "contact"})]
|
||||
(testing "Text not beggining with the command special charactes `/` is recognised"
|
||||
(is (not (input/selected-chat-command "test-command 1" nil commands))))
|
||||
(testing "Command not matching any available commands is not recognised as well"
|
||||
(is (not (input/selected-chat-command "/another-test-command" nil commands))))
|
||||
(testing "Available correctly entered command is recognised"
|
||||
(is (= test-core/TestCommandInstance
|
||||
(get (input/selected-chat-command "/test-command" nil commands) :type))))
|
||||
(testing "Command completion and param position are determined as well"
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(input/selected-chat-command "/test-command 1 " 17 commands)]
|
||||
(is (= 1 current-param-position))
|
||||
(is (= :less-then-needed command-completion)))
|
||||
(let [{:keys [current-param-position command-completion]}
|
||||
(input/selected-chat-command "/test-command 1 2 3" 20 commands)]
|
||||
(is (= 2 current-param-position))
|
||||
(is (= :complete command-completion))))))
|
||||
|
||||
(deftest set-command-parameter-test
|
||||
(testing "Setting command parameter correctly updates the text input"
|
||||
(let [create-cofx (fn [input-text]
|
||||
{:db {:chats {"test" {:input-text input-text}}
|
||||
:current-chat-id "test"}})]
|
||||
(is (= "/test-command first-value "
|
||||
(get-in (input/set-command-parameter
|
||||
false 0 "first-value"
|
||||
(create-cofx "/test-command"))
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (input/set-command-parameter
|
||||
false 1 "second-value"
|
||||
(create-cofx "/test-command first-value edited \"last value\""))
|
||||
[:db :chats "test" :input-text])))
|
||||
(is (= "/test-command first-value second-value \"last value\""
|
||||
(get-in (input/set-command-parameter
|
||||
false 2 "last value"
|
||||
(create-cofx "/test-command first-value second-value"))
|
||||
[:db :chats "test" :input-text]))))))
|
||||
|
||||
(deftest parse-parameters-test
|
||||
(testing "testing that parse-parameters work correctly"
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"
|
||||
:last-param "3"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 2 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2 2"
|
||||
:last-param "3"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 \"2 2\" 3")))
|
||||
(is (= {:first-param "1"
|
||||
:second-param "2"}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command 1 2")))
|
||||
(is (= {}
|
||||
(input/parse-parameters test-core/test-command-parameters "/test-command ")))))
|
@ -1,66 +1,7 @@
|
||||
(ns status-im.test.chat.events
|
||||
(:require [cljs.test :refer [deftest is testing]]
|
||||
reagent.core
|
||||
[re-frame.core :as rf]
|
||||
[day8.re-frame.test :refer [run-test-sync]]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.events :as chat-events]))
|
||||
|
||||
(def test-db
|
||||
{:current-public-key "me"
|
||||
:chats {"status" {:public? true
|
||||
:unviewed-messages #{"6" "5" "4" "3" "2" "1"}
|
||||
:message-statuses {"6" {"me" {:message-id "6"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"5" {"me" {:message-id "5"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"4" {"me" {:message-id "4"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}}}
|
||||
"opened" {:unviewed-messages #{}
|
||||
:message-statuses {"1" {"me" {:message-id "1"
|
||||
:chat-id "opened"
|
||||
:whisper-identity "me"
|
||||
:status :seen}}}}
|
||||
"1-1" {:unviewed-messages #{"6" "5" "4" "3" "2" "1"}
|
||||
:message-statuses {"6" {"me" {:message-id "6"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"5" {"me" {:message-id "5"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"4" {"me" {:message-id "4"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}}}}})
|
||||
|
||||
(deftest mark-messages-seen
|
||||
(testing "Marking messages seen correctly marks loaded messages as seen and updates absolute unviewed set"
|
||||
(let [fx (chat-events/mark-messages-seen "status" {:db test-db})
|
||||
me (:current-public-key test-db)]
|
||||
(is (= '(:seen :seen :seen)
|
||||
(map (fn [[_ v]]
|
||||
(get-in v [me :status]))
|
||||
(get-in fx [:db :chats "status" :message-statuses]))))
|
||||
(is (= 1 (count (:data-store/tx fx))))
|
||||
(is (= nil (:shh/post fx))) ;; for public chats, no confirmation is sent out
|
||||
(is (= #{"3" "2" "1"} (get-in fx [:db :chats "status" :unviewed-messages])))))
|
||||
|
||||
(testing "With empty unviewed set, no effects are produced"
|
||||
(is (= nil (chat-events/mark-messages-seen "opened" {:db test-db}))))
|
||||
|
||||
(testing "For 1-1 chat, we send seen messages confirmation to the recipient as well"
|
||||
(is (= #{"4" "5" "6"}
|
||||
(set (get-in (chat-events/mark-messages-seen "1-1" {:db test-db})
|
||||
[:shh/post 0 :message :payload :message-ids]))))))
|
||||
|
||||
(deftest show-profile-test
|
||||
(testing "Dafault behaviour: navigate to profile"
|
||||
(let [{:keys [db]} (chat-events/show-profile
|
||||
|
@ -210,3 +210,58 @@
|
||||
(testing "it returns false if it's a 1-to-1 chat"
|
||||
(let [cofx {:db {:chats {chat-id {}}}}]
|
||||
(is (not (chat/group-chat? chat-id cofx)))))))
|
||||
|
||||
(def test-db
|
||||
{:current-public-key "me"
|
||||
:chats {"status" {:public? true
|
||||
:unviewed-messages #{"6" "5" "4" "3" "2" "1"}
|
||||
:message-statuses {"6" {"me" {:message-id "6"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"5" {"me" {:message-id "5"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"4" {"me" {:message-id "4"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}}}
|
||||
"opened" {:unviewed-messages #{}
|
||||
:message-statuses {"1" {"me" {:message-id "1"
|
||||
:chat-id "opened"
|
||||
:whisper-identity "me"
|
||||
:status :seen}}}}
|
||||
"1-1" {:unviewed-messages #{"6" "5" "4" "3" "2" "1"}
|
||||
:message-statuses {"6" {"me" {:message-id "6"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"5" {"me" {:message-id "5"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}
|
||||
"4" {"me" {:message-id "4"
|
||||
:chat-id "status"
|
||||
:whisper-identity "me"
|
||||
:status :received}}}}}})
|
||||
|
||||
(deftest mark-messages-seen
|
||||
(testing "Marking messages seen correctly marks loaded messages as seen and updates absolute unviewed set"
|
||||
(let [fx (chat/mark-messages-seen "status" {:db test-db})
|
||||
me (:current-public-key test-db)]
|
||||
(is (= '(:seen :seen :seen)
|
||||
(map (fn [[_ v]]
|
||||
(get-in v [me :status]))
|
||||
(get-in fx [:db :chats "status" :message-statuses]))))
|
||||
(is (= 1 (count (:data-store/tx fx))))
|
||||
(is (= nil (:shh/post fx))) ;; for public chats, no confirmation is sent out
|
||||
(is (= #{"3" "2" "1"} (get-in fx [:db :chats "status" :unviewed-messages])))))
|
||||
|
||||
(testing "With empty unviewed set, no effects are produced"
|
||||
(is (= nil (chat/mark-messages-seen "opened" {:db test-db}))))
|
||||
|
||||
(testing "For 1-1 chat, we send seen messages confirmation to the recipient as well"
|
||||
(is (= #{"4" "5" "6"}
|
||||
(set (get-in (chat/mark-messages-seen "1-1" {:db test-db})
|
||||
[:shh/post 0 :message :payload :message-ids]))))))
|
||||
|
43
test/cljs/status_im/test/chat/models/loading.cljs
Normal file
43
test/cljs/status_im/test/chat/models/loading.cljs
Normal file
@ -0,0 +1,43 @@
|
||||
(ns status-im.test.chat.models.loading
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.chat.models.loading :as loading]))
|
||||
|
||||
(deftest group-chat-messages
|
||||
(let [cofx {:db {:chats {"chat-id" {:messages {0 {:message-id 0
|
||||
:content "a"
|
||||
:clock-value 0
|
||||
:timestamp 0}
|
||||
1 {:message-id 1
|
||||
:content "b"
|
||||
:clock-value 1
|
||||
:timestamp 1}
|
||||
2 {:message-id 2
|
||||
:content "c"
|
||||
:clock-value 2
|
||||
:timestamp 2}
|
||||
3 {:message-id 3
|
||||
:content "d"
|
||||
:clock-value 3
|
||||
:timestamp 3}}}}}}
|
||||
new-messages [{:message-id 1
|
||||
:content "b"
|
||||
:clock-value 1
|
||||
:timestamp 1
|
||||
:show? false}
|
||||
{:message-id 2
|
||||
:content "c"
|
||||
:clock-value 2
|
||||
:timestamp 2
|
||||
:show? true}
|
||||
{:message-id 3
|
||||
:content "d"
|
||||
:clock-value 3
|
||||
:timestamp 3
|
||||
:show? true}]]
|
||||
(testing "New messages are grouped/sorted correctly, hidden messages are not grouped"
|
||||
(is (= '(2 3)
|
||||
(map :message-id
|
||||
(-> (get-in (loading/group-chat-messages "chat-id" new-messages cofx)
|
||||
[:db :chats "chat-id" :message-groups])
|
||||
first
|
||||
second)))))))
|
@ -101,46 +101,6 @@
|
||||
message
|
||||
(assoc-in db [:db :view-id] :home))))))))
|
||||
|
||||
(deftest group-messages
|
||||
(let [cofx {:db {:chats {"chat-id" {:messages {0 {:message-id 0
|
||||
:content "a"
|
||||
:clock-value 0
|
||||
:timestamp 0}
|
||||
1 {:message-id 1
|
||||
:content "b"
|
||||
:clock-value 1
|
||||
:timestamp 1}
|
||||
2 {:message-id 2
|
||||
:content "c"
|
||||
:clock-value 2
|
||||
:timestamp 2}
|
||||
3 {:message-id 3
|
||||
:content "d"
|
||||
:clock-value 3
|
||||
:timestamp 3}}}}}}
|
||||
new-messages [{:message-id 1
|
||||
:content "b"
|
||||
:clock-value 1
|
||||
:timestamp 1
|
||||
:show? false}
|
||||
{:message-id 2
|
||||
:content "c"
|
||||
:clock-value 2
|
||||
:timestamp 2
|
||||
:show? true}
|
||||
{:message-id 3
|
||||
:content "d"
|
||||
:clock-value 3
|
||||
:timestamp 3
|
||||
:show? true}]]
|
||||
(testing "New messages are grouped/sorted correctly, hidden messages are not grouped"
|
||||
(is (= '(2 3)
|
||||
(map :message-id
|
||||
(-> (get-in (message/group-messages "chat-id" new-messages cofx)
|
||||
[:db :chats "chat-id" :message-groups])
|
||||
first
|
||||
second)))))))
|
||||
|
||||
(deftest delete-message
|
||||
(let [timestamp (time/now)
|
||||
cofx1 {:db {:chats {"chat-id" {:messages {0 {:message-id 0
|
||||
|
@ -1,6 +1,5 @@
|
||||
(ns status-im.test.chat.subs
|
||||
(:require [cljs.test :refer-macros [deftest is testing]]
|
||||
[status-im.constants :as const]
|
||||
[status-im.chat.subs :as s]))
|
||||
|
||||
(deftest chat-name
|
||||
@ -113,12 +112,10 @@
|
||||
(deftest active-chats-test
|
||||
(let [active-chat-1 {:is-active true :chat-id 1}
|
||||
active-chat-2 {:is-active true :chat-id 2}
|
||||
console {:is-active true :chat-id const/console-chat-id}
|
||||
chats {1 active-chat-1
|
||||
2 active-chat-2
|
||||
3 {:is-active false :chat-id 3}
|
||||
const/console-chat-id console}]
|
||||
(testing "it returns only chats with is-active, without console"
|
||||
3 {:is-active false :chat-id 3}}]
|
||||
(testing "it returns only chats with is-active"
|
||||
(is (= {1 active-chat-1
|
||||
2 active-chat-2}
|
||||
(s/active-chats chats))))))
|
||||
|
@ -1,6 +1,6 @@
|
||||
(ns status-im.test.chat.views.message
|
||||
(:require [cljs.test :refer [deftest is]]
|
||||
[status-im.chat.views.message.message :as message]))
|
||||
[status-im.ui.screens.chat.message.message :as message]))
|
||||
|
||||
(deftest parse-url
|
||||
(is (= (lazy-seq [{:text "" :url? false}
|
||||
|
@ -1,7 +1,7 @@
|
||||
(ns status-im.test.chat.views.photos
|
||||
(:require [cljs.test :refer [deftest testing is]]
|
||||
[status-im.react-native.resources :as resources]
|
||||
[status-im.chat.views.photos :as photos]))
|
||||
[status-im.ui.screens.chat.photos :as photos]))
|
||||
|
||||
(deftest photos-test
|
||||
(testing "a normal string"
|
||||
|
@ -19,11 +19,13 @@
|
||||
[status-im.test.transport.handlers]
|
||||
[status-im.test.chat.models]
|
||||
[status-im.test.chat.models.input]
|
||||
[status-im.test.chat.models.loading]
|
||||
[status-im.test.chat.models.message]
|
||||
[status-im.test.chat.subs]
|
||||
[status-im.test.chat.views.message]
|
||||
[status-im.test.chat.views.photos]
|
||||
[status-im.test.chat.commands.core]
|
||||
[status-im.test.chat.commands.input]
|
||||
[status-im.test.chat.commands.impl.transactions]
|
||||
[status-im.test.i18n]
|
||||
[status-im.test.protocol.web3.inbox]
|
||||
@ -78,11 +80,13 @@
|
||||
'status-im.test.wallet.subs
|
||||
'status-im.test.wallet.transactions.subs
|
||||
'status-im.test.wallet.transactions.views
|
||||
'status-im.test.chat.models.loading
|
||||
'status-im.test.chat.models.input
|
||||
'status-im.test.chat.models.message
|
||||
'status-im.test.chat.views.message
|
||||
'status-im.test.chat.views.photos
|
||||
'status-im.test.chat.commands.core
|
||||
'status-im.test.chat.commands.input
|
||||
'status-im.test.chat.commands.impl.transactions
|
||||
'status-im.test.i18n
|
||||
'status-im.test.transport.core
|
||||
|
Loading…
x
Reference in New Issue
Block a user