bring messages to chat view

This commit is contained in:
michaelr 2016-03-22 00:43:03 +02:00
parent f32547aaf8
commit ef26278908
18 changed files with 296 additions and 158 deletions

View File

@ -1,7 +1,7 @@
(ns ^:figwheel-no-load env.android.main (ns ^:figwheel-no-load env.android.main
(:require [om.next :as om] (:require [om.next :as om]
[messenger.android.core :as core] [messenger.android.core :as core]
[messenger.state :as state] [messenger.omnext :as omnext]
[figwheel.client :as figwheel :include-macros true])) [figwheel.client :as figwheel :include-macros true]))
(enable-console-print!) (enable-console-print!)
@ -9,7 +9,7 @@
(figwheel/watch-and-reload (figwheel/watch-and-reload
:websocket-url "ws://localhost:3449/figwheel-ws" :websocket-url "ws://localhost:3449/figwheel-ws"
:heads-up-display true :heads-up-display true
:jsload-callback #(om/add-root! state/reconciler core/AppRoot 1)) :jsload-callback #(om/add-root! omnext/reconciler core/AppRoot 1))
(core/init) (core/init)

View File

@ -1,7 +1,7 @@
(ns ^:figwheel-no-load env.ios.main (ns ^:figwheel-no-load env.ios.main
(:require [om.next :as om] (:require [om.next :as om]
[messenger.ios.core :as core] [messenger.ios.core :as core]
[messenger.state :as state] [messenger.omnext :as omnext]
[figwheel.client :as figwheel :include-macros true])) [figwheel.client :as figwheel :include-macros true]))
(enable-console-print!) (enable-console-print!)
@ -9,7 +9,7 @@
(figwheel/watch-and-reload (figwheel/watch-and-reload
:websocket-url "ws://localhost:3449/figwheel-ws" :websocket-url "ws://localhost:3449/figwheel-ws"
:heads-up-display true :heads-up-display true
:jsload-callback #(om/add-root! state/reconciler core/AppRoot 1)) :jsload-callback #(om/add-root! omnext/reconciler core/AppRoot 1))
(core/init) (core/init)

View File

@ -5,7 +5,7 @@
:url "http://www.eclipse.org/legal/epl-v10.html"} :url "http://www.eclipse.org/legal/epl-v10.html"}
:dependencies [[org.clojure/clojure "1.7.0"] :dependencies [[org.clojure/clojure "1.7.0"]
[org.clojure/clojurescript "1.7.170"] [org.clojure/clojurescript "1.7.170"]
[org.omcljs/om "1.0.0-alpha28" :exclusions [cljsjs/react cljsjs/react-dom]] [org.omcljs/om "1.0.0-alpha30" :exclusions [cljsjs/react cljsjs/react-dom]]
[natal-shell "0.1.6"] [natal-shell "0.1.6"]
[syng-im/protocol "0.1.1"]] [syng-im/protocol "0.1.1"]]
:plugins [[lein-cljsbuild "1.1.1"] :plugins [[lein-cljsbuild "1.1.1"]

View File

@ -8,6 +8,7 @@
[natal-shell.alert :refer [alert]]) [natal-shell.alert :refer [alert]])
(:require [om.next :as om :refer-macros [defui]] (:require [om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[messenger.omnext :as omnext]
[messenger.state :as state] [messenger.state :as state]
[messenger.utils.utils :refer [log toast]] [messenger.utils.utils :refer [log toast]]
[messenger.android.login :refer [login]] [messenger.android.login :refer [login]]
@ -15,8 +16,11 @@
[messenger.comm.pubsub :as pubsub] [messenger.comm.pubsub :as pubsub]
[messenger.comm.intercom :as intercom :refer [load-user-phone-number]] [messenger.comm.intercom :as intercom :refer [load-user-phone-number]]
[messenger.protocol.protocol-handler :refer [make-handler]] [messenger.protocol.protocol-handler :refer [make-handler]]
[messenger.init :refer [init-simple-store]]
[messenger.components.chat.chat :as chat]
[syng-im.protocol.api :refer [init-protocol]] [syng-im.protocol.api :refer [init-protocol]]
[messenger.init :refer [init-simple-store]])) [syng-im.utils.logging :as log]
[messenger.components.iname :as in]))
(def app-registry (.-AppRegistry js/React)) (def app-registry (.-AppRegistry js/React))
@ -40,18 +44,20 @@
(defui AppRoot (defui AppRoot
static om/IQuery static om/IQuery
(query [this] (query [this]
'[:loading :contacts-ds :user-phone-number :user-identity :confirmation-code]) [:loading :contacts-ds :user-phone-number :user-identity :confirmation-code])
Object Object
(render [this] (render [this]
(log/debug "APPROOT Rendering")
(navigator (navigator
{:initialRoute {:component login} {:initialRoute {:component login}
:renderScene (fn [route nav] :renderScene (fn [route nav]
(log/debug "RENDER SCENE")
(when state/*nav-render* (when state/*nav-render*
(init-back-button-handler! nav) (init-back-button-handler! nav)
(let [{:keys [component]} (let [{:keys [component]} (js->clj route :keywordize-keys true)
(js->clj route :keywordize-keys true)] props (om/props this)
(component (om/computed (om/props this) props (om/computed props {:nav nav})]
{:nav nav})))))}))) (component props))))})))
;; TODO to service? ;; TODO to service?
(swap! state/app-state assoc :contacts-ds (swap! state/app-state assoc :contacts-ds
@ -66,5 +72,5 @@
(pubsub/setup-pub-sub) (pubsub/setup-pub-sub)
(init-protocol (make-handler)) (init-protocol (make-handler))
(load-user-phone-number) (load-user-phone-number)
(om/add-root! state/reconciler AppRoot 1) (om/add-root! omnext/reconciler AppRoot 1)
(.registerComponent app-registry "Messenger" (fn [] app-root))) (.registerComponent app-registry "Messenger" (fn [] app-root)))

View File

@ -57,3 +57,10 @@
(defn save-new-msg [from payload] (defn save-new-msg [from payload]
(publish! :service [:protocol :protocol/save-new-msg {:from from (publish! :service [:protocol :protocol/save-new-msg {:from from
:payload payload}])) :payload payload}]))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; navigate-to
(defn show-chat [navigator chat-id]
(publish! :service [:navigate-to :scene/chat {:chat-id chat-id
:navigator navigator}]))

View File

@ -4,7 +4,8 @@
[messenger.services.user-data :refer [user-data-handler]] [messenger.services.user-data :refer [user-data-handler]]
[messenger.services.protocol :refer [protocol-handler]] [messenger.services.protocol :refer [protocol-handler]]
[messenger.services.server :refer [server-handler]] [messenger.services.server :refer [server-handler]]
[messenger.services.contacts :refer [contacts-handler]])) [messenger.services.contacts :refer [contacts-handler]]
[messenger.services.navigate-to :refer [navigate-to-handler]]))
(defmulti service (fn [state service-id args] (defmulti service (fn [state service-id args]
service-id)) service-id))
@ -25,6 +26,10 @@
[state service-id args] [state service-id args]
(protocol-handler state args)) (protocol-handler state args))
(defmethod service :navigate-to
[state service-id args]
(navigate-to-handler state args))
(defn services-handler [state service-id args] (defn services-handler [state service-id args]
(log/info "handling " service-id " args = " args) (log/info "handling " service-id " args = " args)
(service state service-id args)) (service state service-id args))

View File

@ -7,7 +7,9 @@
[messenger.components.invertible-scroll-view :refer [invertible-scroll-view]] [messenger.components.invertible-scroll-view :refer [invertible-scroll-view]]
[messenger.components.chat.message :refer [message]] [messenger.components.chat.message :refer [message]]
[messenger.components.chat.new-message :refer [new-message]] [messenger.components.chat.new-message :refer [new-message]]
[messenger.state :as state])) [messenger.state :as state]
[syng-im.utils.logging :as log]
[messenger.components.iname :as in]))
(defn generate-message [n] (defn generate-message [n]
{:id n {:id n
@ -38,10 +40,18 @@
(message (js->clj row :keywordize-keys true))) (message (js->clj row :keywordize-keys true)))
(defui Chat (defui Chat
static in/IName
(get-name [this]
:chat)
static om/IQuery
(query [this]
'[:chat/messages])
Object Object
(render (render
[this] [this]
(let [{:keys [nav]} (om/get-computed this) (let [{:keys [nav]} (om/get-computed this)
{{messages :chat/messages} :chat} (om/props this)
_ (log/debug "messages=" messages)
messages-ds (load-messages)] messages-ds (load-messages)]
(view {:style {:flex 1 (view {:style {:flex 1
:backgroundColor "white"}} :backgroundColor "white"}}

View File

@ -5,15 +5,10 @@
[messenger.state :as state] [messenger.state :as state]
[messenger.utils.utils :refer [log toast http-post]] [messenger.utils.utils :refer [log toast http-post]]
[messenger.utils.resources :as res] [messenger.utils.resources :as res]
[messenger.comm.intercom :as intercom :refer [show-chat]]
[messenger.components.chat.chat :refer [chat]])) [messenger.components.chat.chat :refer [chat]]))
(defn nav-push [nav route] (def react-native-contacts (js/require "react-native-contacts"))
(binding [state/*nav-render* false]
(.push nav (clj->js route))))
(defn show-chat [nav]
(nav-push nav {:component chat
:name "chat"}))
(defui Contact (defui Contact
static om/Ident static om/Ident
@ -21,15 +16,15 @@
[:contact/by-name name]) [:contact/by-name name])
static om/IQuery static om/IQuery
(query [this] (query [this]
'[:name :photo-path :delivery-status :datetime :new-messages-count :online]) '[:name :photo-path :delivery-status :datetime :new-messages-count :online :whisper-identity])
Object Object
(render [this] (render [this]
(let [{:keys [name photo-path delivery-status datetime new-messages-count (let [{:keys [name photo-path delivery-status datetime new-messages-count online whisper-identity]}
online]}
(dissoc (om/props this) :om.next/computed) (dissoc (om/props this) :om.next/computed)
{:keys [nav]} (om/get-computed this)] {:keys [nav]} (om/get-computed this)]
(touchable-highlight (touchable-highlight
{:onPress (fn [] (show-chat nav))} {:onPress (fn []
(show-chat nav whisper-identity))}
(view {:style {:flexDirection "row" (view {:style {:flexDirection "row"
:marginTop 5 :marginTop 5
:marginBottom 5 :marginBottom 5
@ -122,3 +117,4 @@
new-messages-count))))))))) new-messages-count)))))))))
(def contact (om/factory Contact {:keyfn :name})) (def contact (om/factory Contact {:keyfn :name}))

View File

@ -0,0 +1,4 @@
(ns messenger.components.iname)
(defprotocol IName
(get-name [this]))

View File

@ -3,7 +3,7 @@
[natal-shell.alert :refer [alert]]) [natal-shell.alert :refer [alert]])
(:require [om.next :as om :refer-macros [defui]] (:require [om.next :as om :refer-macros [defui]]
[re-natal.support :as sup] [re-natal.support :as sup]
[messenger.state :as state])) [messenger.omnext :as omnext]))
(set! js/React (js/require "react-native")) (set! js/React (js/require "react-native"))
@ -29,5 +29,5 @@
(defonce app-root (om/factory RootNode)) (defonce app-root (om/factory RootNode))
(defn init [] (defn init []
(om/add-root! state/reconciler AppRoot 1) (om/add-root! omnext/reconciler AppRoot 1)
(.registerComponent app-registry "Messenger" (fn [] app-root))) (.registerComponent app-registry "Messenger" (fn [] app-root)))

View File

@ -0,0 +1,8 @@
(ns messenger.models.chat
(:require [messenger.state :as state]))
(defn set-current-chat-id [chat-id]
(swap! state/app-state assoc-in state/current-chat-id-path chat-id))
(defn current-chat-id []
(get-in @state/app-state state/current-chat-id-path))

View File

@ -1,5 +1,6 @@
(ns messenger.models.messages (ns messenger.models.messages
(:require [messenger.persistence.realm :as r])) (:require [messenger.persistence.realm :as r]
[syng-im.utils.random :refer [timestamp]]))
(defn save-message [from {:keys [msg-id] :as msg}] (defn save-message [from {:keys [msg-id] :as msg}]
(when-not (r/exists? :msgs :msg-id msg-id) (when-not (r/exists? :msgs :msg-id msg-id)
@ -7,4 +8,19 @@
(fn [] (fn []
(r/create :msgs {:msg-id msg-id (r/create :msgs {:msg-id msg-id
:chat-id from :chat-id from
:timestamp (timestamp)
:msg (with-out-str (pr msg))} true))))) :msg (with-out-str (pr msg))} true)))))
(defn get-messages [chat-id]
(-> (r/get-by-field :msgs :chat-id chat-id)
(r/sorted :timestamp)
(r/page 0 10)))
(comment
(save-message "0x040028c500ff086ecf1cfbb3c1a7240179cde5b86f9802e6799b9bbe9cdd7ad1b05ae8807fa1f9ed19cc8ce930fc2e878738c59f030a6a2f94b3522dc1378ff154"
{:msg-id "23456"
:content "hi!"})
(get-messages "0x040028c500ff086ecf1cfbb3c1a7240179cde5b86f9802e6799b9bbe9cdd7ad1b05ae8807fa1f9ed19cc8ce930fc2e878738c59f030a6a2f94b3522dc1378ff154")
)

29
src/messenger/omnext.cljs Normal file
View File

@ -0,0 +1,29 @@
(ns messenger.omnext
(:require [om.next :as om]
[syng-im.utils.logging :as log]
[re-natal.support :as sup]
[messenger.models.messages :as msgs]
[messenger.models.chat :as chat]
[messenger.state :as state]))
(defmulti read om/dispatch)
(defmethod read :default [{:keys [state] :as env} key param]
(log/debug "reading" "key=" key "param=" param)
(let [st @state]
(if-let [[_ v] (find st key)]
{:value v}
{:value :not-found})))
(defmethod read :chat [env key param]
(log/debug "reading" "key=" key "param=" param)
(let [chat-id (chat/current-chat-id)
val {:value {:chat/messages (msgs/get-messages chat-id)}}]
val))
(defonce reconciler
(om/reconciler
{:state state/app-state
:parser (om/parser {:read read})
:root-render sup/root-render
:root-unmount sup/root-unmount}))

View File

@ -18,6 +18,7 @@
{:name :msgs {:name :msgs
:primaryKey :msg-id :primaryKey :msg-id
:properties {:msg-id "string" :properties {:msg-id "string"
:timestamp "int"
:chat-id "string" :chat-id "string"
:msg "string"}}]}) :msg "string"}}]})
@ -28,7 +29,6 @@
[name schema])) [name schema]))
(into {}))) (into {})))
(defn field-type [schema-name field] (defn field-type [schema-name field]
(get-in schema-by-name [schema-name :properties field])) (get-in schema-by-name [schema-name :properties field]))
@ -57,6 +57,12 @@
(-> (.objects realm (name schema-name)) (-> (.objects realm (name schema-name))
(.filtered (to-query schema-name :eq field value)))) (.filtered (to-query schema-name :eq field value))))
(defn sorted [results field-name]
(.sorted results (to-string field-name)))
(defn page [results from to]
(js/Array.prototype.slice.call results from to))
(defn single [result] (defn single [result]
(-> (aget result 0))) (-> (aget result 0)))

View File

@ -80,5 +80,5 @@
(sync-contacts args)) (sync-contacts args))
(defn contacts-handler [state [id args]] (defn contacts-handler [state [id args]]
(log/info "user notification: " args) (log/info "contacts-handler: " args)
(contacts state id args)) (contacts state id args))

View File

@ -0,0 +1,35 @@
(ns messenger.services.navigate-to
(:require [syng-im.utils.logging :as log]
[messenger.state :as state]
[messenger.components.chat.chat :as chat]
[messenger.models.chat :refer [set-current-chat-id]]
[om.next :as om]
[messenger.omnext :as omnext]
[messenger.components.iname :as in]))
(defn nav-push [nav route]
(binding [state/*nav-render* false]
(.push nav (clj->js route))))
(defn set-root-query [component]
(let [app-root (om/class->any omnext/reconciler (om/app-root omnext/reconciler))]
(om/set-query! app-root {:query [{(in/get-name component) (om/get-query component)}]})))
(defmulti navigate-to (fn [state id args]
id))
(defmethod navigate-to :scene/chat
[state id {:keys [navigator chat-id] :as args}]
(log/debug "handling " id "args = " (dissoc args :navigator))
(set-current-chat-id chat-id)
(set-root-query chat/Chat)
(nav-push navigator {:component chat/chat}))
(defn navigate-to-handler [state [id args]]
(log/debug "navigate-to-handler: " (dissoc args :navigator))
(navigate-to state id args))
(comment
)

View File

@ -27,5 +27,5 @@
handler)) handler))
(defn server-handler [state [id args]] (defn server-handler [state [id args]]
(log/info "user notification: " args) (log/info "contacts handler: " args)
(server state id args)) (server state id args))

View File

@ -1,7 +1,7 @@
(ns messenger.state (ns messenger.state
(:require [cljs.core.async :as async :refer [chan pub sub]] (:require [cljs.core.async :as async :refer [chan pub sub]]
[om.next :as om] [re-natal.support :as sup]
[re-natal.support :as sup])) [syng-im.utils.logging :as log]))
(def ^{:dynamic true :private true} *nav-render* (def ^{:dynamic true :private true} *nav-render*
"Flag to suppress navigator re-renders from outside om when pushing/popping." "Flag to suppress navigator re-renders from outside om when pushing/popping."
@ -14,26 +14,10 @@
:user-phone-number nil :user-phone-number nil
:user-identity nil :user-identity nil
:confirmation-code nil :confirmation-code nil
:chat {:chat-id nil}
:identity-password "replace-me-with-user-entered-password" :identity-password "replace-me-with-user-entered-password"
:channels {:pub-sub-publisher (chan) :channels {:pub-sub-publisher (chan)
:pub-sub-publication nil}})) :pub-sub-publication nil}}))
(defmulti read om/dispatch)
(defmethod read :default
[{:keys [state]} k _]
(let [st @state]
(if-let [[_ v] (find st k)]
{:value v}
{:value :not-found})))
(defonce reconciler
(om/reconciler
{:state app-state
:parser (om/parser {:read read})
:root-render sup/root-render
:root-unmount sup/root-unmount}))
(defn state [] @app-state) (defn state [] @app-state)
(def pub-sub-bus-path [:channels :pub-sub-publisher]) (def pub-sub-bus-path [:channels :pub-sub-publisher])
@ -42,7 +26,39 @@
(def protocol-initialized-path [:protocol-initialized]) (def protocol-initialized-path [:protocol-initialized])
(def simple-store-path [:simple-store]) (def simple-store-path [:simple-store])
(def identity-password-path [:identity-password]) (def identity-password-path [:identity-password])
(def current-chat-id-path [:chat :current-chat-id])
(defn pub-sub-publisher [app] (get-in app pub-sub-bus-path)) (defn pub-sub-publisher [app] (get-in app pub-sub-bus-path))
(defn kv-store [] (defn kv-store []
(get-in @app-state simple-store-path)) (get-in @app-state simple-store-path))
(comment
(use 'figwheel-sidecar.repl-api)
(cljs-repl)
(defn read
[{:keys [state] :as env} key params]
(let [st @state]
(if-let [[_ v] (find st key)]
{:value v}
{:value :not-found})))
(def my-parser (om/parser {:read read}))
(def my-state (atom {:count 0 :title "what"}))
(my-parser {:state my-state} [:count :title])
(defn mutate
[{:keys [state] :as env} key params]
(if (= 'increment key)
{:value {:keys [:count]}
:action #(swap! state update-in [:count] inc)}
{:value :not-found}))
(def my-parser (om/parser {:read read :mutate mutate}))
(my-parser {:state my-state} '[(increment)])
@my-state
)