From 8913dee762945b9ed0984e498b86644d6cc65910 Mon Sep 17 00:00:00 2001 From: janherich Date: Fri, 14 Sep 2018 12:36:15 +0200 Subject: [PATCH] Chat refactoring Move chat views to ui.screens --- src/status_im/chat/commands/core.cljs | 98 +----------- src/status_im/chat/commands/input.cljs | 97 ++++++++++++ src/status_im/chat/commands/sending.cljs | 3 +- src/status_im/chat/constants.cljs | 2 - src/status_im/chat/events.cljs | 144 ++---------------- src/status_im/chat/events/input.cljs | 7 +- src/status_im/chat/models.cljs | 89 +++++++++-- .../chat.cljs => chat/models/loading.cljs} | 75 +++++++-- src/status_im/chat/models/message.cljs | 32 +--- src/status_im/chat/specs.cljs | 1 - src/status_im/chat/subs.cljs | 10 +- .../chat/views/message/datemark.cljs | 10 -- src/status_im/constants.cljs | 2 - src/status_im/init/core.cljs | 11 +- src/status_im/notifications/core.cljs | 9 +- .../ui/components/chat_icon/screen.cljs | 2 +- .../ui/screens/accounts/login/views.cljs | 2 +- src/status_im/ui/screens/accounts/views.cljs | 2 +- .../screens/add_new/new_public_chat/db.cljs | 11 +- .../views => ui/screens/chat}/actions.cljs | 2 +- .../screens/chat}/bottom_info.cljs | 6 +- .../chat}/input/animations/expandable.cljs | 6 +- .../screens/chat}/input/input.cljs | 12 +- .../screens/chat}/input/parameter_box.cljs | 9 +- .../screens/chat}/input/send_button.cljs | 7 +- .../screens/chat}/input/suggestions.cljs | 10 +- .../screens/chat}/input/utils.cljs | 2 +- .../chat}/input/validation_messages.cljs | 4 +- .../ui/screens/chat/message/datemark.cljs | 10 ++ .../screens/chat}/message/message.cljs | 8 +- .../screens/chat}/message/options.cljs | 15 +- .../views => ui/screens/chat}/photos.cljs | 4 +- .../screens}/chat/styles/animations.cljs | 2 +- .../screens}/chat/styles/input/input.cljs | 2 +- .../chat/styles/input/parameter_box.cljs | 2 +- .../chat/styles/input/send_button.cljs | 2 +- .../chat/styles/input/suggestions.cljs | 2 +- .../chat/styles/input/validation_message.cljs | 7 +- .../screens/chat/styles/main.cljs} | 2 +- .../chat/styles/message/command_pill.cljs | 2 +- .../chat/styles/message/datemark.cljs | 2 +- .../screens}/chat/styles/message/message.cljs | 4 +- .../screens}/chat/styles/message/options.cljs | 5 +- .../{ => ui/screens}/chat/styles/photos.cljs | 2 +- .../screens/chat}/toolbar_content.cljs | 29 ++-- .../screens/chat/views.cljs} | 55 +++---- src/status_im/ui/screens/contacts/events.cljs | 4 +- src/status_im/ui/screens/db.cljs | 1 - .../ui/screens/desktop/main/chat/views.cljs | 6 +- .../screens/group/chat_settings/events.cljs | 4 +- src/status_im/ui/screens/home/views.cljs | 19 +-- .../ui/screens/home/views/inner_item.cljs | 5 +- src/status_im/ui/screens/profile/db.cljs | 2 - src/status_im/ui/screens/profile/models.cljs | 8 +- src/status_im/ui/screens/views.cljs | 2 +- .../ui/screens/wallet/components/views.cljs | 2 +- .../ui/screens/wallet/request/events.cljs | 34 ++--- .../status_im/test/chat/commands/core.cljs | 59 ------- .../status_im/test/chat/commands/input.cljs | 64 ++++++++ test/cljs/status_im/test/chat/events.cljs | 59 ------- test/cljs/status_im/test/chat/models.cljs | 55 +++++++ .../status_im/test/chat/models/loading.cljs | 43 ++++++ .../status_im/test/chat/models/message.cljs | 40 ----- test/cljs/status_im/test/chat/subs.cljs | 7 +- .../status_im/test/chat/views/message.cljs | 2 +- .../status_im/test/chat/views/photos.cljs | 2 +- test/cljs/status_im/test/runner.cljs | 4 + 67 files changed, 574 insertions(+), 668 deletions(-) create mode 100644 src/status_im/chat/commands/input.cljs rename src/status_im/{models/chat.cljs => chat/models/loading.cljs} (61%) delete mode 100644 src/status_im/chat/views/message/datemark.cljs rename src/status_im/{chat/views => ui/screens/chat}/actions.cljs (96%) rename src/status_im/{chat/views => ui/screens/chat}/bottom_info.cljs (95%) rename src/status_im/{chat/views => ui/screens/chat}/input/animations/expandable.cljs (90%) rename src/status_im/{chat/views => ui/screens/chat}/input/input.cljs (93%) rename src/status_im/{chat/views => ui/screens/chat}/input/parameter_box.cljs (61%) rename src/status_im/{chat/views => ui/screens/chat}/input/send_button.cljs (89%) rename src/status_im/{chat/views => ui/screens/chat}/input/suggestions.cljs (82%) rename src/status_im/{chat/views => ui/screens/chat}/input/utils.cljs (94%) rename src/status_im/{chat/views => ui/screens/chat}/input/validation_messages.cljs (88%) create mode 100644 src/status_im/ui/screens/chat/message/datemark.cljs rename src/status_im/{chat/views => ui/screens/chat}/message/message.cljs (98%) rename src/status_im/{chat/views => ui/screens/chat}/message/options.cljs (75%) rename src/status_im/{chat/views => ui/screens/chat}/photos.cljs (92%) rename src/status_im/{ => ui/screens}/chat/styles/animations.cljs (94%) rename src/status_im/{ => ui/screens}/chat/styles/input/input.cljs (98%) rename src/status_im/{ => ui/screens}/chat/styles/input/parameter_box.cljs (80%) rename src/status_im/{ => ui/screens}/chat/styles/input/send_button.cljs (87%) rename src/status_im/{ => ui/screens}/chat/styles/input/suggestions.cljs (93%) rename src/status_im/{ => ui/screens}/chat/styles/input/validation_message.cljs (67%) rename src/status_im/{chat/styles/screen.cljs => ui/screens/chat/styles/main.cljs} (99%) rename src/status_im/{ => ui/screens}/chat/styles/message/command_pill.cljs (86%) rename src/status_im/{ => ui/screens}/chat/styles/message/datemark.cljs (87%) rename src/status_im/{ => ui/screens}/chat/styles/message/message.cljs (97%) rename src/status_im/{ => ui/screens}/chat/styles/message/options.cljs (82%) rename src/status_im/{ => ui/screens}/chat/styles/photos.cljs (92%) rename src/status_im/{chat/views => ui/screens/chat}/toolbar_content.cljs (81%) rename src/status_im/{chat/screen.cljs => ui/screens/chat/views.cljs} (80%) create mode 100644 test/cljs/status_im/test/chat/commands/input.cljs create mode 100644 test/cljs/status_im/test/chat/models/loading.cljs diff --git a/src/status_im/chat/commands/core.cljs b/src/status_im/chat/commands/core.cljs index ccb417b822..be96086247 100644 --- a/src/status_im/chat/commands/core.cljs +++ b/src/status_im/chat/commands/core.cljs @@ -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))) diff --git a/src/status_im/chat/commands/input.cljs b/src/status_im/chat/commands/input.cljs new file mode 100644 index 0000000000..2b030d7c52 --- /dev/null +++ b/src/status_im/chat/commands/input.cljs @@ -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))) diff --git a/src/status_im/chat/commands/sending.cljs b/src/status_im/chat/commands/sending.cljs index dd43847e45..1c123bed08 100644 --- a/src/status_im/chat/commands/sending.cljs +++ b/src/status_im/chat/commands/sending.cljs @@ -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 diff --git a/src/status_im/chat/constants.cljs b/src/status_im/chat/constants.cljs index 7f15175849..befa42a643 100644 --- a/src/status_im/chat/constants.cljs +++ b/src/status_im/chat/constants.cljs @@ -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) diff --git a/src/status_im/chat/events.cljs b/src/status_im/chat/events.cljs index 5c73f9df01..b2dcd66cdf 100644 --- a/src/status_im/chat/events.cljs +++ b/src/status_im/chat/events.cljs @@ -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 diff --git a/src/status_im/chat/events/input.cljs b/src/status_im/chat/events/input.cljs index 1f93f0a305..a91e2aa6e2 100644 --- a/src/status_im/chat/events/input.cljs +++ b/src/status_im/chat/events/input.cljs @@ -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])))] diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index 67238f8560..c369da9ce5 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -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)))) diff --git a/src/status_im/models/chat.cljs b/src/status_im/chat/models/loading.cljs similarity index 61% rename from src/status_im/models/chat.cljs rename to src/status_im/chat/models/loading.cljs index dfe4af61c2..ad1698c95c 100644 --- a/src/status_im/models/chat.cljs +++ b/src/status_im/chat/models/loading.cljs @@ -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))))) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index ebb694fac9..4a92be982a 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -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] diff --git a/src/status_im/chat/specs.cljs b/src/status_im/chat/specs.cljs index f3246d9bdd..68b981a8cd 100644 --- a/src/status_im/chat/specs.cljs +++ b/src/status_im/chat/specs.cljs @@ -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 diff --git a/src/status_im/chat/subs.cljs b/src/status_im/chat/subs.cljs index 4b29b4c6dc..04e827bc65 100644 --- a/src/status_im/chat/subs.cljs +++ b/src/status_im/chat/subs.cljs @@ -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 diff --git a/src/status_im/chat/views/message/datemark.cljs b/src/status_im/chat/views/message/datemark.cljs deleted file mode 100644 index 352832286d..0000000000 --- a/src/status_im/chat/views/message/datemark.cljs +++ /dev/null @@ -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)]]]) diff --git a/src/status_im/constants.cljs b/src/status_im/constants.cljs index 83613ed2a6..39e6891f39 100644 --- a/src/status_im/constants.cljs +++ b/src/status_im/constants.cljs @@ -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) diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs index b957da418d..7bd874993a 100644 --- a/src/status_im/init/core.cljs +++ b/src/status_im/init/core.cljs @@ -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) diff --git a/src/status_im/notifications/core.cljs b/src/status_im/notifications/core.cljs index 08f4e13625..da58dcb2b2 100644 --- a/src/status_im/notifications/core.cljs +++ b/src/status_im/notifications/core.cljs @@ -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] diff --git a/src/status_im/ui/components/chat_icon/screen.cljs b/src/status_im/ui/components/chat_icon/screen.cljs index b81eb212f4..e7bfdce6cc 100644 --- a/src/status_im/ui/components/chat_icon/screen.cljs +++ b/src/status_im/ui/components/chat_icon/screen.cljs @@ -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] diff --git a/src/status_im/ui/screens/accounts/login/views.cljs b/src/status_im/ui/screens/accounts/login/views.cljs index ef74027943..eed50c46af 100644 --- a/src/status_im/ui/screens/accounts/login/views.cljs +++ b/src/status_im/ui/screens/accounts/login/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/accounts/views.cljs b/src/status_im/ui/screens/accounts/views.cljs index 139055fb98..1be09d04a6 100644 --- a/src/status_im/ui/screens/accounts/views.cljs +++ b/src/status_im/ui/screens/accounts/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/add_new/new_public_chat/db.cljs b/src/status_im/ui/screens/add_new/new_public_chat/db.cljs index 78e8907eb1..f6e761f2a8 100644 --- a/src/status_im/ui/screens/add_new/new_public_chat/db.cljs +++ b/src/status_im/ui/screens/add_new/new_public_chat/db.cljs @@ -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\-]+"))) diff --git a/src/status_im/chat/views/actions.cljs b/src/status_im/ui/screens/chat/actions.cljs similarity index 96% rename from src/status_im/chat/views/actions.cljs rename to src/status_im/ui/screens/chat/actions.cljs index 446cda8285..bb974a5700 100644 --- a/src/status_im/chat/views/actions.cljs +++ b/src/status_im/ui/screens/chat/actions.cljs @@ -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])) diff --git a/src/status_im/chat/views/bottom_info.cljs b/src/status_im/ui/screens/chat/bottom_info.cljs similarity index 95% rename from src/status_im/chat/views/bottom_info.cljs rename to src/status_im/ui/screens/chat/bottom_info.cljs index fb4880a965..20054cb553 100644 --- a/src/status_im/chat/views/bottom_info.cljs +++ b/src/status_im/ui/screens/chat/bottom_info.cljs @@ -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])) diff --git a/src/status_im/chat/views/input/animations/expandable.cljs b/src/status_im/ui/screens/chat/input/animations/expandable.cljs similarity index 90% rename from src/status_im/chat/views/input/animations/expandable.cljs rename to src/status_im/ui/screens/chat/input/animations/expandable.cljs index b1def3dd4b..c75de891b4 100644 --- a/src/status_im/chat/views/input/animations/expandable.cljs +++ b/src/status_im/ui/screens/chat/input/animations/expandable.cljs @@ -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) diff --git a/src/status_im/chat/views/input/input.cljs b/src/status_im/ui/screens/chat/input/input.cljs similarity index 93% rename from src/status_im/chat/views/input/input.cljs rename to src/status_im/ui/screens/chat/input/input.cljs index 21d0738420..3a5d22e5b3 100644 --- a/src/status_im/chat/views/input/input.cljs +++ b/src/status_im/ui/screens/chat/input/input.cljs @@ -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] diff --git a/src/status_im/chat/views/input/parameter_box.cljs b/src/status_im/ui/screens/chat/input/parameter_box.cljs similarity index 61% rename from src/status_im/chat/views/input/parameter_box.cljs rename to src/status_im/ui/screens/chat/input/parameter_box.cljs index 0afffb7099..cc70cf6e48 100644 --- a/src/status_im/chat/views/input/parameter_box.cljs +++ b/src/status_im/ui/screens/chat/input/parameter_box.cljs @@ -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]] diff --git a/src/status_im/chat/views/input/send_button.cljs b/src/status_im/ui/screens/chat/input/send_button.cljs similarity index 89% rename from src/status_im/chat/views/input/send_button.cljs rename to src/status_im/ui/screens/chat/input/send_button.cljs index 8aa501b8bb..4b3c428344 100644 --- a/src/status_im/chat/views/input/send_button.cljs +++ b/src/status_im/ui/screens/chat/input/send_button.cljs @@ -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 [_] diff --git a/src/status_im/chat/views/input/suggestions.cljs b/src/status_im/ui/screens/chat/input/suggestions.cljs similarity index 82% rename from src/status_im/chat/views/input/suggestions.cljs rename to src/status_im/ui/screens/chat/input/suggestions.cljs index f6552cca2c..702aef8c99 100644 --- a/src/status_im/chat/views/input/suggestions.cljs +++ b/src/status_im/ui/screens/chat/input/suggestions.cljs @@ -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} diff --git a/src/status_im/chat/views/input/utils.cljs b/src/status_im/ui/screens/chat/input/utils.cljs similarity index 94% rename from src/status_im/chat/views/input/utils.cljs rename to src/status_im/ui/screens/chat/input/utils.cljs index e1d5e154b7..6fb4333040 100644 --- a/src/status_im/chat/views/input/utils.cljs +++ b/src/status_im/ui/screens/chat/input/utils.cljs @@ -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])) diff --git a/src/status_im/chat/views/input/validation_messages.cljs b/src/status_im/ui/screens/chat/input/validation_messages.cljs similarity index 88% rename from src/status_im/chat/views/input/validation_messages.cljs rename to src/status_im/ui/screens/chat/input/validation_messages.cljs index c04b71f605..bb899735c8 100644 --- a/src/status_im/chat/views/input/validation_messages.cljs +++ b/src/status_im/ui/screens/chat/input/validation_messages.cljs @@ -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]}] diff --git a/src/status_im/ui/screens/chat/message/datemark.cljs b/src/status_im/ui/screens/chat/message/datemark.cljs new file mode 100644 index 0000000000..b906c6de7d --- /dev/null +++ b/src/status_im/ui/screens/chat/message/datemark.cljs @@ -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)]]]) diff --git a/src/status_im/chat/views/message/message.cljs b/src/status_im/ui/screens/chat/message/message.cljs similarity index 98% rename from src/status_im/chat/views/message/message.cljs rename to src/status_im/ui/screens/chat/message/message.cljs index 9f97879299..ddde2c11bf 100644 --- a/src/status_im/chat/views/message/message.cljs +++ b/src/status_im/ui/screens/chat/message/message.cljs @@ -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] diff --git a/src/status_im/chat/views/message/options.cljs b/src/status_im/ui/screens/chat/message/options.cljs similarity index 75% rename from src/status_im/chat/views/message/options.cljs rename to src/status_im/ui/screens/chat/message/options.cljs index eb6fbb9c10..98bd1eea09 100644 --- a/src/status_im/chat/views/message/options.cljs +++ b/src/status_im/ui/screens/chat/message/options.cljs @@ -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]}] diff --git a/src/status_im/chat/views/photos.cljs b/src/status_im/ui/screens/chat/photos.cljs similarity index 92% rename from src/status_im/chat/views/photos.cljs rename to src/status_im/ui/screens/chat/photos.cljs index 6732387acc..76d09bd98c 100644 --- a/src/status_im/chat/views/photos.cljs +++ b/src/status_im/ui/screens/chat/photos.cljs @@ -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])) diff --git a/src/status_im/chat/styles/animations.cljs b/src/status_im/ui/screens/chat/styles/animations.cljs similarity index 94% rename from src/status_im/chat/styles/animations.cljs rename to src/status_im/ui/screens/chat/styles/animations.cljs index f62bedca5b..4226799126 100644 --- a/src/status_im/chat/styles/animations.cljs +++ b/src/status_im/ui/screens/chat/styles/animations.cljs @@ -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)") diff --git a/src/status_im/chat/styles/input/input.cljs b/src/status_im/ui/screens/chat/styles/input/input.cljs similarity index 98% rename from src/status_im/chat/styles/input/input.cljs rename to src/status_im/ui/screens/chat/styles/input/input.cljs index a5c82a966c..b367524735 100644 --- a/src/status_im/chat/styles/input/input.cljs +++ b/src/status_im/ui/screens/chat/styles/input/input.cljs @@ -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])) diff --git a/src/status_im/chat/styles/input/parameter_box.cljs b/src/status_im/ui/screens/chat/styles/input/parameter_box.cljs similarity index 80% rename from src/status_im/chat/styles/input/parameter_box.cljs rename to src/status_im/ui/screens/chat/styles/input/parameter_box.cljs index 191564e8c9..c27f9d5be2 100644 --- a/src/status_im/chat/styles/input/parameter_box.cljs +++ b/src/status_im/ui/screens/chat/styles/input/parameter_box.cljs @@ -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])) diff --git a/src/status_im/chat/styles/input/send_button.cljs b/src/status_im/ui/screens/chat/styles/input/send_button.cljs similarity index 87% rename from src/status_im/chat/styles/input/send_button.cljs rename to src/status_im/ui/screens/chat/styles/input/send_button.cljs index b0b505a900..03d55eb038 100644 --- a/src/status_im/chat/styles/input/send_button.cljs +++ b/src/status_im/ui/screens/chat/styles/input/send_button.cljs @@ -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] diff --git a/src/status_im/chat/styles/input/suggestions.cljs b/src/status_im/ui/screens/chat/styles/input/suggestions.cljs similarity index 93% rename from src/status_im/chat/styles/input/suggestions.cljs rename to src/status_im/ui/screens/chat/styles/input/suggestions.cljs index 6cab42b3f9..c510a3b663 100644 --- a/src/status_im/chat/styles/input/suggestions.cljs +++ b/src/status_im/ui/screens/chat/styles/input/suggestions.cljs @@ -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] diff --git a/src/status_im/chat/styles/input/validation_message.cljs b/src/status_im/ui/screens/chat/styles/input/validation_message.cljs similarity index 67% rename from src/status_im/chat/styles/input/validation_message.cljs rename to src/status_im/ui/screens/chat/styles/input/validation_message.cljs index 9677559f51..e6fbcc0602 100644 --- a/src/status_im/chat/styles/input/validation_message.cljs +++ b/src/status_im/ui/screens/chat/styles/input/validation_message.cljs @@ -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}) \ No newline at end of file + :opacity 0.9}) diff --git a/src/status_im/chat/styles/screen.cljs b/src/status_im/ui/screens/chat/styles/main.cljs similarity index 99% rename from src/status_im/chat/styles/screen.cljs rename to src/status_im/ui/screens/chat/styles/main.cljs index 4af66b6aba..e95495c11b 100644 --- a/src/status_im/chat/styles/screen.cljs +++ b/src/status_im/ui/screens/chat/styles/main.cljs @@ -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])) diff --git a/src/status_im/chat/styles/message/command_pill.cljs b/src/status_im/ui/screens/chat/styles/message/command_pill.cljs similarity index 86% rename from src/status_im/chat/styles/message/command_pill.cljs rename to src/status_im/ui/screens/chat/styles/message/command_pill.cljs index 7c9a6cc130..3bfb27093a 100644 --- a/src/status_im/chat/styles/message/command_pill.cljs +++ b/src/status_im/ui/screens/chat/styles/message/command_pill.cljs @@ -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]])) diff --git a/src/status_im/chat/styles/message/datemark.cljs b/src/status_im/ui/screens/chat/styles/message/datemark.cljs similarity index 87% rename from src/status_im/chat/styles/message/datemark.cljs rename to src/status_im/ui/screens/chat/styles/message/datemark.cljs index d58d24838a..f6e18b4a91 100644 --- a/src/status_im/chat/styles/message/datemark.cljs +++ b/src/status_im/ui/screens/chat/styles/message/datemark.cljs @@ -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])) diff --git a/src/status_im/chat/styles/message/message.cljs b/src/status_im/ui/screens/chat/styles/message/message.cljs similarity index 97% rename from src/status_im/chat/styles/message/message.cljs rename to src/status_im/ui/screens/chat/styles/message/message.cljs index 22cc211b5b..b317ef3335 100644 --- a/src/status_im/chat/styles/message/message.cljs +++ b/src/status_im/ui/screens/chat/styles/message/message.cljs @@ -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])) diff --git a/src/status_im/chat/styles/message/options.cljs b/src/status_im/ui/screens/chat/styles/message/options.cljs similarity index 82% rename from src/status_im/chat/styles/message/options.cljs rename to src/status_im/ui/screens/chat/styles/message/options.cljs index ee9ba78a91..f51c8602b0 100644 --- a/src/status_im/chat/styles/message/options.cljs +++ b/src/status_im/ui/screens/chat/styles/message/options.cljs @@ -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 diff --git a/src/status_im/chat/styles/photos.cljs b/src/status_im/ui/screens/chat/styles/photos.cljs similarity index 92% rename from src/status_im/chat/styles/photos.cljs rename to src/status_im/ui/screens/chat/styles/photos.cljs index 1c82671327..9b86c6f64a 100644 --- a/src/status_im/chat/styles/photos.cljs +++ b/src/status_im/ui/screens/chat/styles/photos.cljs @@ -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) diff --git a/src/status_im/chat/views/toolbar_content.cljs b/src/status_im/ui/screens/chat/toolbar_content.cljs similarity index 81% rename from src/status_im/chat/views/toolbar_content.cljs rename to src/status_im/ui/screens/chat/toolbar_content.cljs index 7d561ea3f2..912ad8e592 100644 --- a/src/status_im/chat/views/toolbar_content.cljs +++ b/src/status_im/ui/screens/chat/toolbar_content.cljs @@ -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) diff --git a/src/status_im/chat/screen.cljs b/src/status_im/ui/screens/chat/views.cljs similarity index 80% rename from src/status_im/chat/screen.cljs rename to src/status_im/ui/screens/chat/views.cljs index 9c05345315..4246236b64 100644 --- a/src/status_im/chat/screen.cljs +++ b/src/status_im/ui/screens/chat/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/contacts/events.cljs b/src/status_im/ui/screens/contacts/events.cljs index da9a324079..bd6d4e5292 100644 --- a/src/status_im/ui/screens/contacts/events.cljs +++ b/src/status_im/ui/screens/contacts/events.cljs @@ -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 diff --git a/src/status_im/ui/screens/db.cljs b/src/status_im/ui/screens/db.cljs index 820d985ab6..cbbdfee0fc 100644 --- a/src/status_im/ui/screens/db.cljs +++ b/src/status_im/ui/screens/db.cljs @@ -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 diff --git a/src/status_im/ui/screens/desktop/main/chat/views.cljs b/src/status_im/ui/screens/desktop/main/chat/views.cljs index 1e0e1fe352..d84c3e708a 100644 --- a/src/status_im/ui/screens/desktop/main/chat/views.cljs +++ b/src/status_im/ui/screens/desktop/main/chat/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/group/chat_settings/events.cljs b/src/status_im/ui/screens/group/chat_settings/events.cljs index 221669999c..324f268d9e 100644 --- a/src/status_im/ui/screens/group/chat_settings/events.cljs +++ b/src/status_im/ui/screens/group/chat_settings/events.cljs @@ -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 diff --git a/src/status_im/ui/screens/home/views.cljs b/src/status_im/ui/screens/home/views.cljs index 08cfa23f85..d1cea2ff1a 100644 --- a/src/status_im/ui/screens/home/views.cljs +++ b/src/status_im/ui/screens/home/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/home/views/inner_item.cljs b/src/status_im/ui/screens/home/views/inner_item.cljs index 78476ce996..e641da8b24 100644 --- a/src/status_im/ui/screens/home/views/inner_item.cljs +++ b/src/status_im/ui/screens/home/views/inner_item.cljs @@ -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] diff --git a/src/status_im/ui/screens/profile/db.cljs b/src/status_im/ui/screens/profile/db.cljs index 57c5e86596..8c28f7da0f 100644 --- a/src/status_im/ui/screens/profile/db.cljs +++ b/src/status_im/ui/screens/profile/db.cljs @@ -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] diff --git a/src/status_im/ui/screens/profile/models.cljs b/src/status_im/ui/screens/profile/models.cljs index 486ea176ab..4906621045 100644 --- a/src/status_im/ui/screens/profile/models.cljs +++ b/src/status_im/ui/screens/profile/models.cljs @@ -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)) diff --git a/src/status_im/ui/screens/views.cljs b/src/status_im/ui/screens/views.cljs index 84f23b5ace..494c3885cd 100644 --- a/src/status_im/ui/screens/views.cljs +++ b/src/status_im/ui/screens/views.cljs @@ -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]] diff --git a/src/status_im/ui/screens/wallet/components/views.cljs b/src/status_im/ui/screens/wallet/components/views.cljs index 124b9d8c13..7422fd8342 100644 --- a/src/status_im/ui/screens/wallet/components/views.cljs +++ b/src/status_im/ui/screens/wallet/components/views.cljs @@ -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] diff --git a/src/status_im/ui/screens/wallet/request/events.cljs b/src/status_im/ui/screens/wallet/request/events.cljs index 49e2db7c42..f9749a7467 100644 --- a/src/status_im/ui/screens/wallet/request/events.cljs +++ b/src/status_im/ui/screens/wallet/request/events.cljs @@ -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 diff --git a/test/cljs/status_im/test/chat/commands/core.cljs b/test/cljs/status_im/test/chat/commands/core.cljs index 53276fe0e9..eeadccc20c 100644 --- a/test/cljs/status_im/test/chat/commands/core.cljs +++ b/test/cljs/status_im/test/chat/commands/core.cljs @@ -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 "))))) diff --git a/test/cljs/status_im/test/chat/commands/input.cljs b/test/cljs/status_im/test/chat/commands/input.cljs new file mode 100644 index 0000000000..02085f445c --- /dev/null +++ b/test/cljs/status_im/test/chat/commands/input.cljs @@ -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 "))))) diff --git a/test/cljs/status_im/test/chat/events.cljs b/test/cljs/status_im/test/chat/events.cljs index 61522d2fcf..79dc09273b 100644 --- a/test/cljs/status_im/test/chat/events.cljs +++ b/test/cljs/status_im/test/chat/events.cljs @@ -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 diff --git a/test/cljs/status_im/test/chat/models.cljs b/test/cljs/status_im/test/chat/models.cljs index c6f2451dd3..b60dd7463a 100644 --- a/test/cljs/status_im/test/chat/models.cljs +++ b/test/cljs/status_im/test/chat/models.cljs @@ -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])))))) diff --git a/test/cljs/status_im/test/chat/models/loading.cljs b/test/cljs/status_im/test/chat/models/loading.cljs new file mode 100644 index 0000000000..b5a5526b6a --- /dev/null +++ b/test/cljs/status_im/test/chat/models/loading.cljs @@ -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))))))) diff --git a/test/cljs/status_im/test/chat/models/message.cljs b/test/cljs/status_im/test/chat/models/message.cljs index 56040232ad..2eb05c5c75 100644 --- a/test/cljs/status_im/test/chat/models/message.cljs +++ b/test/cljs/status_im/test/chat/models/message.cljs @@ -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 diff --git a/test/cljs/status_im/test/chat/subs.cljs b/test/cljs/status_im/test/chat/subs.cljs index 5a54ea3da9..8b2e1034ec 100644 --- a/test/cljs/status_im/test/chat/subs.cljs +++ b/test/cljs/status_im/test/chat/subs.cljs @@ -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)))))) diff --git a/test/cljs/status_im/test/chat/views/message.cljs b/test/cljs/status_im/test/chat/views/message.cljs index c7acade8e2..ae1c97ba5a 100644 --- a/test/cljs/status_im/test/chat/views/message.cljs +++ b/test/cljs/status_im/test/chat/views/message.cljs @@ -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} diff --git a/test/cljs/status_im/test/chat/views/photos.cljs b/test/cljs/status_im/test/chat/views/photos.cljs index 33739e0424..2724310502 100644 --- a/test/cljs/status_im/test/chat/views/photos.cljs +++ b/test/cljs/status_im/test/chat/views/photos.cljs @@ -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" diff --git a/test/cljs/status_im/test/runner.cljs b/test/cljs/status_im/test/runner.cljs index 4c5c116eb3..1f24e9d66a 100644 --- a/test/cljs/status_im/test/runner.cljs +++ b/test/cljs/status_im/test/runner.cljs @@ -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