improve navigation duration

This commit is contained in:
Roman Volosovskyi 2017-12-20 20:45:42 +02:00
parent f65e200fca
commit 1ba7c33868
No known key found for this signature in database
GPG Key ID: 93DEFA3D720926F7
11 changed files with 409 additions and 37 deletions

View File

@ -73,6 +73,24 @@
:group-chat group-chat
:current-public-key current-public-key)])
(defview messages-view-animation [message-view]
;; smooths out appearance of message-view
(letsubs [opacity (anim/create-value 0)
duration (if platform/android? 100 200)
timeout (if platform/android? 50 0)]
{:component-did-mount (fn [component]
(anim/start
(anim/anim-sequence
[(anim/anim-delay timeout)
(anim/spring opacity {:toValue 1
:duration duration})])))}
[react/with-activity-indicator
{:style style/message-view-preview
:preview [react/view style/message-view-preview]}
[react/animated-view {:style (style/message-view-animated opacity)}
message-view]]))
(defview messages-view [group-chat]
(letsubs [messages [:get-current-chat-messages]
current-public-key [:get-current-public-key]]
@ -91,7 +109,8 @@
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]]
layout-height [:get :layout-height]
current-view [:get :view-id]]
{:component-did-mount #(re-frame/dispatch [:check-and-open-dapp!])
:component-will-unmount #(re-frame/dispatch [:set-chat-ui-props {:show-emoji? false}])}
[react/view {:style style/chat-view
@ -100,7 +119,9 @@
(when (not= height layout-height)
(re-frame/dispatch [:set-layout-height height]))))}
[chat-toolbar]
[messages-view group-chat]
(when (= :chat current-view)
[messages-view-animation
[messages-view group-chat]])
[input/container {:text-empty? (string/blank? input-text)}]
(when show-actions?
[actions/actions-view])

View File

@ -204,3 +204,12 @@
(defstyle actions-list-view
{:ios {:border-bottom-color component.styles/color-gray3
:border-bottom-width 0.5}})
(def message-view-preview
{:flex 1
:align-items :center
:justify-content :center})
(defn message-view-animated [opacity]
{:opacity opacity
:flex 1})

View File

@ -13,11 +13,12 @@
(first name)]])
(defn chat-icon [photo-path {:keys [size accessibility-label]}]
(let [photo (if (string/starts-with? photo-path "contacts://")
(->> (string/replace photo-path #"contacts://" "")
(keyword)
(get resources/contacts))
{:uri photo-path})]
(let [photo (when photo-path
(if (string/starts-with? photo-path "contacts://")
(->> (string/replace photo-path #"contacts://" "")
(keyword)
(get resources/contacts))
{:uri photo-path}))]
[react/image {:source photo
:style (styles/image-style size)
:accessibility-label (or accessibility-label :chat-icon)}]))

View File

@ -71,7 +71,7 @@
;; Accessor methods for React Components
(defn add-font-style [style-key {:keys [font] :as opts :or {font :default}}]
(let [font (get-in platform-specific [:fonts (keyword font)])
(let [font (get-in platform-specific [:fonts (keyword font)])
style (get opts style-key)]
(-> opts
(dissoc :font)
@ -88,17 +88,18 @@
[text-class (add-font-style :style opts)]
ts))))))
(defn text-input [{:keys [font style] :as opts
:or {font :default}} text]
(let [font (get-in platform-specific [:fonts (keyword font)])]
[text-input-class (merge
{:underline-color-android :transparent
:placeholder-text-color st/text2-color
:placeholder (i18n/label :t/type-a-message)
:value text}
(-> opts
(dissoc :font)
(assoc :style (merge style font))))]))
{:underline-color-android :transparent
:placeholder-text-color st/text2-color
:placeholder (i18n/label :t/type-a-message)
:value text}
(-> opts
(dissoc :font)
(assoc :style (merge style font))))]))
(defn icon
([n] (icon n st/icon-default))
@ -188,7 +189,8 @@
[view props])]
(vec (concat view-element children))))
(views/defview with-activity-indicator [{:keys [timeout style enabled?]} comp]
(views/defview with-activity-indicator
[{:keys [timeout style enabled? preview]} comp]
(views/letsubs
[loading (r/atom true)]
{:component-did-mount (fn []
@ -199,6 +201,33 @@
(reset! loading false))
timeout)))}
(if (and (not enabled?) @loading)
[view {:style style}
[activity-indicator {:animating true}]]
(or preview
[view {:style (or style {:justify-content :center
:align-items :center})}
[activity-indicator {:animating true}]])
comp)))
(defn navigation-wrapper
"Wraps component so that it will be shown only when current-screen is one of views"
[{:keys [component views current-view hide?]
:or {hide? false}}]
(let [current-view? (if (set? views)
(views current-view)
(= views current-view))
style (if current-view?
{:flex 1}
{:opacity 0
:flex 0})
component' (if (fn? component) [component] component)]
(when (or (not hide?) (and hide? current-view?))
(if hide?
component'
[view style (if (fn? component) [component] component)]))))
(defn with-empty-preview [comp]
[with-activity-indicator
{:preview [view {}]}
comp])

View File

@ -54,8 +54,28 @@
[react/view common.styles/flex
[status-bar.view/status-bar {:type (if (= view-id :wallet) :wallet :main)}]
[react/view common.styles/main-container
[(case view-id
:home home.views/home
:wallet wallet.views/wallet
:my-profile profile.views/my-profile)]
[tabs view-id]]]))
[react/with-activity-indicator
{:enabled? (= :home view-id)
:preview [react/view {}]}
[react/navigation-wrapper
{:component home.views/home
:views :home
:current-view view-id}]]
[react/with-activity-indicator
{:enabled? (= :wallet view-id)
:preview [react/view {}]}
[react/navigation-wrapper
{:component wallet.views/wallet
:views :wallet
:current-view view-id}]]
[react/with-activity-indicator
{:enabled? (= :my-profile view-id)
:preview [react/view {}]}
[react/navigation-wrapper
{:component profile.views/my-profile
:views :my-profile
:current-view view-id}]]
[tabs view-id]]]))

