Sync indicator (#312)
This commit is contained in:
parent
1128e5d089
commit
52b786dd25
|
@ -25,12 +25,12 @@
|
||||||
[status-im.chat.views.new-message :refer [chat-message-new]]
|
[status-im.chat.views.new-message :refer [chat-message-new]]
|
||||||
[status-im.chat.views.actions :refer [actions-view]]
|
[status-im.chat.views.actions :refer [actions-view]]
|
||||||
[status-im.chat.views.bottom-info :refer [bottom-info-view]]
|
[status-im.chat.views.bottom-info :refer [bottom-info-view]]
|
||||||
|
[status-im.chat.views.toolbar-content :refer [toolbar-content-view]]
|
||||||
[status-im.i18n :refer [label label-pluralize]]
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
[status-im.components.animation :as anim]
|
[status-im.components.animation :as anim]
|
||||||
[status-im.constants :refer [console-chat-id
|
[status-im.components.sync-state.offline :refer [offline-view]]
|
||||||
content-type-status]]
|
[status-im.constants :refer [content-type-status]]
|
||||||
[reagent.core :as r]
|
[reagent.core :as r]
|
||||||
[clojure.string :as str]
|
|
||||||
[cljs-time.core :as t]))
|
[cljs-time.core :as t]))
|
||||||
|
|
||||||
(defn contacts-by-identity [contacts]
|
(defn contacts-by-identity [contacts]
|
||||||
|
@ -82,44 +82,6 @@
|
||||||
(assoc :last-message (= (js/parseInt index) (dec messages-count))))]
|
(assoc :last-message (= (js/parseInt index) (dec messages-count))))]
|
||||||
(list-item [chat-message message])))
|
(list-item [chat-message message])))
|
||||||
|
|
||||||
(defn online-text [contact chat-id]
|
|
||||||
(cond
|
|
||||||
(= chat-id console-chat-id)
|
|
||||||
(label :t/available)
|
|
||||||
|
|
||||||
contact
|
|
||||||
(let [last-online (get contact :last-online)
|
|
||||||
last-online-date (time/to-date last-online)
|
|
||||||
now-date (t/now)]
|
|
||||||
(if (and (> last-online 0)
|
|
||||||
(<= last-online-date now-date))
|
|
||||||
(time/time-ago last-online-date)
|
|
||||||
(label :t/active-unknown)))
|
|
||||||
|
|
||||||
:else (label :t/active-unknown)))
|
|
||||||
|
|
||||||
(defn toolbar-content []
|
|
||||||
(let [{:keys [group-chat name contacts chat-id]} (subscribe [:chat-properties [:group-chat :name :contacts :chat-id]])
|
|
||||||
show-actions (subscribe [:chat-ui-props :show-actions?])
|
|
||||||
contact (subscribe [:get-in [:contacts @chat-id]])]
|
|
||||||
(fn []
|
|
||||||
[view (st/chat-name-view @show-actions)
|
|
||||||
[text {:style st/chat-name-text
|
|
||||||
:number-of-lines 1}
|
|
||||||
(if (str/blank? @name)
|
|
||||||
(label :t/user-anonymous)
|
|
||||||
(or @name (label :t/chat-name)))]
|
|
||||||
(if @group-chat
|
|
||||||
[view {:flexDirection :row}
|
|
||||||
[icon :group st/group-icon]
|
|
||||||
[text {:style st/members
|
|
||||||
:font :medium}
|
|
||||||
(let [cnt (inc (count @contacts))]
|
|
||||||
(label-pluralize cnt :t/members-active))]]
|
|
||||||
[text {:style st/last-activity
|
|
||||||
:font :default}
|
|
||||||
(online-text @contact @chat-id)])])))
|
|
||||||
|
|
||||||
(defn toolbar-action []
|
(defn toolbar-action []
|
||||||
(let [show-actions (subscribe [:chat-ui-props :show-actions?])]
|
(let [show-actions (subscribe [:chat-ui-props :show-actions?])]
|
||||||
(fn []
|
(fn []
|
||||||
|
@ -138,7 +100,7 @@
|
||||||
[view
|
[view
|
||||||
[status-bar]
|
[status-bar]
|
||||||
[toolbar {:hide-nav? show-actions
|
[toolbar {:hide-nav? show-actions
|
||||||
:custom-content [toolbar-content]
|
:custom-content [toolbar-content-view]
|
||||||
:custom-action [toolbar-action]
|
:custom-action [toolbar-action]
|
||||||
:style (get-in platform-specific [:component-styles :toolbar])}]])
|
:style (get-in platform-specific [:component-styles :toolbar])}]])
|
||||||
|
|
||||||
|
@ -222,4 +184,5 @@
|
||||||
(when @show-actions?
|
(when @show-actions?
|
||||||
[actions-view])
|
[actions-view])
|
||||||
(when @show-bottom-info?
|
(when @show-bottom-info?
|
||||||
[bottom-info-view])])})))
|
[bottom-info-view])
|
||||||
|
[offline-view {:top (get-in platform-specific [:component-styles :status-bar :default :height])}]])})))
|
||||||
|
|
|
@ -10,11 +10,14 @@
|
||||||
[status-im.components.toolbar.styles :refer [toolbar-background1]]))
|
[status-im.components.toolbar.styles :refer [toolbar-background1]]))
|
||||||
|
|
||||||
(def chat-view
|
(def chat-view
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:backgroundColor chat-background})
|
:background-color chat-background})
|
||||||
|
|
||||||
|
(def toolbar-container
|
||||||
|
{})
|
||||||
|
|
||||||
(defn messages-container [bottom]
|
(defn messages-container [bottom]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:padding-bottom bottom})
|
:padding-bottom bottom})
|
||||||
|
|
||||||
(def toolbar-view
|
(def toolbar-view
|
||||||
|
@ -26,6 +29,7 @@
|
||||||
(def action
|
(def action
|
||||||
{:width 56
|
{:width 56
|
||||||
:height 56
|
:height 56
|
||||||
|
:margin-top -2
|
||||||
:alignItems :center
|
:alignItems :center
|
||||||
:justifyContent :center})
|
:justifyContent :center})
|
||||||
|
|
||||||
|
@ -40,14 +44,13 @@
|
||||||
:height 14})
|
:height 14})
|
||||||
|
|
||||||
(defn chat-name-view [show-actions]
|
(defn chat-name-view [show-actions]
|
||||||
{:flex 1
|
{:flex 1
|
||||||
:marginLeft (if show-actions 16 0)
|
:margin-left (if show-actions 16 0)
|
||||||
:alignItems :flex-start
|
:align-items :flex-start
|
||||||
:justifyContent :center})
|
:justify-content :center})
|
||||||
|
|
||||||
(def chat-name-text
|
(def chat-name-text
|
||||||
{:marginTop -2.5
|
{:color text1-color
|
||||||
:color text1-color
|
|
||||||
:fontSize 16})
|
:fontSize 16})
|
||||||
|
|
||||||
(def group-icon
|
(def group-icon
|
||||||
|
@ -66,9 +69,13 @@
|
||||||
:color text2-color})
|
:color text2-color})
|
||||||
|
|
||||||
(def last-activity
|
(def last-activity
|
||||||
{:marginTop 1
|
{:margin-top 3
|
||||||
:color text2-color
|
:height 18})
|
||||||
:fontSize 12})
|
|
||||||
|
(def last-activity-text
|
||||||
|
{:color text2-color
|
||||||
|
:background-color :transparent
|
||||||
|
:font-size 12})
|
||||||
|
|
||||||
(defn actions-wrapper [status-bar-height]
|
(defn actions-wrapper [status-bar-height]
|
||||||
{:backgroundColor toolbar-background1
|
{:backgroundColor toolbar-background1
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
(ns status-im.chat.views.toolbar-content
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[clojure.string :as str]
|
||||||
|
[cljs-time.core :as t]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
text
|
||||||
|
icon]]
|
||||||
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
|
[status-im.chat.styles.screen :as st]
|
||||||
|
[status-im.components.refreshable-text.view :refer [refreshable-text]]
|
||||||
|
[status-im.utils.datetime :as time]
|
||||||
|
[status-im.constants :refer [console-chat-id]]))
|
||||||
|
|
||||||
|
(defn online-text [contact chat-id]
|
||||||
|
(cond
|
||||||
|
(= chat-id console-chat-id) (label :t/available)
|
||||||
|
contact (let [last-online (get contact :last-online)
|
||||||
|
last-online-date (time/to-date last-online)
|
||||||
|
now-date (t/now)]
|
||||||
|
(if (and (> last-online 0)
|
||||||
|
(<= last-online-date now-date))
|
||||||
|
(time/time-ago last-online-date)
|
||||||
|
(label :t/active-unknown)))
|
||||||
|
:else (label :t/active-unknown)))
|
||||||
|
|
||||||
|
(defn last-activity [{:keys [online-text sync-state]}]
|
||||||
|
[refreshable-text {:style st/last-activity
|
||||||
|
:text-style st/last-activity-text
|
||||||
|
:font :default
|
||||||
|
:value (case sync-state
|
||||||
|
:in-progress (label :t/sync-in-progress)
|
||||||
|
:synced (label :t/sync-synced)
|
||||||
|
online-text)}])
|
||||||
|
|
||||||
|
(defn group-last-activity [{:keys [contacts sync-state]}]
|
||||||
|
(if (or (= sync-state :in-progress)
|
||||||
|
(= sync-state :synced))
|
||||||
|
[last-activity {:sync-state sync-state}]
|
||||||
|
[view {:flex-direction :row}
|
||||||
|
[icon :group st/group-icon]
|
||||||
|
[text {:style st/members
|
||||||
|
:font :medium}
|
||||||
|
(let [cnt (inc (count contacts))]
|
||||||
|
(label-pluralize cnt :t/members-active))]]))
|
||||||
|
|
||||||
|
(defn toolbar-content-view []
|
||||||
|
(let [{:keys [group-chat
|
||||||
|
name
|
||||||
|
contacts
|
||||||
|
chat-id]} (subscribe [:chat-properties [:group-chat :name :contacts :chat-id]])
|
||||||
|
show-actions (subscribe [:chat-ui-props :show-actions?])
|
||||||
|
contact (subscribe [:get-in [:contacts @chat-id]])
|
||||||
|
sync-state (subscribe [:get :sync-state])]
|
||||||
|
(fn []
|
||||||
|
[view (st/chat-name-view @show-actions)
|
||||||
|
[text {:style st/chat-name-text
|
||||||
|
:number-of-lines 1}
|
||||||
|
(if (str/blank? @name)
|
||||||
|
(label :t/user-anonymous)
|
||||||
|
(or @name (label :t/chat-name)))]
|
||||||
|
(if @group-chat
|
||||||
|
[group-last-activity {:contacts @contacts
|
||||||
|
:sync-state @sync-state}]
|
||||||
|
[last-activity {:online-text (online-text @contact @chat-id)
|
||||||
|
:sync-state @sync-state}])])))
|
|
@ -24,6 +24,7 @@
|
||||||
[status-im.chats-list.styles :as st]
|
[status-im.chats-list.styles :as st]
|
||||||
[status-im.utils.platform :refer [platform-specific]]
|
[status-im.utils.platform :refer [platform-specific]]
|
||||||
[status-im.components.tabs.bottom-gradient :refer [bottom-gradient]]
|
[status-im.components.tabs.bottom-gradient :refer [bottom-gradient]]
|
||||||
|
[status-im.components.sync-state.offline :refer [offline-view]]
|
||||||
[status-im.components.tabs.styles :refer [tabs-height]]))
|
[status-im.components.tabs.styles :refer [tabs-height]]))
|
||||||
|
|
||||||
(defview chats-list-toolbar []
|
(defview chats-list-toolbar []
|
||||||
|
@ -86,4 +87,5 @@
|
||||||
:style st/list-container}]
|
:style st/list-container}]
|
||||||
(when (get-in platform-specific [:chats :action-button?])
|
(when (get-in platform-specific [:chats :action-button?])
|
||||||
[chats-action-button])
|
[chats-action-button])
|
||||||
[bottom-gradient]])
|
[bottom-gradient]
|
||||||
|
[offline-view]])
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
(ns status-im.components.refreshable-text.view
|
||||||
|
(:require [reagent.core :as r]
|
||||||
|
[reagent.impl.util :as ru]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
animated-view
|
||||||
|
text]]
|
||||||
|
[status-im.components.animation :as anim]))
|
||||||
|
|
||||||
|
(defn start-animation [{:keys [old-value-top
|
||||||
|
new-value-top
|
||||||
|
old-value-opacity
|
||||||
|
new-value-opacity]}]
|
||||||
|
(anim/start
|
||||||
|
(anim/timing old-value-top {:toValue 10
|
||||||
|
:duration 300}))
|
||||||
|
(anim/start
|
||||||
|
(anim/timing new-value-top {:toValue 0
|
||||||
|
:duration 300}))
|
||||||
|
(anim/start
|
||||||
|
(anim/timing old-value-opacity {:toValue 0
|
||||||
|
:duration 300}))
|
||||||
|
(anim/start
|
||||||
|
(anim/timing new-value-opacity {:toValue 1.0
|
||||||
|
:duration 300})))
|
||||||
|
|
||||||
|
(defn refreshable-text [{:keys [value]}]
|
||||||
|
(let [old-value-top (anim/create-value 0)
|
||||||
|
new-value-top (anim/create-value 0)
|
||||||
|
old-value-opacity (anim/create-value 0)
|
||||||
|
new-value-opacity (anim/create-value 1.0)
|
||||||
|
context {:old-value-top old-value-top
|
||||||
|
:new-value-top new-value-top
|
||||||
|
:old-value-opacity old-value-opacity
|
||||||
|
:new-value-opacity new-value-opacity}]
|
||||||
|
(r/create-class
|
||||||
|
{:get-initial-state
|
||||||
|
(fn []
|
||||||
|
{:old-value nil
|
||||||
|
:value value})
|
||||||
|
:component-will-update
|
||||||
|
(fn [component props]
|
||||||
|
(let [{new-value :value} (ru/extract-props props)
|
||||||
|
{old-value :value} (r/props component)]
|
||||||
|
(r/set-state component {:old-value old-value
|
||||||
|
:value new-value})
|
||||||
|
(anim/set-value old-value-top 0)
|
||||||
|
(anim/set-value new-value-top -10)
|
||||||
|
(anim/set-value old-value-opacity 1.0)
|
||||||
|
(anim/set-value new-value-opacity 0.0)
|
||||||
|
(start-animation context)))
|
||||||
|
:reagent-render
|
||||||
|
(fn [{:keys [style text-style font]}]
|
||||||
|
(let [component (r/current-component)
|
||||||
|
{:keys [old-value value]} (r/state component)]
|
||||||
|
[view style
|
||||||
|
[animated-view {:style {:position :absolute
|
||||||
|
:margin-top old-value-top
|
||||||
|
:opacity old-value-opacity}}
|
||||||
|
[text {:style text-style
|
||||||
|
:font font}
|
||||||
|
old-value]]
|
||||||
|
[animated-view {:style {:position :absolute
|
||||||
|
:margin-top new-value-top
|
||||||
|
:opacity new-value-opacity}}
|
||||||
|
[text {:style text-style
|
||||||
|
:font font}
|
||||||
|
value]]]))})))
|
|
@ -0,0 +1,119 @@
|
||||||
|
(ns status-im.components.sync-state.gradient
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[reagent.core :as r]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
text
|
||||||
|
animated-view
|
||||||
|
linear-gradient
|
||||||
|
get-dimensions]]
|
||||||
|
[status-im.components.sync-state.styles :as st]
|
||||||
|
[status-im.components.animation :as anim]
|
||||||
|
[taoensso.timbre :as log]))
|
||||||
|
|
||||||
|
(def gradient-animation-duration 700)
|
||||||
|
(def synced-disappear-delay 2500)
|
||||||
|
(def gradient-width 250)
|
||||||
|
(def in-progress-animation-delay 1500)
|
||||||
|
|
||||||
|
(def window-width (:width (get-dimensions "window")))
|
||||||
|
|
||||||
|
(declare start-gradient-reverse-animation)
|
||||||
|
|
||||||
|
(defn- start-gradient-animation [{:keys [gradient-position sync-state] :as context}]
|
||||||
|
(when (= @sync-state :in-progress)
|
||||||
|
(anim/start
|
||||||
|
(anim/timing gradient-position
|
||||||
|
{:toValue (- window-width (/ gradient-width 3))
|
||||||
|
:duration gradient-animation-duration})
|
||||||
|
(fn [_]
|
||||||
|
(start-gradient-reverse-animation context)))))
|
||||||
|
|
||||||
|
(defn- start-gradient-reverse-animation [{:keys [gradient-position sync-state] :as context}]
|
||||||
|
(when (= @sync-state :in-progress)
|
||||||
|
(anim/start
|
||||||
|
(anim/timing gradient-position
|
||||||
|
{:toValue (- 0 (* 2 (/ gradient-width 3)))
|
||||||
|
:duration gradient-animation-duration})
|
||||||
|
(fn [_]
|
||||||
|
(start-gradient-animation context)))))
|
||||||
|
|
||||||
|
(defn- start-synced-animation [{:keys [sync-state-opacity in-progress-opacity synced-opacity]}]
|
||||||
|
(anim/start
|
||||||
|
(anim/timing in-progress-opacity {:toValue 0.0
|
||||||
|
:duration 250}))
|
||||||
|
(anim/start
|
||||||
|
(anim/timing synced-opacity {:toValue 1.0
|
||||||
|
:duration 250})
|
||||||
|
(fn [_]
|
||||||
|
(anim/start
|
||||||
|
(anim/timing sync-state-opacity {:toValue 0.0
|
||||||
|
:duration 250
|
||||||
|
:delay synced-disappear-delay})
|
||||||
|
(fn [_]
|
||||||
|
(dispatch [:set :sync-state :done]))))))
|
||||||
|
|
||||||
|
(defn start-in-progress-animation [component]
|
||||||
|
(r/set-state component
|
||||||
|
{:pending? true
|
||||||
|
:animation (js/setTimeout
|
||||||
|
(fn []
|
||||||
|
(dispatch [:set :sync-state :in-progress])
|
||||||
|
(r/set-state component {:pending? false}))
|
||||||
|
in-progress-animation-delay)}))
|
||||||
|
|
||||||
|
(defn start-offline-animation [{:keys [sync-state-opacity]}]
|
||||||
|
(anim/start
|
||||||
|
(anim/timing sync-state-opacity {:toValue 0.0
|
||||||
|
:duration 250})))
|
||||||
|
|
||||||
|
(defn clear-pending-animation [component]
|
||||||
|
(let [{:keys [pending? animation]} (r/state component)]
|
||||||
|
(when pending?
|
||||||
|
(r/set-state component {:pending? false})
|
||||||
|
(js/clearTimeout animation))))
|
||||||
|
|
||||||
|
|
||||||
|
(defn sync-state-gradient-view []
|
||||||
|
(let [sync-state (subscribe [:get :sync-state])
|
||||||
|
gradient-position (anim/create-value 0)
|
||||||
|
sync-state-opacity (anim/create-value 0.0)
|
||||||
|
in-progress-opacity (anim/create-value 0.0)
|
||||||
|
synced-opacity (anim/create-value 0.0)
|
||||||
|
|
||||||
|
context {:sync-state sync-state
|
||||||
|
:gradient-position gradient-position
|
||||||
|
|
||||||
|
:sync-state-opacity sync-state-opacity
|
||||||
|
:in-progress-opacity in-progress-opacity
|
||||||
|
:synced-opacity synced-opacity}
|
||||||
|
on-update (fn [component _]
|
||||||
|
(case @sync-state
|
||||||
|
:pending (start-in-progress-animation component)
|
||||||
|
:in-progress (do
|
||||||
|
(anim/set-value gradient-position 0)
|
||||||
|
(anim/set-value sync-state-opacity 1)
|
||||||
|
(anim/set-value in-progress-opacity 1)
|
||||||
|
(anim/set-value synced-opacity 0)
|
||||||
|
(start-gradient-animation context))
|
||||||
|
:synced (start-synced-animation context)
|
||||||
|
:done (clear-pending-animation component)
|
||||||
|
:offline (do (clear-pending-animation component)
|
||||||
|
(start-offline-animation context))
|
||||||
|
(log/debug "Sync state:" @sync-state)))]
|
||||||
|
(r/create-class
|
||||||
|
{:component-did-mount
|
||||||
|
on-update
|
||||||
|
:component-did-update
|
||||||
|
on-update
|
||||||
|
:reagent-render
|
||||||
|
(fn []
|
||||||
|
[view st/sync-style-gradient
|
||||||
|
[animated-view {:style (st/loading-wrapper sync-state-opacity)}
|
||||||
|
[animated-view {:style (st/gradient-wrapper in-progress-opacity gradient-position)}
|
||||||
|
[linear-gradient {:colors ["#89b1fe" "#8b5fe4" "#8b5fe4" "#89b1fe"]
|
||||||
|
:start [0, 1]
|
||||||
|
:end [1, 1]
|
||||||
|
:locations [0 0.3 0.7 1]
|
||||||
|
:style (st/gradient gradient-width)}]]
|
||||||
|
(when (not= @sync-state :in-progress)
|
||||||
|
[animated-view {:style (st/synced-wrapper synced-opacity window-width)}])]])})))
|
|
@ -0,0 +1,38 @@
|
||||||
|
(ns status-im.components.sync-state.offline
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[reagent.core :as r]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
text
|
||||||
|
animated-view
|
||||||
|
linear-gradient
|
||||||
|
get-dimensions]]
|
||||||
|
[status-im.components.sync-state.styles :as st]
|
||||||
|
[status-im.components.animation :as anim]
|
||||||
|
[status-im.i18n :refer [label]]))
|
||||||
|
|
||||||
|
(def window-width (:width (get-dimensions "window")))
|
||||||
|
|
||||||
|
(defn start-offline-animation [offline-opacity]
|
||||||
|
(anim/start
|
||||||
|
(anim/timing offline-opacity {:toValue 1.0
|
||||||
|
:duration 250})))
|
||||||
|
|
||||||
|
(defn offline-view [_]
|
||||||
|
(let [sync-state (subscribe [:get :sync-state])
|
||||||
|
offline-opacity (anim/create-value 0.0)
|
||||||
|
on-update (fn [_ _]
|
||||||
|
(anim/set-value offline-opacity 0)
|
||||||
|
(when (= @sync-state :offline)
|
||||||
|
(start-offline-animation offline-opacity)))]
|
||||||
|
(r/create-class
|
||||||
|
{:component-did-mount
|
||||||
|
on-update
|
||||||
|
:component-did-update
|
||||||
|
on-update
|
||||||
|
:reagent-render
|
||||||
|
(fn [{:keys [top]}]
|
||||||
|
(when (= @sync-state :offline)
|
||||||
|
[animated-view {:style (st/offline-wrapper top offline-opacity window-width)}
|
||||||
|
[view
|
||||||
|
[text {:style st/offline-text}
|
||||||
|
(label :t/offline)]]]))})))
|
|
@ -0,0 +1,41 @@
|
||||||
|
(ns status-im.components.sync-state.styles)
|
||||||
|
|
||||||
|
(def sync-style-gradient
|
||||||
|
{:position :relative
|
||||||
|
:height 0
|
||||||
|
:top -2})
|
||||||
|
|
||||||
|
(defn loading-wrapper [opacity]
|
||||||
|
{:background-color "#89b1fe"
|
||||||
|
:opacity opacity
|
||||||
|
:height 2})
|
||||||
|
|
||||||
|
(defn gradient-wrapper [in-progress-opacity position]
|
||||||
|
{:position :absolute
|
||||||
|
:left position
|
||||||
|
:opacity in-progress-opacity})
|
||||||
|
|
||||||
|
(defn gradient [width]
|
||||||
|
{:width width
|
||||||
|
:height 2})
|
||||||
|
|
||||||
|
(defn synced-wrapper [opacity window-width]
|
||||||
|
{:opacity opacity
|
||||||
|
:position :absolute
|
||||||
|
:width window-width
|
||||||
|
:background-color "#5fc48d"
|
||||||
|
:height 2})
|
||||||
|
|
||||||
|
(defn offline-wrapper [top opacity window-width]
|
||||||
|
{:opacity opacity
|
||||||
|
:width window-width
|
||||||
|
:top (+ 56 top)
|
||||||
|
:position :absolute
|
||||||
|
:background-color "#828b92cc"
|
||||||
|
:height 35})
|
||||||
|
|
||||||
|
(def offline-text
|
||||||
|
{:text-align :center
|
||||||
|
:color :white
|
||||||
|
:font-size 14
|
||||||
|
:top 8})
|
|
@ -13,12 +13,14 @@
|
||||||
(def toolbar-gradient
|
(def toolbar-gradient
|
||||||
{:height 4})
|
{:height 4})
|
||||||
|
|
||||||
(defn toolbar [background-color]
|
(defn toolbar-wrapper [background-color]
|
||||||
{:flexDirection :row
|
{:backgroundColor (or background-color toolbar-background1)
|
||||||
:backgroundColor (or background-color toolbar-background1)
|
|
||||||
:height toolbar-height
|
|
||||||
:elevation 2})
|
:elevation 2})
|
||||||
|
|
||||||
|
(def toolbar
|
||||||
|
{:flex-direction :row
|
||||||
|
:height toolbar-height})
|
||||||
|
|
||||||
(defn toolbar-nav-actions-container [actions]
|
(defn toolbar-nav-actions-container [actions]
|
||||||
{:width (if (and actions (> (count actions) 0))
|
{:width (if (and actions (> (count actions) 0))
|
||||||
(-> (+ toolbar-icon-width toolbar-icon-spacing)
|
(-> (+ toolbar-icon-width toolbar-icon-spacing)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
text
|
text
|
||||||
image
|
image
|
||||||
touchable-highlight]]
|
touchable-highlight]]
|
||||||
|
[status-im.components.sync-state.gradient :refer [sync-state-gradient-view]]
|
||||||
[status-im.components.styles :refer [icon-back]]
|
[status-im.components.styles :refer [icon-back]]
|
||||||
[status-im.components.toolbar.styles :as st]))
|
[status-im.components.toolbar.styles :as st]))
|
||||||
|
|
||||||
|
@ -17,30 +18,32 @@
|
||||||
background-color :background-color
|
background-color :background-color
|
||||||
custom-content :custom-content
|
custom-content :custom-content
|
||||||
style :style}]
|
style :style}]
|
||||||
(let [style (merge (st/toolbar background-color) style)]
|
(let [style (merge (st/toolbar-wrapper background-color) style)]
|
||||||
[view {:style style}
|
[view {:style style}
|
||||||
[view (st/toolbar-nav-actions-container actions)
|
[view st/toolbar
|
||||||
(when (not hide-nav?)
|
[view (st/toolbar-nav-actions-container actions)
|
||||||
(if nav-action
|
(when (not hide-nav?)
|
||||||
[touchable-highlight {:on-press (:handler nav-action)}
|
(if nav-action
|
||||||
[view st/toolbar-nav-action
|
[touchable-highlight {:on-press (:handler nav-action)}
|
||||||
[image (:image nav-action)]]]
|
[view st/toolbar-nav-action
|
||||||
[touchable-highlight {:on-press #(dispatch [:navigate-back])
|
[image (:image nav-action)]]]
|
||||||
:accessibility-label :navigate-back}
|
[touchable-highlight {:on-press #(dispatch [:navigate-back])
|
||||||
[view st/toolbar-nav-action
|
:accessibility-label :navigate-back}
|
||||||
[image {:source {:uri :icon_back}
|
[view st/toolbar-nav-action
|
||||||
:style icon-back}]]]))]
|
[image {:source {:uri :icon_back}
|
||||||
(or custom-content
|
:style icon-back}]]]))]
|
||||||
[view {:style st/toolbar-title-container}
|
(or custom-content
|
||||||
[text {:style st/toolbar-title-text}
|
[view {:style st/toolbar-title-container}
|
||||||
title]])
|
[text {:style st/toolbar-title-text}
|
||||||
[view st/toolbar-actions-container
|
title]])
|
||||||
(if actions
|
[view st/toolbar-actions-container
|
||||||
(for [{action-image :image
|
(if actions
|
||||||
action-handler :handler} actions]
|
(for [{action-image :image
|
||||||
^{:key (str "action-" action-image)}
|
action-handler :handler} actions]
|
||||||
[touchable-highlight {:on-press action-handler}
|
^{:key (str "action-" action-image)}
|
||||||
[view st/toolbar-action
|
[touchable-highlight {:on-press action-handler}
|
||||||
[image action-image]]])
|
[view st/toolbar-action
|
||||||
custom-action)]]))
|
[image action-image]]])
|
||||||
|
custom-action)]]
|
||||||
|
[sync-state-gradient-view]]))
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
(def response-suggesstion-resize-duration 100)
|
(def response-suggesstion-resize-duration 100)
|
||||||
|
|
||||||
(def default-number-of-messages 20)
|
(def default-number-of-messages 20)
|
||||||
|
(def blocks-per-hour 120)
|
||||||
|
|
||||||
(def default-number-of-discovery-search-results 20)
|
(def default-number-of-discovery-search-results 20)
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,10 @@
|
||||||
:keyboard-height 0
|
:keyboard-height 0
|
||||||
:animations {;; todo clear this
|
:animations {;; todo clear this
|
||||||
:tabs-bar-value (anim/create-value 0)}
|
:tabs-bar-value (anim/create-value 0)}
|
||||||
:loading-allowed true})
|
:loading-allowed true
|
||||||
|
|
||||||
|
:sync-state :done
|
||||||
|
:sync-listener nil})
|
||||||
|
|
||||||
(defn chat-staged-commands-path [chat-id]
|
(defn chat-staged-commands-path [chat-id]
|
||||||
[:chats chat-id :staged-commands])
|
[:chats chat-id :staged-commands])
|
||||||
|
|
|
@ -57,6 +57,7 @@
|
||||||
(fn [_ [_ address]]
|
(fn [_ [_ address]]
|
||||||
(dispatch [:initialize-account-db])
|
(dispatch [:initialize-account-db])
|
||||||
(dispatch [:initialize-protocol address])
|
(dispatch [:initialize-protocol address])
|
||||||
|
(dispatch [:initialize-sync-listener])
|
||||||
(dispatch [:initialize-chats])
|
(dispatch [:initialize-chats])
|
||||||
(dispatch [:load-contacts])
|
(dispatch [:load-contacts])
|
||||||
(dispatch [:init-chat])
|
(dispatch [:init-chat])
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
[status-im.data-store.pending-messages :as pending-messages]
|
[status-im.data-store.pending-messages :as pending-messages]
|
||||||
[status-im.data-store.chats :as chats]
|
[status-im.data-store.chats :as chats]
|
||||||
[status-im.protocol.core :as protocol]
|
[status-im.protocol.core :as protocol]
|
||||||
[status-im.constants :refer [text-content-type]]
|
[status-im.constants :refer [text-content-type
|
||||||
|
blocks-per-hour]]
|
||||||
[status-im.i18n :refer [label]]
|
[status-im.i18n :refer [label]]
|
||||||
[status-im.utils.random :as random]
|
[status-im.utils.random :as random]
|
||||||
[taoensso.timbre :as log :refer-macros [debug]]))
|
[taoensso.timbre :as log :refer-macros [debug]]))
|
||||||
|
@ -43,6 +44,32 @@
|
||||||
(contacts/get-all))})]
|
(contacts/get-all))})]
|
||||||
(assoc db :web3 w3)))))
|
(assoc db :web3 w3)))))
|
||||||
|
|
||||||
|
(register-handler :update-sync-state
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [{:keys [sync-state]} [_ error sync]]
|
||||||
|
(let [{:keys [highestBlock currentBlock]} (js->clj sync :keywordize-keys true)
|
||||||
|
syncing? (> (- highestBlock currentBlock) blocks-per-hour)
|
||||||
|
new-state (cond
|
||||||
|
error :offline
|
||||||
|
syncing? (if (= sync-state :done)
|
||||||
|
:pending
|
||||||
|
:in-progress)
|
||||||
|
:else (if (or (= sync-state :done)
|
||||||
|
(= sync-state :pending))
|
||||||
|
:done
|
||||||
|
:synced))]
|
||||||
|
(when (not= sync-state new-state)
|
||||||
|
(dispatch [:set :sync-state new-state]))))))
|
||||||
|
|
||||||
|
(register-handler :initialize-sync-listener
|
||||||
|
(fn [{:keys [web3 sync-listener] :as db} _]
|
||||||
|
(when sync-listener
|
||||||
|
(.stopWatching sync-listener))
|
||||||
|
(->> (.isSyncing (.-eth web3)
|
||||||
|
(fn [error sync]
|
||||||
|
(dispatch [:update-sync-state error sync])))
|
||||||
|
(assoc db :sync-listener))))
|
||||||
|
|
||||||
(register-handler :incoming-message
|
(register-handler :incoming-message
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [_ [_ type {:keys [payload] :as message}]]
|
(fn [_ [_ type {:keys [payload] :as message}]]
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
:not-implemented "!not implemented"
|
:not-implemented "!not implemented"
|
||||||
:chat-name "Chat name"
|
:chat-name "Chat name"
|
||||||
:notifications-title "Notifications and sounds"
|
:notifications-title "Notifications and sounds"
|
||||||
|
:offline "Offline"
|
||||||
|
|
||||||
;drawer
|
;drawer
|
||||||
:invite-friends "Invite friends"
|
:invite-friends "Invite friends"
|
||||||
|
@ -23,11 +24,15 @@
|
||||||
:members-active {:one "1 member, 1 active"
|
:members-active {:one "1 member, 1 active"
|
||||||
:other "{{count}} members, {{count}} active"
|
:other "{{count}} members, {{count}} active"
|
||||||
:zero "no members"}
|
:zero "no members"}
|
||||||
:active-online "online"
|
:active-online "Online"
|
||||||
:active-unknown "unknown"
|
:active-unknown "Unknown"
|
||||||
:available "available"
|
:available "Available"
|
||||||
:no-messages "No messages"
|
:no-messages "No messages"
|
||||||
|
|
||||||
|
;sync
|
||||||
|
:sync-in-progress "Syncing..."
|
||||||
|
:sync-synced "In sync"
|
||||||
|
|
||||||
;messages
|
;messages
|
||||||
:status-sending "Sending"
|
:status-sending "Sending"
|
||||||
:status-pending "Sending"
|
:status-pending "Sending"
|
||||||
|
|
Loading…
Reference in New Issue