Navigation

Former-commit-id: 50beafc5a2
This commit is contained in:
virvar 2016-02-25 19:21:08 +03:00
parent 4adbc18dab
commit 0ed10176b2
6 changed files with 236 additions and 115 deletions

BIN
images/nav-back.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 530 B

View File

@ -0,0 +1,78 @@
(ns messenger.android.chat
(:require-macros
[natal-shell.components :refer [view text image touchable-highlight list-view
toolbar-android]]
[natal-shell.data-source :refer [data-source clone-with-rows]]
[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]
[messenger.android.resources :as res]))
(defn nav-pop [nav]
(binding [state/*nav-render* false]
(.pop nav)))
(defui Message
static om/Ident
(ident [this {:keys [id]}]
[:message/by-id id])
static om/IQuery
(query [this]
'[:id :body :delivery-status :datetime])
Object
(render [this]
(let [{:keys [id body delivery-status datetime]}
(om/props this)]
(text {:style {:color "#AAB2B2"
:fontFamily "Avenir-Roman"
:fontSize 14
:marginTop 2
:paddingRight 10}}
body))))
(def message (om/factory Message {:keyfn :id}))
(defn render-row [row section-id row-id]
(message (js->clj row :keywordize-keys true)))
(defn generate-message [n]
{:id n
:body "Hi"
:delivery-status (if (< (rand) 0.5) :delivered :seen)
:datetime "15:30"})
(defn generate-messages [n]
(map generate-message (range 1 (inc n))))
(defn load-message []
(swap! state/app-state update :contacts-ds
#(clone-with-rows %
(vec (generate-messages 10)))))
(defui Chat
;; static om/IQuery
;; (query [this]
;; '[:contacts-ds])
Object
;; (componentDidMount [this]
;; (load-contacts))
(render [this]
(let [{:keys [contacts-ds]} (om/props this)
{:keys [nav]} (om/get-computed this)]
(view {:style {:flex 1}}
(toolbar-android {:logo res/logo-icon
:title "Chat name"
:style {:backgroundColor "#e9eaed"
:height 56}
:navIcon res/nav-back-icon
:onIconClicked (fn []
(nav-pop nav))})
(text {} "Hello")
;; (list-view {:dataSource contacts-ds
;; :renderRow render-row
;; :style {}})
))))
(def chat (om/factory Chat))

View File

@ -7,18 +7,21 @@
[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.state :as state]
[messenger.android.resources :as res]
[messenger.android.chat :refer [chat]]))
(def fake-contacts? true) (def fake-contacts? true)
(set! js/React (js/require "react-native"))
(def react-native-contacts (js/require "react-native-contacts")) (def react-native-contacts (js/require "react-native-contacts"))
(def logo-icon (js/require "./images/logo.png")) (defn nav-push [nav route]
(def user-no-photo (js/require "./images/no-photo.png")) (binding [state/*nav-render* false]
(def online-icon (js/require "./images/online.png")) (.push nav (clj->js route))))
(def seen-icon (js/require "./images/seen.png"))
(def delivered-icon (js/require "./images/delivered.png")) (defn show-chat [nav]
(nav-push nav {:component chat
:name "chat"}))
(defui Contact (defui Contact
static om/Ident static om/Ident
@ -30,7 +33,10 @@
Object Object
(render [this] (render [this]
(let [{:keys [name photo delivery-status datetime new-messages-count online]} (let [{:keys [name photo delivery-status datetime new-messages-count online]}
(om/props this)] (dissoc (om/props this) :om.next/computed)
{:keys [nav]} (om/get-computed this)]
(touchable-highlight
{:onPress (fn [] (show-chat nav))}
(view {:style {:flexDirection "row" (view {:style {:flexDirection "row"
:marginTop 5 :marginTop 5
:marginBottom 5 :marginBottom 5
@ -49,7 +55,7 @@
:elevation 6} :elevation 6}
(image {:source (if (< 0 (count photo)) (image {:source (if (< 0 (count photo))
{:uri photo} {:uri photo}
user-no-photo) res/user-no-photo)
:style {:borderWidth 2 :style {:borderWidth 2
:borderColor "#FFFFFF" :borderColor "#FFFFFF"
:borderRadius 50 :borderRadius 50
@ -69,7 +75,7 @@
:borderRadius 50 :borderRadius 50
:backgroundColor "#FFFFFF" :backgroundColor "#FFFFFF"
:elevation 6} :elevation 6}
(image {:source online-icon (image {:source res/online-icon
:style {:width 12 :style {:width 12
:height 12}})))) :height 12}}))))
(view {:style {:flexDirection "column" (view {:style {:flexDirection "column"
@ -95,8 +101,8 @@
:right 0}} :right 0}}
(when delivery-status (when delivery-status
(image {:source (if (= (keyword delivery-status) :seen) (image {:source (if (= (keyword delivery-status) :seen)
seen-icon res/seen-icon
delivered-icon) res/delivered-icon)
:style {:marginTop 5}})) :style {:marginTop 5}}))
;;; datetime ;;; datetime
(text {:style {:fontFamily "Avenir-Roman" (text {:style {:fontFamily "Avenir-Roman"
@ -125,12 +131,13 @@
:lineHeight 19 :lineHeight 19
:textAlign "center" :textAlign "center"
:top 1}} :top 1}}
new-messages-count)))))))) new-messages-count)))))))))
(def contact (om/factory Contact {:keyfn :name})) (def contact (om/factory Contact {:keyfn :name}))
(defn render-row [row section-id row-id] (defn render-row [nav row section-id row-id]
(contact (js->clj row :keywordize-keys true))) (contact (om/computed (js->clj row :keywordize-keys true)
{:nav nav})))
(defn generate-contact [n] (defn generate-contact [n]
{:name (str "Contact " n) {:name (str "Contact " n)
@ -167,14 +174,15 @@
(componentDidMount [this] (componentDidMount [this]
(load-contacts)) (load-contacts))
(render [this] (render [this]
(let [{:keys [contacts-ds]} (om/props this)] (let [{:keys [contacts-ds]} (om/props this)
{:keys [nav]} (om/get-computed this)]
(view {:style {:flex 1}} (view {:style {:flex 1}}
(toolbar-android {:logo logo-icon (toolbar-android {:logo res/logo-icon
:title "Chats" :title "Chats"
:style {:backgroundColor "#e9eaed" :style {:backgroundColor "#e9eaed"
:height 56}}) :height 56}})
(list-view {:dataSource contacts-ds (list-view {:dataSource contacts-ds
:renderRow render-row :renderRow (partial render-row nav)
:style {}}))))) :style {}})))))
(def contacts-list (om/factory ContactsList)) (def contacts-list (om/factory ContactsList))

View File

@ -1,30 +1,52 @@
(ns messenger.android.core (ns messenger.android.core
(:require-macros (:require-macros
[natal-shell.components :refer [view text image touchable-highlight list-view [natal-shell.components :refer [navigator view text image touchable-highlight list-view
toolbar-android]] toolbar-android]]
[natal-shell.data-source :refer [data-source clone-with-rows]] [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.core :refer [with-error-view]]
[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.state :as state]
[messenger.android.contacts-list :as contacts-list])) [messenger.android.contacts-list :refer [contacts-list]]
[messenger.android.chat :refer [chat]]))
(set! js/React (js/require "react-native"))
(def app-registry (.-AppRegistry js/React)) (def app-registry (.-AppRegistry js/React))
(def initialized-atom (atom false))
(defn init-back-button-handler! [nav]
(if (not @initialized-atom)
(swap! initialized-atom
(fn [initialized]
(when (not initialized)
(add-event-listener "hardwareBackPress"
(fn []
(binding [state/*nav-render* false]
(when (< 1 (.-length (.getCurrentRoutes nav)))
(.pop nav)
true)))))
true))))
(defui AppRoot (defui AppRoot
static om/IQuery static om/IQuery
(query [this] (query [this]
'[:contacts-ds]) '[:page :contacts-ds])
Object Object
(render [this] (render [this]
(let [{:keys [contacts-ds]} (om/props this)] (let [{:keys [page contacts-ds]} (om/props this)]
(contacts-list/contacts-list (om/props this))))) (navigator
{:initialRoute {:component contacts-list}
: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})))))}))))
(swap! state/app-state assoc :contacts-ds (swap! state/app-state assoc :contacts-ds
(data-source {:rowHasChanged (fn [row1 row2] (data-source {:rowHasChanged (fn [row1 row2]
(not= row1 row2))})) (not= row1 row2))}))
(swap! state/app-state assoc :component contacts-list)
(defonce RootNode (sup/root-node! 1)) (defonce RootNode (sup/root-node! 1))
(defonce app-root (om/factory RootNode)) (defonce app-root (om/factory RootNode))

View File

@ -0,0 +1,8 @@
(ns messenger.android.resources)
(def logo-icon (js/require "./images/logo.png"))
(def nav-back-icon (js/require "./images/nav-back.png"))
(def user-no-photo (js/require "./images/no-photo.png"))
(def online-icon (js/require "./images/online.png"))
(def seen-icon (js/require "./images/seen.png"))
(def delivered-icon (js/require "./images/delivered.png"))

View File

@ -2,7 +2,12 @@
(:require [om.next :as om] (:require [om.next :as om]
[re-natal.support :as sup])) [re-natal.support :as sup]))
(defonce app-state (atom {})) (set! js/React (js/require "react-native"))
(defonce app-state (atom {:component nil}))
(def ^{:dynamic true :private true} *nav-render*
"Flag to suppress navigator re-renders from outside om when pushing/popping."
true)
(defmulti read om/dispatch) (defmulti read om/dispatch)
(defmethod read :default (defmethod read :default