From 0f4581476d52eaf91a4dacd1d248b73c7d141c8b Mon Sep 17 00:00:00 2001 From: Roman Volosovskyi Date: Wed, 8 Jun 2016 15:14:35 +0300 Subject: [PATCH] fetch commands.js init --- src/status_im/android/core.cljs | 1 - src/status_im/chat/handlers.cljs | 5 + src/status_im/chat/sign_up.cljs | 3 + src/status_im/chat/suggestions.cljs | 36 +++--- src/status_im/chat/views/suggestions.cljs | 47 ++++--- src/status_im/commands/handlers.cljs | 148 ++++++++++++++++++++++ src/status_im/handlers.cljs | 16 +-- src/status_im/models/commands.cljs | 6 - src/status_im/persistence/realm.cljs | 4 + src/status_im/utils/utils.cljs | 6 +- 10 files changed, 204 insertions(+), 68 deletions(-) create mode 100644 src/status_im/commands/handlers.cljs diff --git a/src/status_im/android/core.cljs b/src/status_im/android/core.cljs index 080a91fa54..c864b06ec6 100644 --- a/src/status_im/android/core.cljs +++ b/src/status_im/android/core.cljs @@ -56,7 +56,6 @@ (dispatch [:load-user-phone-number]) (dispatch [:load-contacts]) ;; load commands from remote server (todo: uncomment) - ;; (dispatch [:load-commands]) (dispatch [:init-console-chat]) (dispatch [:init-chat]) (init-back-button-handler!) diff --git a/src/status_im/chat/handlers.cljs b/src/status_im/chat/handlers.cljs index 0d0af3a2f3..253342baee 100644 --- a/src/status_im/chat/handlers.cljs +++ b/src/status_im/chat/handlers.cljs @@ -250,9 +250,14 @@ ([{:keys [messages current-chat-id] :as db} _] (assoc-in db [:chats current-chat-id :messages] messages))) +(defn load-commands! + [{:keys [current-chat-id]}] + (dispatch [:load-commands! current-chat-id])) + (register-handler :init-chat (-> load-messages! ((enrich init-chat)) + ((after load-commands!)) debug)) (defn initialize-chats diff --git a/src/status_im/chat/sign_up.cljs b/src/status_im/chat/sign_up.cljs index 9633d94464..0c59915e31 100644 --- a/src/status_im/chat/sign_up.cljs +++ b/src/status_im/chat/sign_up.cljs @@ -184,6 +184,9 @@ (def console-chat {:chat-id "console" :name "console" + ; todo remove/change dapp config fot console + :dapp-url "http://localhost:8185" + :dapp-hash 123 :color default-chat-color :group-chat false :is-active true diff --git a/src/status_im/chat/suggestions.cljs b/src/status_im/chat/suggestions.cljs index dcdc0d3db4..c5a0a8a53b 100644 --- a/src/status_im/chat/suggestions.cljs +++ b/src/status_im/chat/suggestions.cljs @@ -2,22 +2,29 @@ (:require [re-frame.core :refer [subscribe dispatch dispatch-sync]] [status-im.db :as db] [status-im.models.commands :refer [commands - suggestions - get-commands - get-chat-command-request - get-chat-command-to-msg-id - clear-staged-commands]] + get-commands + get-chat-command-request + get-chat-command-to-msg-id + clear-staged-commands]] [status-im.utils.utils :refer [log on-error http-get]] [clojure.string :as s])) (defn suggestion? [text] (= (get text 0) "!")) -(defn get-suggestions [db text] - (if (suggestion? text) - ;; TODO change 'commands' to 'suggestions' - (filterv #(.startsWith (:text %) text) (get-commands db)) - [])) +(defn can-be-suggested? [text] + (fn [{:keys [name]}] + (.startsWith (str "!" name) text))) + +(defn get-suggestions + [{:keys [current-chat-id] :as db} text] + (let [commands (get-in db [:chats current-chat-id :commands])] + (if (suggestion? text) + ;; TODO change 'commands' to 'suggestions' + (->> commands + vals + (filter (can-be-suggested? text))) + []))) (defn get-command [db text] (when (suggestion? text) @@ -45,15 +52,6 @@ staged-commands)) (clear-staged-commands db))) -(defn execute-commands-js [body] - (.eval js/window body) - (let [commands (.-commands js/window)] - (dispatch [:set-commands (map #(update % :command keyword) - (js->clj commands :keywordize-keys true))]))) - -(defn load-commands [] - (http-get "chat-commands.js" execute-commands-js nil)) - (defn check-suggestion [db message] (when-let [suggestion-text (when (string? message) (re-matches #"^![^\s]+\s" message))] diff --git a/src/status_im/chat/views/suggestions.cljs b/src/status_im/chat/views/suggestions.cljs index 9a170cd5a5..039554d390 100644 --- a/src/status_im/chat/views/suggestions.cljs +++ b/src/status_im/chat/views/suggestions.cljs @@ -1,11 +1,12 @@ (ns status-im.chat.views.suggestions + (:require-macros [status-im.utils.views :refer [defview]]) (:require [re-frame.core :refer [subscribe dispatch]] [status-im.components.react :refer [view - text - icon - touchable-highlight - list-view - list-item]] + text + icon + touchable-highlight + list-view + list-item]] [status-im.utils.listview :refer [to-datasource]] [status-im.chat.styles.suggestions :as st])) @@ -13,11 +14,11 @@ (dispatch [:set-chat-command command])) (defn suggestion-list-item - [{:keys [description command] - label :text + [{:keys [description] + label :name :as suggestion}] [touchable-highlight - {:onPress #(set-command-input (keyword command))} + {:onPress #(set-command-input (keyword label))} [view st/suggestion-container [view st/suggestion-sub-container [view (st/suggestion-background suggestion) @@ -28,19 +29,17 @@ (defn render-row [row _ _] (list-item [suggestion-list-item row])) -(defn suggestions-view [] - (let [suggestions-atom (subscribe [:get-suggestions])] - (fn [] - (let [suggestions @suggestions-atom] - (when (seq suggestions) - [view - [touchable-highlight {:style st/drag-down-touchable - :onPress (fn [] - ;; TODO hide suggestions? - )} - [view - [icon :drag_down st/drag-down-icon]]] - [view (st/suggestions-container (count suggestions)) - [list-view {:dataSource (to-datasource suggestions) - :enableEmptySections true - :renderRow render-row}]]]))))) +(defview suggestions-view [] + [suggestions [:get-suggestions]] + (when (seq suggestions) + [view + [touchable-highlight {:style st/drag-down-touchable + :onPress (fn [] + ;; TODO hide suggestions? + )} + [view + [icon :drag_down st/drag-down-icon]]] + [view (st/suggestions-container (count suggestions)) + [list-view {:dataSource (to-datasource suggestions) + :enableEmptySections true + :renderRow render-row}]]])) diff --git a/src/status_im/commands/handlers.cljs b/src/status_im/commands/handlers.cljs new file mode 100644 index 0000000000..7f8657d7b2 --- /dev/null +++ b/src/status_im/commands/handlers.cljs @@ -0,0 +1,148 @@ +(ns status-im.commands.handlers + (:require [re-frame.core :refer [register-handler after dispatch subscribe + trim-v debug]] + [status-im.utils.handlers :as u] + [status-im.components.react :as r] + [status-im.utils.utils :refer [http-get toast]] + [clojure.string :as s])) + +;; commands loading flow +; ┌────────────────────────────┐ +; │ user starts chat with dapp │ +; └────────────────────────────┘ +; │ +; ▼ +; ┌───────────────────────┐ +; │ fetch current │ +; │ `commands.js` hash │ +; └───────────────────────┘ +; │ +; ▼ +; ┌───────────────────────────┐ +; │try to fetch `commands.js` │ +; └───────────────────────────┘ +; │ +; ▼ +;┌───┐ ┌─────────────────────────┐ ┌───┐ +;│no ├────────│ there is `commands.js` │────┤yes│ +;└─┬─┘ └─────────────────────────┘ └─┬─┘ +; │ │ +; │ ▼ +; │ ┌───────────────────┐ +; │ ┌────┐ │ Is file's hash │ +; │ │nope├─────────────────│ equal to current? │ +; │ └─┬──┘ └───────────────────┘ +; │ │ │ +; │ │ ┌─┴─┐ +; │ │ │yes│ +; │ │ └─┬─┘ +; │ │ │ +; │ │ ▼ +; │ │ ┌────┐ ┌──────────────────────────┐ ┌────┐ +; │ │ │fail├──│ ask `otto` to handle js │──┤succ│ +; │ │ └──┬─┘ └──────────────────────────┘ └─┬──┘ +; │ │ │ │ +; │ │ │ ▼ +; │ │ │ ┌────────────────────────────┐ +; │ │ ▼ │ save commands │ +; │ │ ┌────────────────────────┐ │ save js ? │ +; │ │ │the dapp emit a message │ │ add some API object form │ +; │ └─▶│ saying js is broken │ │ otto to app-db │ +; │ └────────────────────────┘ └────────────────────────────┘ +; │ │ │ +; │ │ │ +; │ ┌───────────────────┘ ▼ +; │ │ ┌─────────────────────────┐ +; │ │ │ if it is necessary show │ +; │ ▼ │ as fullscreen │ +; │ ┌───────────┐ └─────────────────────────┘ +; │ │ │ │ +; └─▶│ Fin' │◀──────────────────────────────────────────┘ +; │ │ +; └───────────┘ + +(defn reg-handler + ([name handler] (reg-handler name nil handler)) + ([name middleware handler] + (register-handler name [debug trim-v middleware] handler))) + +(def commands-js "commands.js") + +(defn fetch-commands! + [db [identity]] + (when-let [url (:dapp-url (get-in db [:chats identity]))] + (http-get (s/join "/" [url commands-js]) + #(dispatch [::validate-hash identity %]) + #(dispatch [::loading-failed! identity ::file-was-not-found])))) + +(defn dispatch-loaded! + [db [identity file]] + (if (::valid-hash db) + (dispatch [::parse-commands! identity file]) + (dispatch [::loading-failed! identity ::wrong-hash]))) + +(defn get-hash-by-dentity + [db identity] + (get-in db [:chats identity :dapp-hash])) + +(defn get-hash-by-file + [file] + ;; todo implement + 123) + +(defn get-jail [] + (.-Jail (.-NativeModules r/react))) + +(defn parse [file success-callback fail-callback] + (.parse (get-jail) file success-callback fail-callback)) + +(defn json->clj [json] + (js->clj (.parse js/JSON json) :keywordize-keys true)) + +(defn parse-commands! [_ [identity file]] + (parse file + (fn [result] + (let [commands (json->clj result)] + (dispatch [::add-commands identity commands]))) + #(dispatch [::loading-failed! identity ::error-in-jail %]))) + +(defn validate-hash + [db [identity file]] + (let [valid? (= (get-hash-by-dentity db identity) + (get-hash-by-file file))] + (assoc db ::valid-hash valid?))) + +(defn save-commands! + [db] + #_(realm/save (::new-commands db))) + +(defn add-commands + [db [id commands-obj]] + (let [commands (:commands commands-obj)] + (-> db + (update-in [:chats id :commands] merge commands) + (assoc db ::new-commands commands)))) + +(defn loading-failed + [db [id reason details]] + (let [url (get-in db [:chats id :dapp-url])] + (toast (s/join "\n" ["commands.js loading failed" + url + id + (name reason) + details])))) + +(reg-handler :load-commands! (u/side-effect! fetch-commands!)) + +(reg-handler ::validate-hash + (after dispatch-loaded!) + validate-hash) + +(reg-handler ::parse-commands! (u/side-effect! parse-commands!)) + +(reg-handler ::add-commands + (after save-commands!) + add-commands) + +(reg-handler ::loading-failed! (u/side-effect! loading-failed)) + diff --git a/src/status_im/handlers.cljs b/src/status_im/handlers.cljs index 6aa74b5c5f..02d7d9e760 100644 --- a/src/status_im/handlers.cljs +++ b/src/status_im/handlers.cljs @@ -5,8 +5,6 @@ [status-im.db :refer [app-db schema]] [status-im.persistence.simple-kv-store :as kv] [status-im.protocol.state.storage :as storage] - [status-im.models.commands :refer [set-commands]] - [status-im.chat.suggestions :refer [load-commands]] [status-im.utils.logging :as log] [status-im.utils.crypt :refer [gen-random-bytes]] [status-im.utils.handlers :as u] @@ -17,7 +15,8 @@ status-im.discovery.handlers status-im.new-group.handlers status-im.participants.handlers - status-im.protocol.handlers)) + status-im.protocol.handlers + status-im.commands.handlers)) ;; -- Middleware ------------------------------------------------------------ ;; @@ -75,17 +74,6 @@ (fn [_ _] (log/debug "crypt initialized")))) -(register-handler :load-commands - (u/side-effect! - (fn [_ [action]] - (log/debug action) - (load-commands)))) - -(register-handler :set-commands - (fn [db [action commands]] - (log/debug action commands) - (set-commands db commands))) - ;; -- User data -------------------------------------------------------------- (register-handler :load-user-phone-number (fn [db [_]] diff --git a/src/status_im/models/commands.cljs b/src/status_im/models/commands.cljs index a9ba2ffd26..48e808bf12 100644 --- a/src/status_im/models/commands.cljs +++ b/src/status_im/models/commands.cljs @@ -64,12 +64,6 @@ ;; (get db :commands) commands) -(defn set-commands [db commands] - (assoc db :commands commands)) - -;; todo delete -(def suggestions (filterv :suggestion commands)) - (defn get-command [db command-key] (first (filter #(= command-key (:command %)) (get-commands db)))) diff --git a/src/status_im/persistence/realm.cljs b/src/status_im/persistence/realm.cljs index 5d304828fe..fa471355b1 100644 --- a/src/status_im/persistence/realm.cljs +++ b/src/status_im/persistence/realm.cljs @@ -51,6 +51,10 @@ :timestamp "int" :contacts {:type "list" :objectType "chat-contact"} + :dapp-url {:type :string + :optional true} + :dapp-hash {:type :int + :optional true} :last-msg-id "string"}} {:name :tag :primaryKey :name diff --git a/src/status_im/utils/utils.cljs b/src/status_im/utils/utils.cljs index c20a6c1e2a..b317dd0301 100644 --- a/src/status_im/utils/utils.cljs +++ b/src/status_im/utils/utils.cljs @@ -41,10 +41,8 @@ (toast (str error)))))))) (defn http-get - ([action on-success on-error] - (-> (.fetch js/window - (str const/server-address action) - (clj->js {:method "GET"})) + ([url on-success on-error] + (-> (.fetch js/window url (clj->js {:method "GET"})) (.then (fn [response] (log response) (.text response)))