diff --git a/project.clj b/project.clj index 910e05fdda..63025bbf95 100644 --- a/project.clj +++ b/project.clj @@ -12,35 +12,36 @@ [lein-figwheel "0.5.0-2"]] :clean-targets ["target/" "index.ios.js" "index.android.js"] :aliases {"prod-build" ^{:doc "Recompile code with prod profile."} - ["do" "clean" - ["with-profile" "prod" "cljsbuild" "once" "ios"] - ["with-profile" "prod" "cljsbuild" "once" "android"]]} + ["do" "clean" + ["with-profile" "prod" "cljsbuild" "once" "ios"] + ["with-profile" "prod" "cljsbuild" "once" "android"]]} + :figwheel {:nrepl-port 7888} :profiles - {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"] - [com.cemerick/piggieback "0.2.1"]] - :source-paths ["src" "env/dev"] - :cljsbuild {:builds - {:ios {:source-paths ["src" "env/dev"] - :figwheel true - :compiler {:output-to "target/ios/not-used.js" - :main "env.ios.main" - :output-dir "target/ios" - :optimizations :none}} - :android {:source-paths ["src" "env/dev"] - :figwheel true - :compiler {:output-to "target/android/not-used.js" - :main "env.android.main" - :output-dir "target/android" - :optimizations :none}}}} - :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}} + {:dev {:dependencies [[figwheel-sidecar "0.5.0-2"] + [com.cemerick/piggieback "0.2.1"]] + :source-paths ["src" "env/dev"] + :cljsbuild {:builds + {:ios {:source-paths ["src" "env/dev"] + :figwheel true + :compiler {:output-to "target/ios/not-used.js" + :main "env.ios.main" + :output-dir "target/ios" + :optimizations :none}} + :android {:source-paths ["src" "env/dev"] + :figwheel true + :compiler {:output-to "target/android/not-used.js" + :main "env.android.main" + :output-dir "target/android" + :optimizations :none}}}} + :repl-options {:nrepl-middleware [cemerick.piggieback/wrap-cljs-repl]}} :prod {:cljsbuild {:builds - {:ios {:source-paths ["src" "env/prod"] - :compiler {:output-to "index.ios.js" - :main "env.ios.main" - :output-dir "target/ios" - :optimizations :simple}} + {:ios {:source-paths ["src" "env/prod"] + :compiler {:output-to "index.ios.js" + :main "env.ios.main" + :output-dir "target/ios" + :optimizations :simple}} :android {:source-paths ["src" "env/prod"] - :compiler {:output-to "index.android.js" - :main "env.android.main" - :output-dir "target/android" - :optimizations :simple}}}}}}) + :compiler {:output-to "index.android.js" + :main "env.android.main" + :output-dir "target/android" + :optimizations :simple}}}}}}) diff --git a/src/messenger/android/core.cljs b/src/messenger/android/core.cljs index 63bfee03b2..59d264d785 100644 --- a/src/messenger/android/core.cljs +++ b/src/messenger/android/core.cljs @@ -1,11 +1,11 @@ (ns messenger.android.core (:require-macros - [natal-shell.components :refer [navigator view text image touchable-highlight list-view - toolbar-android]] - [natal-shell.data-source :refer [data-source clone-with-rows]] - [natal-shell.back-android :refer [add-event-listener]] - [natal-shell.core :refer [with-error-view]] - [natal-shell.alert :refer [alert]]) + [natal-shell.components :refer [navigator view text image touchable-highlight list-view + toolbar-android]] + [natal-shell.data-source :refer [data-source clone-with-rows]] + [natal-shell.back-android :refer [add-event-listener]] + [natal-shell.core :refer [with-error-view]] + [natal-shell.alert :refer [alert]]) (:require [om.next :as om :refer-macros [defui]] [re-natal.support :as sup] [messenger.state :as state] @@ -15,7 +15,10 @@ [messenger.android.chat :refer [chat]] [messenger.comm.pubsub :as pubsub] [messenger.comm.intercom :as intercom :refer [load-user-phone-number - load-user-whisper-identity]])) + load-user-whisper-identity]] + [messenger.protocol.protocol-handler :refer [make-handler]] + [syng-im.protocol.api :refer [init-protocol]])) + (def app-registry (.-AppRegistry js/React)) @@ -36,18 +39,18 @@ (defui AppRoot static om/IQuery (query [this] - '[:contacts-ds :user-phone-number :confirmation-code]) + '[:contacts-ds :user-phone-number :confirmation-code]) Object (render [this] - (navigator - {:initialRoute {:component login} - :renderScene (fn [route nav] - (when state/*nav-render* - (init-back-button-handler! nav) - (let [{:keys [component]} - (js->clj route :keywordize-keys true)] - (component (om/computed (om/props this) - {:nav nav})))))}))) + (navigator + {:initialRoute {:component login} + :renderScene (fn [route nav] + (when state/*nav-render* + (init-back-button-handler! nav) + (let [{:keys [component]} + (js->clj route :keywordize-keys true)] + (component (om/computed (om/props this) + {:nav nav})))))}))) ;; TODO to service? (swap! state/app-state assoc :contacts-ds @@ -60,6 +63,7 @@ (defn init [] (pubsub/setup-pub-sub) + (init-protocol (make-handler)) (load-user-phone-number) (load-user-whisper-identity) (om/add-root! state/reconciler AppRoot 1) diff --git a/src/messenger/android/login.cljs b/src/messenger/android/login.cljs index 34a4d2a6c0..4dda8190e4 100644 --- a/src/messenger/android/login.cljs +++ b/src/messenger/android/login.cljs @@ -9,7 +9,8 @@ [messenger.comm.intercom :as intercom :refer [set-user-phone-number]] [messenger.utils.utils :refer [log toast http-post]] [messenger.utils.resources :as res] - [messenger.android.sign-up-confirm :refer [sign-up-confirm]])) + [messenger.android.sign-up-confirm :refer [sign-up-confirm]] + [messenger.constants :refer [ethereum-rpc-url]])) (def nav-atom (atom nil)) diff --git a/src/messenger/comm/intercom.cljs b/src/messenger/comm/intercom.cljs index 9199559bfa..0c6cd1370c 100644 --- a/src/messenger/comm/intercom.cljs +++ b/src/messenger/comm/intercom.cljs @@ -10,7 +10,6 @@ (put! publisher [topic message]))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - ;;; user data (defn set-user-phone-number [phone-number] @@ -30,6 +29,7 @@ (publish! :service [:user-data :user-data/set-confirmation-code confirmation-code])) +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; server (defn sign-up [phone-number whisper-identity handler] @@ -42,7 +42,7 @@ {:confirmation-code confirmation-code :handler handler}])) - +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; contacts (defn load-syng-contacts [] @@ -52,3 +52,7 @@ (publish! :service [:contacts :contacts/sync-contacts handler])) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; protocol + +(defn protocol-initialized [identity] + (publish! :service [:protocol :protocol/initialized {:identity identity}])) diff --git a/src/messenger/comm/services.cljs b/src/messenger/comm/services.cljs index 59a3bda5f4..f3155d6112 100644 --- a/src/messenger/comm/services.cljs +++ b/src/messenger/comm/services.cljs @@ -2,6 +2,7 @@ (:require [syng-im.utils.logging :as log] [messenger.services.user-data :refer [user-data-handler]] + [messenger.services.protocol :refer [protocol-handler]] [messenger.services.server :refer [server-handler]] [messenger.services.contacts :refer [contacts-handler]])) @@ -20,6 +21,10 @@ [state service-id args] (contacts-handler state args)) +(defmethod service :protocol + [state service-id args] + (protocol-handler state args)) + (defn services-handler [state service-id args] (log/info "handling " service-id " args = " args) (service state service-id args)) diff --git a/src/messenger/constants.cljs b/src/messenger/constants.cljs new file mode 100644 index 0000000000..5a37187434 --- /dev/null +++ b/src/messenger/constants.cljs @@ -0,0 +1,3 @@ +(ns messenger.constants) + +(def ethereum-rpc-url "http://localhost:8545") diff --git a/src/messenger/models/protocol.cljs b/src/messenger/models/protocol.cljs new file mode 100644 index 0000000000..f09529d3a7 --- /dev/null +++ b/src/messenger/models/protocol.cljs @@ -0,0 +1,19 @@ +(ns messenger.models.protocol + (:require [messenger.state :as state] + [messenger.persistence.realm :as r])) + +(defn set-initialized [initialized?] + (swap! state/app-state assoc-in state/protocol-initialized-path initialized?)) + +;; TODO at least the private key has to be encrypted with user's password + +(defn update-identity [identity] + (r/write + (fn [] + (r/create :kv-store {:key :identity + :value (str identity)} true)))) + +(defn current-identity [] + (-> (r/get-by-field :kv-store :key :identity) + (r/single-cljs) + (r/decode-value))) diff --git a/src/messenger/persistence/realm.cljs b/src/messenger/persistence/realm.cljs new file mode 100644 index 0000000000..da2eb59dd6 --- /dev/null +++ b/src/messenger/persistence/realm.cljs @@ -0,0 +1,83 @@ +(ns messenger.persistence.realm + (:require [cljs.reader :refer [read-string]] + [syng-im.utils.logging :as log] + [messenger.utils.types :refer [to-string]])) + +(set! js/Realm (js/require "realm")) + +(def opts {:schema [{:name "Contact" + :properties {:phone-number "string" + :whisper-identity "string" + :name "string" + :photo-path "string"}} + {:name :kv-store + :primaryKey :key + :properties {:key "string" + :value "string"}}]}) + +(def realm (js/Realm. (clj->js opts))) + +(def schema-by-name (->> (:schema opts) + (mapv (fn [{:keys [name] :as schema}] + [name schema])) + (into {}))) + + +(defn field-type [schema-name field] + (get-in schema-by-name [schema-name :properties field])) + +(defn write [f] + (.write realm f)) + +(defn create + ([schema-name obj] + (create schema-name obj false)) + ([schema-name obj update?] + (.create realm (to-string schema-name) (clj->js obj) update?))) + +(defmulti to-query (fn [schema-name operator field value] + operator)) + +(defmethod to-query :eq [schema-name operator field value] + (let [value (to-string value) + query (str (name field) "=" (if (= "string" (field-type schema-name field)) + (str "\"" value "\"") + value)) + ;_ (log/debug query) + ] + query)) + +(defn get-by-field [schema-name field value] + (-> (.objects realm (name schema-name)) + (.filtered (to-query schema-name :eq field value)))) + +(defn single [result] + (-> (aget result 0))) + +(defn single-cljs [result] + (-> (aget result 0) + (js->clj :keywordize-keys true))) + +(defn decode-value [{:keys [key value]}] + (read-string value)) + +(comment + (use 'figwheel-sidecar.repl-api) + (cljs-repl) + + (def x (-> (get-by-field :kv-store :key :identity) + (single))) + + (aget x 1) + + (write (fn [] + (.delete realm (-> (get-by-field :kv-store :key :identity) + (single))))) + + + (log/info (.keys js/Object realm)) + (log/info (clj->js opts)) + + (clj->js (clj->js {:a [{:b 123}]})) + + ) \ No newline at end of file diff --git a/src/messenger/protocol/protocol_handler.cljs b/src/messenger/protocol/protocol_handler.cljs new file mode 100644 index 0000000000..447af14424 --- /dev/null +++ b/src/messenger/protocol/protocol_handler.cljs @@ -0,0 +1,44 @@ +(ns messenger.protocol.protocol-handler + (:require [syng-im.utils.logging :as log] + [messenger.constants :refer [ethereum-rpc-url]] + [messenger.comm.intercom :refer [protocol-initialized]] + [messenger.models.protocol :refer [current-identity]])) + +(defn make-handler [] + {:ethereum-rpc-url ethereum-rpc-url + :identity (current-identity) + :storage nil + :handler (fn [{:keys [event-type] :as event}] + (log/info "Event:" (clj->js event)) + (case event-type + :initialized (let [{:keys [identity]} event] + (protocol-initialized identity)) + ;:new-msg (let [{from :from + ; {content :content} :payload} event] + ; (add-to-chat "chat" from content)) + ;:msg-acked (let [{:keys [msg-id]} event] + ; (add-to-chat "chat" ":" (str "Message " msg-id " was acked"))) + ;:delivery-failed (let [{:keys [msg-id]} event] + ; (add-to-chat "chat" ":" (str "Delivery of message " msg-id " failed"))) + ;:new-group-chat (let [{:keys [from group-id identities]} event] + ; (set-group-id! group-id) + ; (set-group-identities identities) + ; (add-to-chat "group-chat" ":" (str "Received group chat invitation from " from " for group-id: " group-id))) + ;:group-chat-invite-acked (let [{:keys [from group-id]} event] + ; (add-to-chat "group-chat" ":" (str "Received ACK for group chat invitation from " from " for group-id: " group-id))) + ;:new-group-msg (let [{from :from + ; {content :content} :payload} event] + ; (add-to-chat "group-chat" from content)) + ;:group-new-participant (let [{:keys [group-id identity from]} event] + ; (add-to-chat "group-chat" ":" (str (shorten from) " added " (shorten identity) " to group chat")) + ; (add-identity-to-group-list identity)) + ;:group-removed-participant (let [{:keys [group-id identity from]} event] + ; (add-to-chat "group-chat" ":" (str (shorten from) " removed " (shorten identity) " from group chat")) + ; (remove-identity-from-group-list identity)) + ;:removed-from-group (let [{:keys [group-id from]} event] + ; (add-to-chat "group-chat" ":" (str (shorten from) " removed you from group chat"))) + ;:participant-left-group (let [{:keys [group-id from]} event] + ; (add-to-chat "group-chat" ":" (str (shorten from) " left group chat"))) + ;(add-to-chat "chat" ":" (str "Don't know how to handle " event-type)) + (log/info "Don't know how to handle" event-type) + ))}) diff --git a/src/messenger/services/protocol.cljs b/src/messenger/services/protocol.cljs new file mode 100644 index 0000000000..b48d38a5fe --- /dev/null +++ b/src/messenger/services/protocol.cljs @@ -0,0 +1,17 @@ +(ns messenger.services.protocol + (:require [messenger.models.protocol :refer [set-initialized + update-identity]] + [syng-im.utils.logging :as log])) + +(defmulti protocol (fn [state id args] + id)) + +(defmethod protocol :protocol/initialized + [state id {:keys [identity] :as args}] + (log/info "handling " id "args = " args) + (update-identity identity) + (set-initialized true)) + +(defn protocol-handler [state [id args]] + (log/debug "protocol-handler: " args) + (protocol state id args)) diff --git a/src/messenger/services/user_data.cljs b/src/messenger/services/user_data.cljs index b921d93207..c51f42dd39 100644 --- a/src/messenger/services/user_data.cljs +++ b/src/messenger/services/user_data.cljs @@ -26,7 +26,7 @@ (defmethod user-data :user-data/load-phone-number [state id args] - (log/info "handling " id " args = " args) + (log/debug "handling " id "args = " args) (load-phone-number)) (defmethod user-data :user-data/load-whisper-identity @@ -48,5 +48,5 @@ (set-confirmation-code confirmation-code)) (defn user-data-handler [state [id args]] - (log/info "user notification: " args) + (log/debug "user-data-handler: " args) (user-data state id args)) diff --git a/src/messenger/state.cljs b/src/messenger/state.cljs index 598adf8dd2..746d4f998c 100644 --- a/src/messenger/state.cljs +++ b/src/messenger/state.cljs @@ -37,5 +37,6 @@ (def pub-sub-bus-path [:channels :pub-sub-publisher]) (def pub-sub-path [:channels :pub-sub-publication]) (def user-notification-path [:user-notification]) +(def protocol-initialized-path [:protocol-initialized]) (defn pub-sub-publisher [app] (get-in app pub-sub-bus-path)) diff --git a/src/messenger/utils/database.cljs b/src/messenger/utils/database.cljs index 04ef19f127..c0858f3dcd 100644 --- a/src/messenger/utils/database.cljs +++ b/src/messenger/utils/database.cljs @@ -1,13 +1,6 @@ (ns messenger.utils.database - (:require [messenger.utils.utils :refer [log toast http-post]])) - -(set! js/Realm (js/require "realm")) - -(def realm (js/Realm. (clj->js {:schema [{:name "Contact" - :properties {:phone-number "string" - :whisper-identity "string" - :name "string" - :photo-path "string"}}]}))) + (:require [messenger.utils.utils :refer [log toast http-post]] + [messenger.persistence.realm :refer [realm]])) (defn write [f] (.write realm f)) diff --git a/src/messenger/utils/types.cljs b/src/messenger/utils/types.cljs new file mode 100644 index 0000000000..fed789f0c1 --- /dev/null +++ b/src/messenger/utils/types.cljs @@ -0,0 +1,6 @@ +(ns messenger.utils.types) + +(defn to-string [s] + (if (keyword? s) + (name s) + s))