View File

@ -1,8 +1,8 @@
(ns status-im.ui.screens.views
(:require-macros [status-im.utils.views :refer [defview letsubs]])
(:require-macros [status-im.utils.views :refer [defview letsubs] :as views])
(:require [re-frame.core :refer [dispatch]]
[status-im.utils.platform :refer [android?]]
[status-im.ui.components.react :refer [view modal]]
[status-im.ui.components.react :refer [view modal] :as react]
[status-im.ui.components.styles :as common-styles]
[status-im.ui.screens.main-tabs.views :refer [main-tabs]]
[status-im.ui.components.context-menu :refer [menu-context]]
@ -60,10 +60,72 @@
current-view
:chat))
;;; defines hierarchy of views, when parent screen is opened children screens
;;; are pre-rendered, currently it is:
;;;
;;; root-
;;; |
;;; - main-tabs -
;;; | |
;;; - chat |
;;; wallet
;;; - wallet-send-transaction -
;;; | |
;;; | - choose-recipient
;;; | |
;;; | - wallet-transaction-sent
;;; |
;;; - transactions-history, unsigned-transactions
;;; |
;;; - wallet-request-transaction -
;;; | |
;;; | - choose-recipient
;;; |
;;; my-profile
;;; - edit-my-profile -
;;; |
;;; - profile-photo-capture
(views/compile-views root-view
[{:views #{:home :wallet :my-profile}
:component main-tabs}
{:view :chat
:hide? (not android?)
:component chat}
{:view :wallet-send-transaction
:parent :wallet
:component send-transaction}
{:view :wallet-request-transaction
:parent :wallet
:component request-transaction}
{:view :wallet-request-assets
:parent :wallet-request-transaction
:component wallet.components/request-assets}
{:view :choose-recipient
:parent :wallet-send-transaction
:component choose-recipient}
{:view :wallet-transaction-sent
:parent :wallet-send-transaction
:component transaction-sent}
{:views #{:transactions-history :unsigned-transactions}
:parent :wallet
:component wallet-transactions/transactions}
{:view :profile-photo-capture
:parent :my-profile
:component profile-photo-capture}])
(defview main []
(letsubs [signed-up? [:signed-up?]
view-id [:get :view-id]
modal-view [:get :modal]]
{:component-will-update (fn [] (react/dismiss-keyboard!))}
(when view-id
(let [current-view (validate-current-view view-id signed-up?)]
(let [component (case current-view
@ -109,7 +171,14 @@
(throw (str "Unknown view: " current-view)))]
[(if android? menu-context view) common-styles/flex
[view common-styles/flex
[component]
(if (and signed-up?
(#{:home :wallet :my-profile :chat :wallet-send-transaction
:choose-recipient :wallet-transaction-sent :transactions-history
:unsigned-transactions :wallet-request-transaction :edit-my-profile
:profile-photo-capture :wallet-request-assets}
current-view))
[root-view]
[component])
(when modal-view
[view common-styles/modal
[modal {:animation-type :slide

View File

@ -73,7 +73,8 @@
(defview choose-recipient []
(letsubs [camera-dimensions [:wallet.send/camera-dimensions]
camera-flashlight [:wallet.send/camera-flashlight]
camera-permitted? [:wallet.send/camera-permitted?]]
camera-permitted? [:wallet.send/camera-permitted?]
view [:get :view-id]]
[react/view {:style styles/wallet-container}
[status-bar/status-bar {:type :wallet}]
[toolbar-view camera-flashlight]
@ -83,12 +84,17 @@
(re-frame/dispatch [:wallet.send/set-camera-dimensions
{:width (.-width layout)
:height (.-height layout)}]))}
(when (or platform/android?
camera-permitted?)
[camera/camera {:style styles/preview
:aspect :fill
:captureAudio false
:torchMode (camera/set-torch camera-flashlight)
:onBarCodeRead #(re-frame/dispatch [:wallet/fill-request-from-url (camera/get-qr-code-data %) nil])}])
(when (and
(= view :choose-recipient)
(or platform/android?
camera-permitted?))
[react/with-activity-indicator
{}
[camera/camera {:style styles/preview
:aspect :fill
:captureAudio false
:torchMode (camera/set-torch camera-flashlight)
:onBarCodeRead #(re-frame/dispatch [:wallet/fill-request-from-url (camera/get-qr-code-data %) nil])}]])
[viewfinder camera-dimensions]]
[recipient-buttons]]))

View File

@ -58,7 +58,9 @@
[react/view components.styles/flex
[react/view styles/network-container
[react/view styles/qr-container
[qr-code amount symbol]]]
[react/with-activity-indicator
{:style wallet.styles/qr-code-preview}
[qr-code amount symbol]]]]
[react/view wallet.styles/amount-container
[components/amount-input
{:error amount-error

View File

@ -82,3 +82,9 @@
(def choose-asset-container
{:margin-top 16
:margin-horizontal 15})
(def qr-code-preview
{:width 256
:height 256
:justify-content :center
:align-items :center})

View File

@ -35,7 +35,8 @@
[toolbar/content-title (i18n/label :t/transactions)]
(case current-tab
:transactions-history [toolbar/actions [(history-action (not (all-checked? filter-data)))]]
:unsigned-transactions nil)]) ;; TODO (andrey) implement [unsigned-action unsigned-transactions-count]
:unsigned-transactions nil
nil)]) ;; TODO (andrey) implement [unsigned-action unsigned-transactions-count]
(defn action-buttons [{:keys [id] :as transaction}]
@ -197,7 +198,8 @@
[tabs current-tab]
[(case current-tab
:transactions-history history-list
:unsigned-transactions unsigned-list)]]))
:unsigned-transactions unsigned-list
react/view)]]))
(defn- pretty-print-asset [symbol amount]
(case symbol

View File

@ -66,3 +66,210 @@
(fn ~params
(let [~@vars-bindings]
~body))})))))))
(defn check-view [all {:keys [view views component hide? parent]}]
(let [parent (or parent :root)
views (or views #{view})
comp {:views views
:component component
:hide? hide?}]
(-> all
(assoc-in [:components views] comp)
(update-in [:view->children parent]
(fn [children]
(let [children (or children [])]
(conj children views))))
(update :view->components
(fn [view->components]
(reduce (fn [view->components view]
(assoc view->components view views))
view->components views))))))
(defn -build-tree [views]
(reduce check-view {:components {}
:view->components {}
:view->children {}} views))
(defn -get-all-views
[{:keys [view->children] :as config} component]
(let [children (reduce clojure.set/union (keep view->children component))]
(reduce clojure.set/union
(concat [component]
children
(map (fn [child]
(-get-all-views config child))
(reduce clojure.set/union
(map view->children component)))))))
(defn -get-grandchildren [{:keys [view->children] :as config} children]
(into {}
(filter
(fn [[_ children]]
(not (nil? children)))
(map (fn [child]
[child (get view->children child)])
(reduce clojure.set/union children)))))
(defn -generate-component
[{:keys [components view->children] :as config} view-sym component-name]
(let [component-config (get components component-name)
children (get view->children component-name)
grandchildren (-get-grandchildren config children)]
`[status-im.ui.components.react/view
{:flex
~(if (= :root component-name)
1
`(if (contains?
~(disj (-get-all-views config #{component-name}) component-name)
~view-sym)
1
0))}
~@(when component-config
`[status-im.ui.components.react/navigation-wrapper
~(assoc component-config :current-view view-sym)])
~@(map (fn [child]
`[status-im.ui.components.react/navigation-wrapper
~(assoc (get components child) :current-view view-sym)])
children)
~@(map (fn [[component-name children]]
`[status-im.ui.components.react/navigation-wrapper
{:component [status-im.ui.components.react/with-empty-preview
~(-generate-component config view-sym component-name)]
:views ~(conj
(reduce
clojure.set/union
(map (fn [child]
(-get-all-views config child))
children))
component-name)
:hide? true
:current-view ~view-sym}])
grandchildren)]))
(defn -compile-views [n views]
(let [view-sym (gensym "view-id")]
`(defview ~n []
(letsubs [~view-sym [:get :view-id]]
~(let [tree (-build-tree views)]
(-generate-component tree view-sym :root))))))
(defmacro compile-views
[n views]
(-compile-views n views))
(comment
(-compile-views
'root-view
'[{:views #{:home :wallet :my-profile}
:component main-tabs}
{:view :chat
:hide? (not android?)
:component chat}
{:view :wallet-send-transaction
:parent :wallet
:component send-transaction}
{:view :wallet-request-transaction
:parent :wallet
:component request-transaction}
{:view :choose-recipient
:parent :wallet-send-transaction
:component choose-recipient}
{:view :wallet-transaction-sent
:parent :wallet-send-transaction
:component transaction-sent}
{:views #{:transactions-history :unsigned-transactions}
:parent :wallet
:component wallet-transactions/transactions}
{:view :edit-my-profile
:parent :profile
:component edit-my-profile}])
(status-im.utils.views/defview
root-view
[]
(status-im.utils.views/letsubs
[view-id76826 [:get :view-id]]
[status-im.ui.components.react/view
{:flex 1}
[status-im.ui.components.react/navigation-wrapper
{:views #{:home :wallet :my-profile},
:component main-tabs,
:hide? nil,
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:views #{:chat},
:component chat,
:hide? (not android?),
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:hide? true,
:component [status-im.ui.components.react/with-empty-preview
[status-im.ui.components.react/view
{:flex (if
(clojure.core/contains?
#{:wallet-request-transaction
:wallet-send-transaction
:choose-recipient
:wallet-transaction-sent
:transactions-history
:unsigned-transactions}
view-id76826)
1
0)}
[status-im.ui.components.react/navigation-wrapper
{:views #{:wallet-send-transaction},
:component send-transaction,
:hide? nil,
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:views #{:wallet-request-transaction},
:component request-transaction,
:hide? nil,
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:views #{:transactions-history :unsigned-transactions},
:component wallet-transactions/transactions,
:hide? nil,
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:hide? true,
:component [status-im.ui.components.react/with-empty-preview
[status-im.ui.components.react/view
{:flex (if
(clojure.core/contains?
#{:choose-recipient
:wallet-transaction-sent}
view-id76826)
1
0)}
[status-im.ui.components.react/navigation-wrapper
{:views #{:choose-recipient},
:component choose-recipient,
:hide? nil,
:current-view view-id76826}]
[status-im.ui.components.react/navigation-wrapper
{:views #{:wallet-transaction-sent},
:component transaction-sent,
:hide? nil,
:current-view view-id76826}]]],
:current-view view-id76826,
:views #{:wallet-send-transaction
:choose-recipient
:wallet-transaction-sent}}]]],
:current-view view-id76826,
:views #{:wallet-request-transaction
:wallet
:wallet-send-transaction
:choose-recipient
:wallet-transaction-sent
:transactions-history
:unsigned-transactions}}]])))