More efficient subscriptions

This commit is contained in:
janherich 2017-11-28 13:33:58 +01:00 committed by Jan Herich
parent c38f1ce8a4
commit 25d3940d49
21 changed files with 315 additions and 282 deletions

View File

@ -22,7 +22,7 @@
;; in handlers
(let [stack (subscribe [:get :navigation-stack])
creating? (subscribe [:get :accounts/creating-account?])
result-box (subscribe [:chat-ui-props :result-box])
result-box (subscribe [:get-current-chat-ui-prop :result-box])
webview (subscribe [:get :webview-bridge])]
(cond
@creating? true

View File

@ -2,14 +2,11 @@
(:require [re-frame.core :as re-frame]
[status-im.chat.models.input :as input-model]))
(re-frame/reg-sub
:bot-db
(fn [db]
(:bot-db db)))
(re-frame/reg-sub :get-bot-db :bot-db)
(re-frame/reg-sub
:current-bot-db
:<- [:bot-db]
:<- [:get-bot-db]
:<- [:selected-chat-command]
(fn [[bot-db command]]
(let [command-owner (get-in command [:command :owner-id])]

View File

@ -6,7 +6,6 @@
[status-im.chat.utils :as chat-utils]
[status-im.chat.models :as model]
[status-im.chat.models.input :as input-model]
[status-im.chat.models.commands :as commands-model]
[status-im.chat.events.commands :as commands-events]
[status-im.chat.events.animation :as animation-events]
[status-im.bots.events :as bots-events]
@ -64,6 +63,9 @@
(and dapp? (str/blank? chat-text))
(assoc-in [:chats current-chat-id :parameter-boxes :message] nil))))
;; TODO janherich: this is super fragile and won't work at all for group chats with bots.
;; The proper way how to do it is to check each chat participant and call `:on-message-input-change`
;; jail function in each participant's jail
(defn call-on-message-input-change
"Calls bot's `on-message-input-change` function"
[{:keys [current-chat-id current-account-id chats local-storage] :as db}]
@ -99,7 +101,7 @@
[{:keys [current-chat-id] :as db} index arg move-to-next?]
(let [command (-> (get-in db [:chats current-chat-id :input-text])
(input-model/split-command-args))
seq-params? (-> (input-model/selected-chat-command db current-chat-id)
seq-params? (-> (input-model/selected-chat-command db)
(get-in [:command :sequential-params]))]
(if seq-params?
(set-chat-seq-arg-input-text db arg)
@ -114,7 +116,7 @@
(input-model/join-command-args command-args)
(when (and move-to-next?
(= index (dec (count command-args))))
const/spacing-char))]
const/spacing-char))]
(set-chat-input-text db input-text)))))
(defn load-chat-parameter-box
@ -160,9 +162,8 @@
(defn update-text-selection
"Updates text selection in active chat input"
[{:keys [current-chat-id] :as db} selection]
(let [input-text (get-in db [:chats current-chat-id :input-text])
command (input-model/selected-chat-command db current-chat-id input-text)
[db selection]
(let [command (input-model/selected-chat-command db)
new-db (model/set-chat-ui-props db {:selection selection})
chat-parameter-box-fx (when command
(load-chat-parameter-box new-db (:command command)))]
@ -213,13 +214,10 @@
(defn set-contact-as-command-argument
"Sets contact as command argument for active chat"
[{:keys [current-chat-id] :as db} {:keys [bot-db-key contact arg-index]}]
[db {:keys [bot-db-key contact arg-index]}]
(let [name (str/replace (:name contact) (re-pattern const/arg-wrapping-char) "")
contact (select-keys contact [:address :whisper-identity :name :photo-path :dapp?])
command-owner (-> db
(input-model/selected-chat-command current-chat-id)
:command
:owner-id)]
command-owner (get-in (input-model/selected-chat-command db) [:command :owner-id])]
(-> db
(set-command-argument arg-index name true)
(bots-events/set-in-bot-db {:bot command-owner
@ -441,8 +439,7 @@
[(re-frame/inject-cofx :random-id)]
(fn [{{:keys [current-chat-id current-public-key] :as db} :db message-id :random-id current-time :now} _]
(let [input-text (get-in db [:chats current-chat-id :input-text])
chat-command (-> db
(input-model/selected-chat-command current-chat-id input-text)
chat-command (-> (input-model/selected-chat-command db)
(as-> selected-command
(if (get-in selected-command [:command :sequential-params])
(assoc selected-command :args
@ -493,7 +490,7 @@
(fn [{{:keys [current-chat-id chats] :as db} :db} _]
(let [text (get-in chats [current-chat-id :seq-argument-input-text])
seq-arguments (get-in chats [current-chat-id :seq-arguments])
command (-> (input-model/selected-chat-command db current-chat-id)
command (-> (input-model/selected-chat-command db)
(assoc :args (into [] (conj seq-arguments text))))]
(request-command-data db {:content command
:chat-id current-chat-id
@ -520,8 +517,7 @@
(handlers/register-handler-fx
:select-prev-argument
(fn [{{:keys [chat-ui-props current-chat-id] :as db} :db} _]
(let [input-text (get-in db [:chats current-chat-id :input-text])
command (input-model/selected-chat-command db current-chat-id input-text)]
(let [command (input-model/selected-chat-command db)]
(if (get-in command [:command :sequential-params])
(-> db
(set-command-argument 0 "" false)

View File

@ -96,45 +96,44 @@
(str/join const/spacing-char))))
(defn selected-chat-command
"Returns a map containing `:command`, `:metadata` and `:args` keys.
Can also return `nil` if there is no selected command.
"Takes whole db, or current chat and available commands/responses and returns a map
containing `:command`, `:metadata` and `:args` keys. Can also return `nil` if there is no selected command.
* `:command` key contains a map with all information about command.
* `:metadata` is also a map which contains some additional information, usually not visible by user.
For instance, we can add a `:to-message-id` key to this map, and this key will allow us to identity
the request we're responding to.
* `:args` contains all arguments provided by user."
([{:keys [current-chat-id access-scope->commands-responses]
:contacts/keys [contacts]
:accounts/keys [accounts current-account-id] :as db} chat-id input-text]
(let [chat-id (or chat-id current-chat-id)
chat (get-in db [:chats chat-id])
{:keys [input-metadata seq-arguments requests]} chat
command-args (split-command-args input-text)
command-name (first command-args)]
(when (starts-as-command? (or command-name ""))
(let [account (get accounts current-account-id)
available-commands-responses (merge (commands-model/commands-responses :command
access-scope->commands-responses
account
chat
contacts)
(commands-model/requested-responses access-scope->commands-responses
account
chat
contacts
(vals requests)))]
(when-let [{{:keys [message-id]} :request :as command} (get available-commands-responses (subs command-name 1))]
{:command command
:metadata (if (and (nil? (:to-message-id input-metadata)) message-id)
(assoc input-metadata :to-message-id message-id)
input-metadata)
:args (->> (if (empty? seq-arguments)
([{:keys [input-text input-metadata seq-arguments] :as current-chat} commands responses]
(let [[command-name :as command-args] (split-command-args input-text)]
(when-let [{{:keys [message-id]} :request :as command} (and command-name
(starts-as-command? command-name)
(get (merge commands
responses)
(subs command-name 1)))]
{:command command
:metadata (if (and message-id (not (:to-message-id input-metadata)))
(assoc input-metadata :to-message-id message-id)
input-metadata)
:args (into [] (if (empty? seq-arguments)
(rest command-args)
seq-arguments)
(into []))})))))
([{:keys [current-chat-id] :as db} chat-id]
(selected-chat-command db chat-id (get-in db [:chats chat-id :input-text]))))
seq-arguments))})))
([{:keys [chats current-chat-id access-scope->commands-responses]
:contacts/keys [contacts]
:accounts/keys [accounts current-account-id] :as db}]
(let [chat (get chats current-chat-id)
account (get accounts current-account-id)]
(selected-chat-command chat
(commands-model/commands-responses :command
access-scope->commands-responses
account
chat
contacts)
(commands-model/requested-responses access-scope->commands-responses
account
chat
contacts
(vals (:requests chat)))))))
(def *no-argument-error* -1)
@ -169,7 +168,7 @@
(let [input-text (get-in db [:chats current-chat-id :input-text])
seq-arguments (get-in db [:chats current-chat-id :seq-arguments])
selection (get-in db [:chat-ui-props current-chat-id :selection])
chat-command (selected-chat-command db current-chat-id)]
chat-command (selected-chat-command db)]
(current-chat-argument-position chat-command input-text selection seq-arguments)))
(defn command-completion
@ -178,30 +177,25 @@
* `:less-than-needed` means that the command is not complete and additional arguments should be provided;
* `:more-than-needed` means that the command is more than complete and contains redundant arguments;
* `:no-command` means that there is no selected command."
([{:keys [current-chat-id] :as db} chat-id]
(let [chat-id (or chat-id current-chat-id)
input-text (get-in db [:chats chat-id :input-text])
chat-command (selected-chat-command db chat-id)]
(command-completion chat-command)))
([{:keys [args] :as chat-command}]
(let [args (remove str/blank? args)
params (get-in chat-command [:command :params])
required-params (remove :optional params)]
(if chat-command
(cond
(or (= (count args) (count params))
(= (count args) (count required-params)))
:complete
[{:keys [args] :as chat-command}]
(let [args (remove str/blank? args)
params (get-in chat-command [:command :params])
required-params (remove :optional params)]
(if chat-command
(cond
(or (= (count args) (count params))
(= (count args) (count required-params)))
:complete
(< (count args) (count required-params))
:less-than-needed
(< (count args) (count required-params))
:less-than-needed
(> (count args) (count params))
:more-than-needed
(> (count args) (count params))
:more-than-needed
:default
:no-command)
:no-command))))
:default
:no-command)
:no-command)))
(defn args->params
"Uses `args` (which is a list or vector like ['Jarrad' '1.0']) and command's `params`
@ -228,8 +222,7 @@
(defn modified-db-after-change
"Returns the new db object that should be used after any input change."
[{:keys [current-chat-id] :as db}]
(let [input-text (get-in db [:chats current-chat-id :input-text])
command (selected-chat-command db current-chat-id input-text)
(let [command (selected-chat-command db)
prev-command (get-in db [:chat-ui-props current-chat-id :prev-command])]
(if command
(cond-> db

View File

@ -86,7 +86,7 @@
(list-item [chat-message message])))
(defn toolbar-action []
(let [show-actions (subscribe [:chat-ui-props :show-actions?])]
(let [show-actions (subscribe [:get-current-chat-ui-prop :show-actions?])]
(fn []
(let [show-actions @show-actions]
[touchable-highlight
@ -108,7 +108,7 @@
(label :t/add-to-contacts)]]]))
(defview chat-toolbar []
[show-actions? [:chat-ui-props :show-actions?]
[show-actions? [:get-current-chat-ui-prop :show-actions?]
accounts [:get-accounts]
creating? [:get :accounts/creating-account?]]
[view
@ -175,9 +175,9 @@
(defview chat []
[group-chat [:chat :group-chat]
show-actions? [:chat-ui-props :show-actions?]
show-bottom-info? [:chat-ui-props :show-bottom-info?]
show-emoji? [:chat-ui-props :show-emoji?]
show-actions? [:get-current-chat-ui-prop :show-actions?]
show-bottom-info? [:get-current-chat-ui-prop :show-bottom-info?]
show-emoji? [:get-current-chat-ui-prop :show-emoji?]
layout-height [:get :layout-height]
input-text [:chat :input-text]]
{:component-did-mount #(dispatch [:check-and-open-dapp!])

View File

@ -14,17 +14,36 @@
[taoensso.timbre :as log]
[clojure.string :as str]))
(reg-sub
:chat-ui-props
(fn [db [_ ui-element chat-id]]
(let [current-chat-id (subscribe [:get-current-chat-id])
data (get-in db [:chat-ui-props (or chat-id @current-chat-id) ui-element])]
(cond-> data
(:markup data)
(update :markup commands-utils/generate-hiccup)
(reg-sub :chats :chats)
(and (= ui-element :validation-messages) data)
commands-utils/generate-hiccup))))
(reg-sub :get-current-chat-id :current-chat-id)
(reg-sub :chat-ui-props :chat-ui-props)
(reg-sub
:get-current-chat-ui-props
:<- [:chat-ui-props]
:<- [:get-current-chat-id]
(fn [[chat-ui-props id]]
(get chat-ui-props id)))
(reg-sub
:get-current-chat-ui-prop
:<- [:get-current-chat-ui-props]
(fn [ui-props [_ prop]]
(get ui-props prop)))
(reg-sub
:validation-messages
:<- [:get-current-chat-ui-props]
(fn [ui-props]
(some-> ui-props :validation-messages commands-utils/generate-hiccup)))
(reg-sub
:result-box-markup
:<- [:get-current-chat-ui-props]
(fn [ui-props]
(some-> ui-props :result-box :markup commands-utils/generate-hiccup)))
(reg-sub
:chat-input-margin
@ -32,11 +51,6 @@
(fn [kb-height]
(if ios? kb-height 0)))
(reg-sub
:chats
(fn [db]
(:chats db)))
(reg-sub
:get-current-chat
:<- [:chats]
@ -53,16 +67,16 @@
(reg-sub
:get-commands-for-chat
:<- [:get-commands-responses-by-access-scope]
:<- [:get-commands-responses-by-access-scope]
:<- [:get-current-account]
:<- [:get-current-chat]
:<- [:get-contacts]
(fn [[commands-responses account chat contacts]]
(fn [[commands-responses account chat contacts]]
(commands-model/commands-responses :command commands-responses account chat contacts)))
(reg-sub
:get-responses-for-chat
:<- [:get-commands-responses-by-access-scope]
:<- [:get-commands-responses-by-access-scope]
:<- [:get-current-account]
:<- [:get-current-chat]
:<- [:get-contacts]
@ -90,61 +104,54 @@
available-commands-responses)
(reg-sub
:get-available-commands-responses
:<- [:get-commands-for-chat]
:<- [:get-responses-for-chat]
(fn [[commands responses]]
(map->sorted-seq (merge commands responses))))
(reg-sub
:get-current-chat-id
(fn [db]
(:current-chat-id db)))
(reg-sub
:get-chat-by-id
(fn [_ [_ chat-id]]
(chats/get-by-id chat-id)))
:get-available-commands-responses
:<- [:get-commands-for-chat]
:<- [:get-responses-for-chat]
(fn [[commands responses]]
(map->sorted-seq (merge commands responses))))
(reg-sub
:selected-chat-command
(fn [db [_ chat-id]]
(let [current-chat-id (subscribe [:get :current-chat-id])
input-text (subscribe [:chat :input-text])]
(input-model/selected-chat-command db (or chat-id @current-chat-id) @input-text))))
:<- [:get-current-chat]
:<- [:get-commands-for-chat]
:<- [:get-responses-for-chat]
(fn [[chat commands responses]]
(input-model/selected-chat-command chat commands responses)))
(reg-sub
:current-chat-argument-position
:<- [:selected-chat-command]
:<- [:chat :input-text]
:<- [:chat :seq-arguments]
:<- [:chat-ui-props :selection]
(fn [[command input-text seq-arguments selection]]
:<- [:get-current-chat-ui-prop :selection]
(fn [[command input-text seq-arguments selection]]
(input-model/current-chat-argument-position command input-text selection seq-arguments)))
(reg-sub
:chat-parameter-box
(fn [db]
(let [chat-id (subscribe [:get-current-chat-id])
command (subscribe [:selected-chat-command])
index (subscribe [:current-chat-argument-position])]
(cond
(and @command (not= @index input-model/*no-argument-error*))
(let [command-name (get-in @command [:command :name])]
(get-in db [:chats @chat-id :parameter-boxes command-name @index]))
:<- [:get-current-chat]
:<- [:selected-chat-command]
:<- [:current-chat-argument-position]
(fn [[current-chat selected-chat-command argument-position]]
(cond
(and selected-chat-command
(not= argument-position input-model/*no-argument-error*))
(get-in current-chat [:parameter-boxes
(get-in selected-chat-command [:command :name])
argument-position])
(not @command)
(get-in db [:chats @chat-id :parameter-boxes :message])
(not selected-chat-command)
(get-in current-chat [:parameter-boxes :message])
:default
nil))))
:default
nil)))
(reg-sub
:show-parameter-box?
:show-parameter-box?
:<- [:chat-parameter-box]
:<- [:show-suggestions?]
:<- [:chat :input-text]
:<- [:chat-ui-props :validation-messages]
:<- [:validation-messages]
(fn [[chat-parameter-box show-suggestions? input-text validation-messages]]
(and (get chat-parameter-box :markup)
(not validation-messages)
@ -152,109 +159,116 @@
(reg-sub
:command-completion
(fn [db [_ chat-id]]
(input-model/command-completion db chat-id)))
:<- [:selected-chat-command]
input-model/command-completion)
(reg-sub
:show-suggestions?
(fn [db [_ chat-id]]
(let [chat-id (or chat-id (db :current-chat-id))
show-suggestions? (subscribe [:chat-ui-props :show-suggestions? chat-id])
input-text (subscribe [:chat :input-text chat-id])
selected-command (subscribe [:selected-chat-command chat-id])
commands-responses (subscribe [:get-available-commands-responses])]
(and (or @show-suggestions? (input-model/starts-as-command? (str/trim (or @input-text ""))))
(not (:command @selected-command))
(seq @commands-responses)))))
:<- [:get-current-chat-ui-prop :show-suggestions?]
:<- [:chat :input-text]
:<- [:selected-chat-command]
:<- [:get-available-commands-responses]
(fn [[show-suggestions? input-text selected-command commands-responses]]
(and (or show-suggestions? (input-model/starts-as-command? (str/trim (or input-text ""))))
(not (:command selected-command))
(seq commands-responses))))
(reg-sub :get-chat
(fn [db [_ chat-id]]
(get-in db [:chats chat-id])))
(reg-sub :get-response
(fn [db [_ n]]
(let [chat-id (subscribe [:get-current-chat-id])]
(get-in db [:contacts/contacts @chat-id :responses n]))))
(reg-sub :is-request-answered?
(reg-sub
:is-request-answered?
:<- [:chat :requests]
(fn [requests [_ message-id]]
(not= "open" (get-in requests [message-id :status]))))
(reg-sub :unviewed-messages-count
(reg-sub
:unviewed-messages-count
(fn [db [_ chat-id]]
(get-in db [:unviewed-messages chat-id :count])))
(reg-sub :web-view-extra-js
(fn [db]
(let [chat-id (subscribe [:get-current-chat-id])]
(get-in db [:web-view-extra-js @chat-id]))))
(reg-sub
:web-view-extra-js
:<- [:get-current-chat]
(fn [current-chat]
(:web-view-extra-js current-chat)))
(reg-sub :all-messages-loaded?
(fn [db]
(let [chat-id (subscribe [:get-current-chat-id])]
(get-in db [:chats @chat-id :all-loaded?]))))
(reg-sub
:all-messages-loaded?
:<- [:get-current-chat]
(fn [current-chat]
(:all-loaded? current-chat)))
(reg-sub :photo-path
(reg-sub
:photo-path
:<- [:get-contacts]
(fn [contacts [_ id]]
(:photo-path (contacts id))))
(reg-sub :get-last-message
(fn [db [_ chat-id]]
(let [{:keys [last-message messages]} (get-in db [:chats chat-id])]
;; TODO janherich: this is just bad and horribly ineffecient (always sorting to get last msg +
;; stale `:last-message` in app-db) refactor messages data-model to properly index them ASAP
(reg-sub
:get-last-message
:<- [:chats]
(fn [chats [_ chat-id]]
(let [{:keys [last-message messages]} (get chats chat-id)]
(->> (conj messages last-message)
(sort-by :clock-value >)
(filter :show?)
(first)))))
(sort-by :clock-value >)
(filter :show?)
first))))
(reg-sub :get-message-short-preview-markup
(reg-sub
:get-message-short-preview-markup
(fn [db [_ message-id]]
(get-in db [:message-data :short-preview message-id :markup])))
(reg-sub :get-last-message-short-preview
(reg-sub
:get-last-message-short-preview
(fn [db [_ chat-id]]
(let [last-message (subscribe [:get-last-message chat-id])
preview (subscribe [:get-message-short-preview-markup (:message-id @last-message)])]
(when-let [markup @preview]
(commands-utils/generate-hiccup markup)))))
(reg-sub :get-default-container-area-height
:<- [:chat-ui-props :input-height]
(reg-sub
:get-default-container-area-height
:<- [:get-current-chat-ui-prop :input-height]
:<- [:get :layout-height]
:<- [:chat-input-margin]
(fn [[input-height layout-height chat-input-margin]]
(let [bottom (+ input-height chat-input-margin)]
(input-utils/default-container-area-height bottom layout-height))))
(reg-sub :get-max-container-area-height
:<- [:chat-ui-props :input-height]
(reg-sub
:get-max-container-area-height
:<- [:get-current-chat-ui-prop :input-height]
:<- [:get :layout-height]
:<- [:chat-input-margin]
(fn [[input-height layout-height chat-input-margin]]
(let [bottom (+ input-height chat-input-margin)]
(input-utils/max-container-area-height bottom layout-height))))
(reg-sub :chat-animations
(reg-sub
:chat-animations
(fn [db [_ key type]]
(let [chat-id (subscribe [:get-current-chat-id])]
(get-in db [:chat-animations @chat-id key type]))))
(reg-sub :get-chat-last-outgoing-message
(fn [db [_ chat-id]]
(->> (:messages (get-in db [:chats chat-id]))
(reg-sub
:get-chat-last-outgoing-message
:<- [:chats]
(fn [chats [_ chat-id]]
(->> (:messages (get chats chat-id))
(filter :outgoing)
(sort-by :clock-value >)
(first))))
first)))
(reg-sub :get-message-preview-markup
(reg-sub
:get-message-preview-markup
(fn [db [_ message-id]]
(get-in db [:message-data :preview message-id :markup])))
(reg-sub
:get-message-preview
(fn [[_ message-id]]
[(subscribe [:get-message-preview-markup message-id])])
(fn [[markup]]
(when markup
(commands-utils/generate-hiccup markup))))
:get-message-preview
(fn [[_ message-id]]
[(subscribe [:get-message-preview-markup message-id])])
(fn [[markup]]
(when markup
(commands-utils/generate-hiccup markup))))

View File

@ -67,7 +67,7 @@
(list-item [message-status-row contact row]))))
(defn bottom-info-view []
(let [bottom-info (subscribe [:chat-ui-props :bottom-info])
(let [bottom-info (subscribe [:get-current-chat-ui-prop :bottom-info])
contacts (subscribe [:get-contacts])]
(r/create-class
{:display-name "bottom-info-view"

View File

@ -54,9 +54,9 @@
(defn expandable-view [{:keys [key height hide-overlay?]} & _]
(let [anim-value (anim/create-value 0)
input-height (subscribe [:chat-ui-props :input-height])
input-height (subscribe [:get-current-chat-ui-prop :input-height])
max-height (subscribe [:get-max-container-area-height])
fullscreen? (subscribe [:chat-ui-props :fullscreen?])
fullscreen? (subscribe [:get-current-chat-ui-prop :fullscreen?])
chat-input-margin (subscribe [:chat-input-margin])
to-changed-height (subscribe [:chat-animations key :height])
changes-counter (subscribe [:chat-animations key :changes-counter])

View File

@ -11,7 +11,7 @@
(defn get-header [type]
(fn []
(let [parameter-box (subscribe [:chat-parameter-box])
result-box (subscribe [:chat-ui-props :result-box])
result-box (subscribe [:get-current-chat-ui-prop :result-box])
chat-id (subscribe [:get-current-chat-id])
command (subscribe [:selected-chat-command])
index (subscribe [:current-chat-argument-position])]
@ -36,4 +36,4 @@
(dispatch [:set-in [:chats @chat-id :parameter-boxes command-name @index] nil]))
(dispatch [:set-chat-ui-props {:result-box nil}])))}
[view style/header-close-container
[icon :close_light_gray style/header-icon]]]]])))))
[icon :close_light_gray style/header-icon]]]]])))))

View File

@ -55,8 +55,8 @@
(defn- basic-text-input [_]
(let [input-text (subscribe [:chat :input-text])
command (subscribe [:selected-chat-command])
sending-in-progress? (subscribe [:chat-ui-props :sending-in-progress?])
input-focused? (subscribe [:chat-ui-props :input-focused?])
sending-in-progress? (subscribe [:get-current-chat-ui-prop :sending-in-progress?])
input-focused? (subscribe [:get-current-chat-ui-prop :input-focused?])
input-ref (atom nil)]
(fn [{:keys [set-layout-height-fn set-container-width-fn height single-line-input?]}]
[text-input
@ -143,7 +143,7 @@
(let [command (subscribe [:selected-chat-command])
arg-pos (subscribe [:current-chat-argument-position])
seq-arg-input-text (subscribe [:chat :seq-argument-input-text])
sending-in-progress? (subscribe [:chat-ui-props :sending-in-progress?])]
sending-in-progress? (subscribe [:get-current-chat-ui-prop :sending-in-progress?])]
(fn [{:keys [command-width container-width]}]
(when (get-in @command [:command :sequential-params])
(let [{:keys [placeholder hidden type]} (get-in @command [:command :params @arg-pos])]
@ -210,7 +210,7 @@
selected-command [:selected-chat-command]
input-text [:chat :input-text]
seq-arg-input-text [:chat :seq-argument-input-text]
result-box [:chat-ui-props :result-box]]
result-box [:get-current-chat-ui-prop :result-box]]
(let [single-line-input? (:singleLineInput result-box)
{:keys [hide-send-button sequential-params]} (:command selected-command)]
[view style/input-container
@ -236,7 +236,7 @@
(defn container []
(let [margin (subscribe [:chat-input-margin])
show-emoji? (subscribe [:chat-ui-props :show-emoji?])
show-emoji? (subscribe [:get-current-chat-ui-prop :show-emoji?])
input-text (subscribe [:chat :input-text])
anim-margin (anim/create-value 10)
container-anim-margin (anim/create-value 16)

View File

@ -8,7 +8,7 @@
(defmethod action-view :fullscreen
[_]
(let [fullscreen? (re-frame/subscribe [:chat-ui-props :fullscreen?])]
(let [fullscreen? (re-frame/subscribe [:get-current-chat-ui-prop :fullscreen?])]
(fn []
[react/touchable-highlight
{:on-press #(re-frame/dispatch [:set-chat-ui-props {:fullscreen? (not @fullscreen?)}])}
@ -20,7 +20,7 @@
(defmethod action-view :web-view-back
[_]
(let [result-box (re-frame/subscribe [:chat-ui-props :result-box])
(let [result-box (re-frame/subscribe [:get-current-chat-ui-prop :result-box])
webview (re-frame/subscribe [:get :webview-bridge])]
(fn []
[react/touchable-highlight
@ -33,7 +33,7 @@
(defmethod action-view :web-view-forward
[_]
(let [result-box (re-frame/subscribe [:chat-ui-props :result-box])
(let [result-box (re-frame/subscribe [:get-current-chat-ui-prop :result-box])
webview (re-frame/subscribe [:get :webview-bridge])]
(fn []
[react/touchable-highlight
@ -54,7 +54,7 @@
[react/icon (str "action_" image) style/action-view-icon]]])
(defn input-actions-view []
(let [result-box (re-frame/subscribe [:chat-ui-props :result-box])]
(let [result-box (re-frame/subscribe [:get-current-chat-ui-prop :result-box])]
(fn []
(let [{:keys [actions]} @result-box]
[react/view style/actions-container

View File

@ -2,10 +2,10 @@
(:require-macros [status-im.utils.views :refer [defview]])
(:require [re-frame.core :refer [subscribe dispatch]]
[status-im.ui.components.react :refer [view
scroll-view
touchable-highlight
text
icon]]
scroll-view
touchable-highlight
text
icon]]
[status-im.chat.views.input.animations.expandable :refer [expandable-view]]
[status-im.chat.views.input.box-header :as box-header]
[status-im.ui.components.sync-state.offline :refer [offline-view]]))
@ -15,8 +15,8 @@
markup])
(defview result-box-view []
[{:keys [markup] :as result-box} [:chat-ui-props :result-box]]
(when result-box
[markup [:result-box-markup]]
(when markup
[expandable-view {:key :result-box
:draggable? true
:custom-header (box-header/get-header :result-box)}

View File

@ -19,8 +19,8 @@
(defview validation-messages-view []
(letsubs [chat-input-margin [:chat-input-margin]
input-height [:chat-ui-props :input-height]
messages [:chat-ui-props :validation-messages]]
input-height [:get-current-chat-ui-prop :input-height]
messages [:validation-messages]]
(when messages
[c/view (style/root (+ input-height chat-input-margin))
(if (string? messages)

View File

@ -32,7 +32,7 @@
(defview bridged-web-view [{:keys [url]}]
[extra-js [:web-view-extra-js]
rpc-url [:get :rpc-url]
result-box [:chat-ui-props :result-box]]
result-box [:get-current-chat-ui-prop :result-box]]
(when url
[webview-bridge
{:ref #(dispatch [:chat-webview-bridge/set-ref %])

View File

@ -246,7 +246,7 @@
(defview group-message-delivery-status [{:keys [message-id group-id message-status user-statuses] :as msg}]
[app-db-message-user-statuses [:get-in [:message-data :user-statuses message-id]]
app-db-message-status-value [:get-in [:message-data :statuses message-id :status]]
chat [:get-chat-by-id group-id]
chat [:get-current-chat]
contacts [:get-contacts]]
(let [status (or message-status app-db-message-status-value :sending)
user-statuses (merge user-statuses app-db-message-user-statuses)

View File

@ -68,7 +68,7 @@
contacts [:chat :contacts]
public? [:chat :public?]
public-key [:chat :public-key]
show-actions? [:chat-ui-props :show-actions?]
show-actions? [:get-current-chat-ui-prop :show-actions?]
accounts [:get-accounts]
contact [:get-in [:contacts/contacts @chat-id]]
sync-state [:sync-state]

View File

@ -1,13 +1,10 @@
(ns status-im.commands.subs
(:require [re-frame.core :refer [reg-sub]]))
(reg-sub
:get-commands-responses-by-access-scope
(fn [db _]
(:access-scope->commands-responses db)))
(reg-sub :get-commands-responses-by-access-scope :access-scope->commands-responses)
(reg-sub
:get-command
:<- [:get-contacts]
(fn [contacts [_ ref]]
(fn [contacts [_ ref]]
(some->> ref (get-in contacts))))

View File

@ -1,14 +1,20 @@
(ns status-im.ui.screens.accounts.subs
(:require [re-frame.core :refer [reg-sub subscribe]]))
(reg-sub
:get-accounts
(fn [db _]
(get db :accounts/accounts)))
(reg-sub :get-current-public-key
(fn [db]
(:current-public-key db)))
(reg-sub
:get-current-account
:<- [:get :accounts/current-account-id]
(reg-sub :get-accounts
(fn [db]
(:accounts/accounts db)))
(reg-sub :get-current-account-id
(fn [db]
(:accounts/current-account-id db)))
(reg-sub :get-current-account
:<- [:get-current-account-id]
:<- [:get-accounts]
(fn [[account-id accounts]]
(some-> accounts (get account-id))))

View File

@ -154,12 +154,9 @@
(:name (contacts identity))))
(reg-sub :chat-by-id
(fn [db [_ chat-id]]
(get-in db [:chats chat-id])))
(reg-sub :current-chat
(fn [db _]
(get-in db [:chats (:current-chat-id db)])))
:<- [:chats]
(fn [chats [_ chat-id]]
(get chats chat-id)))
(defn chat-contacts [[chat contacts] [_ fn]]
(when chat
@ -171,7 +168,7 @@
(vals contacts)))))
(reg-sub :contacts-current-chat
:<- [:current-chat]
:<- [:get-current-chat]
:<- [:get-contacts]
chat-contacts)
@ -195,7 +192,7 @@
(fn [[_ chat-id] _]
[(if chat-id
(subscribe [:chat-by-id chat-id])
(subscribe [:current-chat]))
(subscribe [:get-current-chat]))
(subscribe [:contacts-by-chat filter chat-id])])
(fn [[chat contacts] [_ chat-id]]
(when (and chat (not (:group-chat chat)))

View File

@ -2,18 +2,25 @@
(:require [re-frame.core :refer [reg-sub]]
[status-im.utils.datetime :as time]))
(defn- calculate-priority [{:keys [chats current-public-key]
:contacts/keys [contacts]}
(reg-sub :get-discoveries :discoveries)
(reg-sub :get-current-tag :current-tag)
(reg-sub :get-discover-search-tags :discover-search-tags)
(reg-sub :get-tags :tags)
(defn- calculate-priority [chats current-public-key contacts
{:keys [whisper-id created-at]}]
(let [contact (get contacts whisper-id)
chat (get chats whisper-id)
seen-online-recently? (< (- (time/now-ms) (get contact :last-online))
time/hour)
me? (= current-public-key whisper-id)]
(+ created-at ;; message is newer => priority is higher
(if (or me? contact) time/day 0) ;; user exists in contact list => increase priority
(if (or me? chat) time/day 0) ;; chat with this user exists => increase priority
(if (or me? seen-online-recently?) time/hour 0)))) ;; the user was online recently => increase priority
(+ created-at ; message is newer => priority is higher
(if (or me? contact) time/day 0) ; user exists in contact list => increase priority
(if (or me? chat) time/day 0) ; chat with this user exists => increase priority
(if (or me? seen-online-recently?) time/hour 0)))) ; the user was online recently => increase priority
(defn- get-discoveries-by-tags [discoveries current-tag tags]
@ -24,45 +31,59 @@
tags')
(vals discoveries))))
(reg-sub :get-popular-discoveries
(fn [db [_ limit tags]]
(let [discoveries (:discoveries db)
current-tag (:current-tag db)
search-tags (:discover-search-tags db)]
(let [discoveries (->> (get-discoveries-by-tags discoveries current-tag (or tags search-tags))
(map #(assoc % :priority (calculate-priority db %)))
(sort-by :priority >))]
{:discoveries (take limit discoveries)
:total (count discoveries)}))))
(reg-sub
:get-popular-discoveries
:<- [:get-discoveries]
:<- [:get-current-tag]
:<- [:get-discover-search-tags]
:<- [:chats]
:<- [:get-contacts]
:<- [:get-current-public-key]
(fn [[discoveries current-tag discover-search-tags chats contacts public-key]
[_ limit tags]]
(let [discoveries (->> (get-discoveries-by-tags discoveries
current-tag
(or tags discover-search-tags))
(map #(assoc % :priority (calculate-priority chats public-key contacts %)))
(sort-by :priority >))]
{:discoveries (take limit discoveries)
:total (count discoveries)})))
(reg-sub :get-top-discovery-per-tag
(fn [{:keys [discoveries tags]} [_ limit]]
(reg-sub
:get-top-discovery-per-tag
:<- [:get-discoveries]
:<- [:get-tags]
(fn [[discoveries tags] [_ limit]]
(let [tag-names (map :name (take limit tags))]
(for [tag tag-names]
(let [results (get-discoveries-by-tags discoveries tag nil)]
(for [tag tag-names]
(let [results (get-discoveries-by-tags discoveries tag nil)]
[tag {:discovery (first results)
:total (count results)}])))))
(reg-sub :get-recent-discoveries
(fn [db]
(sort-by :created-at > (vals (:discoveries db)))))
(reg-sub
:get-recent-discoveries
:<- [:get-discoveries]
(fn [discoveries]
(sort-by :created-at > (vals discoveries))))
(reg-sub :get-popular-tags
(fn [db [_ limit]]
(take limit (:tags db))))
(reg-sub
:get-popular-tags
:<- [:get-tags]
(fn [tags [_ limit]]
(take limit tags)))
(reg-sub :get-discover-search-results
(fn [db]
(let [discoveries (:discoveries db)
current-tag (:current-tag db)
tags (:discover-search-tags db)]
(get-discoveries-by-tags discoveries current-tag tags))))
(reg-sub
:get-discover-search-results
:<- [:get-discoveries]
:<- [:get-current-tag]
:<- [:get-discover-search-tags]
(fn [[discoveries current-tag discover-search-tags]]
(get-discoveries-by-tags discoveries current-tag discover-search-tags)))
(reg-sub :get-all-dapps
(fn [db]
(let [dapp? (->> (get-in db [:group/contact-groups "dapps" :contacts])
(map :identity)
set)]
(->> (:contacts/contacts db)
(filter #(-> % key dapp?))
(into {})))))
(reg-sub
:get-all-dapps
:<- [:get-contact-groups]
:<- [:get-contacts]
(fn [[groups contacts]]
(let [dapp-ids (into #{} (map :identity) (get-in groups ["dapps" :contacts]))]
(select-keys contacts dapp-ids))))

View File

@ -65,28 +65,40 @@
(is (= "/send 1.0 \"John Doe\"" (input/join-command-args ["/send" "1.0" "John Doe"]))))
(deftest selected-chat-command
(is (= (input/selected-chat-command fake-db "test1" "/global-command1")
(is (= (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test1")
(assoc-in [:chats "test1" :input-text] "/global-command1")))
{:command {:name "global-command1"
:ref ["0x1" :command 0 "global-command1"]}
:metadata nil
:args ["arg1" "arg2"]}))
(is (= (input/selected-chat-command fake-db "test2" "/command2")
(is (= (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test2")
(assoc-in [:chats "test2" :input-text] "/command2")))
{:command {:name "command2"
:ref ["0x1" :command 4 "command2"]}
:metadata nil
:args []}))
(is (nil? (input/selected-chat-command fake-db "test1" "/command3")))
(is (= (input/selected-chat-command fake-db "test1" "/command2")
(is (nil? (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test1")
(assoc-in [:chats "test1" :input-text] "/command3")))))
(is (= (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test1")
(assoc-in [:chats "test1" :input-text] "/command2")))
{:command {:name "command2"
:ref ["0x1" :command 2 "command2"]}
:metadata nil
:args ["arg1" "arg2"]}))
(is (= (input/selected-chat-command fake-db "test2" "/response1 arg1")
(is (= (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test2")
(assoc-in [:chats "test2" :input-text] "/response1 arg1")))
{:command {:name "response1"
:ref ["0x2" :response 4 "response1"]}
:metadata nil
:args ["arg1"]}))
(is (= (input/selected-chat-command fake-db "test4" "/command2 arg1")
(is (= (input/selected-chat-command (-> fake-db
(assoc :current-chat-id "test4")
(assoc-in [:chats "test4" :input-text] "/command2 arg1")))
{:command {:name "command2"
:ref ["0x1" :command 4 "command2"]}
:metadata {:meta-k "meta-v"}