[#7684] Relocate and change menu for "+" icon on home/chat screen

This commit is contained in:
Andrey Shovkoplyas 2019-03-18 15:01:09 +01:00
parent 8d9664581f
commit ad4c6ce94f
No known key found for this signature in database
GPG Key ID: EAAB7C8622D860A4
15 changed files with 350 additions and 298 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

@ -107,13 +107,14 @@
(defn account-set-name [{{:accounts/keys [create] :as db} :db now :now :as cofx}] (defn account-set-name [{{:accounts/keys [create] :as db} :db now :now :as cofx}]
(fx/merge cofx (fx/merge cofx
{:db (assoc db :accounts/create {:show-welcome? true}) {:db db
:notifications/request-notifications-permissions nil :notifications/request-notifications-permissions nil
:dispatch [:navigate-to :home]} :dispatch-n [[:navigate-to :home]
[:navigate-to :welcome]]}
;; We set last updated as we are actually changing a field, ;; We set last updated as we are actually changing a field,
;; unlike on recovery where the name is not set ;; unlike on recovery where the name is not set
(accounts.update/account-update {:last-updated now (accounts.update/account-update {:last-updated now
:name (:name create)} {}) :name (:name create)} {})
(mobile-network/on-network-status-change))) (mobile-network/on-network-status-change)))
(fx/defn next-step (fx/defn next-step

View File

@ -52,8 +52,7 @@
[status-im.node.core :as node] [status-im.node.core :as node]
[status-im.stickers.core :as stickers] [status-im.stickers.core :as stickers]
[status-im.utils.config :as config] [status-im.utils.config :as config]
[status-im.constants :as constants] [status-im.ui.components.bottom-sheet.core :as bottom-sheet]))
[status-im.utils.ethereum.core :as ethereum]))
;; init module ;; init module
@ -1801,3 +1800,15 @@
:tribute-to-talk.ui/remove-pressed :tribute-to-talk.ui/remove-pressed
(fn [cofx _] (fn [cofx _]
(tribute-to-talk/remove cofx))) (tribute-to-talk/remove cofx)))
(handlers/register-handler-fx
:bottom-sheet/show-sheet
(fn [cofx [_ view]]
(bottom-sheet/show-bottom-sheet
cofx
{:view view})))
(handlers/register-handler-fx
:bottom-sheet/hide-sheet
(fn [cofx _]
(bottom-sheet/hide-bottom-sheet cofx)))

View File

@ -2,10 +2,12 @@
(:require [status-im.ui.components.action-button.styles :as st] (:require [status-im.ui.components.action-button.styles :as st]
[status-im.ui.components.common.common :refer [list-separator]] [status-im.ui.components.common.common :refer [list-separator]]
[status-im.ui.components.icons.vector-icons :as vi] [status-im.ui.components.icons.vector-icons :as vi]
[status-im.ui.components.react :as rn])) [status-im.ui.components.react :as rn]
[status-im.ui.components.colors :as colors]))
(defn action-button [{:keys [label accessibility-label icon icon-opts on-press label-style cyrcle-color]}] (defn action-button [{:keys [label accessibility-label icon icon-opts on-press label-style cyrcle-color]}]
[rn/touchable-highlight (merge {:on-press on-press} [rn/touchable-highlight (merge {:on-press on-press
:underlay-color (colors/alpha colors/gray 0.15)}
(when accessibility-label (when accessibility-label
{:accessibility-label accessibility-label})) {:accessibility-label accessibility-label}))
[rn/view {:style st/action-button} [rn/view {:style st/action-button}

View File

@ -1,15 +1,14 @@
(ns status-im.ui.components.action-button.styles (ns status-im.ui.components.action-button.styles
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.ui.components.styles :as styles] (:require [status-im.ui.components.colors :as colors]))
[status-im.ui.components.colors :as colors]))
(defstyle action-button (defstyle action-button
{:padding-left 16 {:padding-left 16
:flex-direction :row :flex-direction :row
:align-items :center :align-items :center
:ios {:height 63} :ios {:height 64}
:desktop {:height 50} :desktop {:height 50}
:android {:height 56}}) :android {:height 64}})
(defnstyle action-button-icon-container [circle-color] (defnstyle action-button-icon-container [circle-color]
{:border-radius 50 {:border-radius 50
@ -28,8 +27,7 @@
(defstyle actions-list (defstyle actions-list
{:background-color colors/white {:background-color colors/white
:android {:padding-top 8 :flex 1})
:padding-bottom 8}})
(def action-button-label-disabled (def action-button-label-disabled
(merge action-button-label (merge action-button-label

View File

@ -35,7 +35,6 @@
:align-self :stretch :align-self :stretch
:transform [{:translateY bottom-value}] :transform [{:translateY bottom-value}]
:justify-content :flex-start :justify-content :flex-start
:align-items :center
:padding-bottom bottom-padding}) :padding-bottom bottom-padding})
(def content-header (def content-header

View File

@ -0,0 +1,140 @@
(ns status-im.ui.screens.home.filter.views
(:require [status-im.ui.components.list.views :as list]
[status-im.ui.screens.home.styles :as styles]
[status-im.ui.components.react :as react]
[status-im.i18n :as i18n]
[status-im.ui.components.colors :as colors]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.utils.utils :as utils]
[status-im.ui.components.animation :as animation]
[reagent.core :as reagent]
[re-frame.core :as re-frame]
[status-im.ui.components.icons.vector-icons :as icons]))
(defn search-input [_ {:keys [on-cancel on-focus on-change]}]
(let [input-is-focused? (reagent/atom false)
input-ref (reagent/atom nil)]
(fn [search-filter]
(let [show-cancel? (or @input-is-focused?
search-filter)]
[react/view {:style styles/search-container}
[react/view {:style styles/search-input-container}
[icons/icon :main-icons/search {:color colors/gray
:container-style {:margin-left 6
:margin-right 2}}]
[react/text-input {:placeholder (i18n/label :t/search)
:blur-on-submit true
:multiline false
:ref #(reset! input-ref %)
:style styles/search-input
:default-value search-filter
:on-focus #(do
(when on-focus
(on-focus search-filter))
(reset! input-is-focused? true))
:on-change (fn [e]
(let [native-event (.-nativeEvent e)
text (.-text native-event)]
(when on-change
(on-change text))))}]]
(when show-cancel?
[react/touchable-highlight
{:on-press #(do
(when on-cancel
(on-cancel))
(.blur @input-ref)
(reset! input-is-focused? false))
:style {:margin-left 16}}
[react/text {:style {:color colors/blue
:font-size 15}}
(i18n/label :t/cancel)]])]))))
(defonce search-input-state
(reagent/atom {:show? false
:height (animation/create-value 0)}))
(defn show-search!
[]
(swap! search-input-state assoc :show? true)
(animation/start
(animation/timing (:height @search-input-state)
{:toValue styles/search-input-height
:duration 350
:easing (.out (animation/easing)
(.-quad (animation/easing)))})))
(defn hide-search!
[]
(utils/set-timeout
#(swap! search-input-state assoc :show? false)
350)
(animation/start
(animation/timing (:height @search-input-state)
{:toValue 0
:duration 350
:easing (.in (animation/easing)
(.-quad (animation/easing)))})))
(defn set-search-state-visible!
[visible?]
(swap! search-input-state assoc :show? visible?)
(animation/set-value (:height @search-input-state)
(if visible?
styles/search-input-height
0)))
(defn animated-search-input
[search-filter]
(reagent/create-class
{:component-will-unmount
#(set-search-state-visible! false)
:component-did-mount
#(when search-filter
(set-search-state-visible! true))
:reagent-render
(fn [search-filter]
(let [{:keys [show? height]} @search-input-state]
(when (or show?
search-filter)
[react/animated-view
{:style {:height height}}
[search-input search-filter
{:on-cancel #(do
(re-frame/dispatch [:search/filter-changed nil])
(hide-search!))
:on-focus (fn [search-filter]
(when-not search-filter
(re-frame/dispatch [:search/filter-changed ""])))
:on-change (fn [text]
(re-frame/dispatch [:search/filter-changed text]))}]])))}))
(defn home-filtered-items-list
[chats]
[list/section-list
{:sections [{:title :t/chats
:data chats}
{:title :t/messages
:data []}]
:key-fn first
;; true by default on iOS
:stickySectionHeadersEnabled false
:render-section-header-fn (fn [{:keys [title data]}]
[react/view {:style {:height 40}}
[react/text {:style styles/filter-section-title}
(i18n/label title)]])
:render-section-footer-f (fn [{:keys [title data]}]
(when (empty? data)
[list/big-list-item
{:text (i18n/label (if (= title "messages")
:t/messages-search-coming-soon
:t/no-result))
:text-color colors/gray
:hide-chevron? true
:action-fn #()
:icon (case title
"messages" :main-icons/private-chat
"browser" :main-icons/browser
"chats" :main-icons/message)
:icon-color colors/gray}]))
:render-fn (fn [home-item]
[inner-item/home-list-item home-item])}])

View File

@ -0,0 +1,54 @@
(ns status-im.ui.screens.home.sheet.views
(:require [re-frame.core :as re-frame]
[status-im.i18n :as i18n]
[status-im.ui.components.action-button.action-button :as action-button]
[status-im.ui.components.action-button.styles :as action-button.styles]
[status-im.ui.components.colors :as colors]
[status-im.ui.components.list-selection :as list-selection]
[status-im.ui.components.react :as react]))
(defn hide-sheet-and-dispatch [event]
(re-frame/dispatch [:bottom-sheet/hide-sheet])
(re-frame/dispatch event))
(defn add-new-view []
[react/view {:flex 1 :flex-direction :row}
[react/view action-button.styles/actions-list
[action-button/action-button
{:label (i18n/label :t/start-new-chat)
:accessibility-label :start-1-1-chat-button
:icon :main-icons/private-chat
:icon-opts {:color colors/blue}
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-chat])}]
[action-button/action-button
{:label (i18n/label :t/start-group-chat)
:accessibility-label :start-group-chat-button
:icon :main-icons/group-chat
:icon-opts {:color colors/blue}
:on-press #(hide-sheet-and-dispatch [:contact.ui/start-group-chat-pressed])}]
[action-button/action-button
{:label (i18n/label :t/new-public-group-chat)
:accessibility-label :join-public-chat-button
:icon :main-icons/public-chat
:icon-opts {:color colors/blue}
:on-press #(hide-sheet-and-dispatch [:navigate-to :new-public-chat])}]
[action-button/action-button
{:label (i18n/label :t/scan-qr)
:accessibility-label :scan-qr-code-button
:icon :main-icons/qr
:icon-opts {:color colors/blue}
:on-press #(hide-sheet-and-dispatch [:qr-scanner.ui/scan-qr-code-pressed
{:toolbar-title (i18n/label :t/scan-qr)}
:handle-qr-code])}]
[action-button/action-button
{:label (i18n/label :t/invite-friends)
:accessibility-label :invite-friends-button
:icon :main-icons/share
:icon-opts {:color colors/blue}
:on-press #(do
(re-frame/dispatch [:bottom-sheet/hide-sheet])
(list-selection/open-share {:message (i18n/label :t/get-status-at)}))}]]])
(def add-new
{:content add-new-view
:content-height 320})

View File

@ -1,7 +1,8 @@
(ns status-im.ui.screens.home.styles (ns status-im.ui.screens.home.styles
(:require-macros [status-im.utils.styles :refer [defstyle defnstyle]]) (:require-macros [status-im.utils.styles :refer [defstyle defnstyle]])
(:require [status-im.ui.components.colors :as colors] (:require [status-im.ui.components.colors :as colors]
[status-im.utils.platform :as platform])) [status-im.utils.platform :as platform]
[status-im.ui.components.bottom-bar.styles :as tabs.styles]))
(defn toolbar [] (defn toolbar []
{:background-color colors/white}) {:background-color colors/white})
@ -76,14 +77,14 @@
:height 26}}) :height 26}})
(defstyle private-group-icon-container (defstyle private-group-icon-container
{:align-items :center {:align-items :center
:justify-content :center :justify-content :center
:margin-right 6}) :margin-right 6})
(defstyle public-group-icon-container (defstyle public-group-icon-container
{:align-items :center {:align-items :center
:justify-content :center :justify-content :center
:margin-right 6}) :margin-right 6})
(def last-message-container (def last-message-container
{:flex-shrink 1}) {:flex-shrink 1})
@ -115,8 +116,8 @@
:border-radius 8}) :border-radius 8})
(def search-input (def search-input
(merge {:flex 1 (merge {:flex 1
:font-size 15} :font-size 15}
(when platform/android? (when platform/android?
{:line-height 22 {:line-height 22
:margin 0 :margin 0
@ -168,55 +169,51 @@
:margin-horizontal 34}) :margin-horizontal 34})
(def no-chats-text (def no-chats-text
{:line-height 21 {:line-height 22
:text-align :center :font-size 15
:color colors/gray}) :text-align :center
:color colors/gray})
(def welcome-view (def welcome-view
{:flex 1}) {:flex 1})
(defstyle welcome-image-container (def welcome-image-container
{:align-items :center {:align-items :center
:android {:margin-top 38} :margin-top 42})
:ios {:margin-top 42}})
(def welcome-image (def welcome-text
{:width 320
:height 278})
(defstyle welcome-text
{:line-height 28 {:line-height 28
:font-size 22 :font-size 22
:font-weight :bold :font-weight :bold
:android {:margin-top 22} :margin-top 32
:ios {:margin-top 96}
:text-align :center :text-align :center
:color colors/black}) :color colors/black})
(defstyle welcome-text-description (def welcome-text-description
{:line-height 21 {:line-height 22
:margin-top 8 :font-size 15
:android {:margin-bottom 82} :margin-top 8
:ios {:margin-bottom 32} :text-align :center
:text-align :center :margin-horizontal 32
:color colors/gray}) :color colors/gray})
(def toolbar-logo
{:size 40
:icon-size 17})
(def action-button-container (def action-button-container
{:position :absolute {:position :absolute
:bottom 16 :align-items :center
:right 16}) :bottom (+ tabs.styles/tabs-diff 6)
:right 0
:left 0})
(def action-button (def action-button
{:width 56 {:margin 10
:height 56 :width 40
:height 40
:background-color colors/blue :background-color colors/blue
:border-radius 28 :border-radius 20
:align-items :center :align-items :center
:justify-content :center}) :justify-content :center
:shadow-offset {:width 0 :height 1}
(def spinner-container :shadow-radius 6
{:margin-right 10}) :shadow-opacity 1
:shadow-color "rgba(0, 12, 63, 0.2)"
:elevation 2})

View File

@ -3,239 +3,73 @@
[reagent.core :as reagent] [reagent.core :as reagent]
[status-im.i18n :as i18n] [status-im.i18n :as i18n]
[status-im.react-native.resources :as resources] [status-im.react-native.resources :as resources]
[status-im.ui.components.animation :as animation]
[status-im.ui.components.colors :as colors] [status-im.ui.components.colors :as colors]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.connectivity.view :as connectivity] [status-im.ui.components.connectivity.view :as connectivity]
[status-im.ui.components.icons.vector-icons :as icons] [status-im.ui.components.icons.vector-icons :as icons]
[status-im.ui.components.list.views :as list] [status-im.ui.components.list.views :as list]
[status-im.ui.components.react :as react] [status-im.ui.components.react :as react]
[status-im.ui.components.status-bar.view :as status-bar] [status-im.ui.components.status-bar.view :as status-bar]
[status-im.ui.components.toolbar.actions :as toolbar.actions]
[status-im.ui.components.toolbar.view :as toolbar] [status-im.ui.components.toolbar.view :as toolbar]
[status-im.ui.screens.home.styles :as styles] [status-im.ui.screens.home.styles :as styles]
[status-im.ui.screens.home.views.inner-item :as inner-item] [status-im.ui.screens.home.filter.views :as filter.views]
[status-im.utils.platform :as platform]
[status-im.utils.utils :as utils] [status-im.utils.utils :as utils]
[status-im.ui.components.bottom-bar.styles :as tabs.styles]) [status-im.ui.components.bottom-bar.styles :as tabs.styles]
[status-im.ui.screens.home.views.inner-item :as inner-item]
[status-im.ui.components.common.common :as components.common]
[status-im.ui.components.list-selection :as list-selection])
(:require-macros [status-im.utils.views :as views])) (:require-macros [status-im.utils.views :as views]))
(defn- toolbar [show-welcome? show-sync-state sync-state latest-block-number logged-in?] (views/defview les-debug-info []
(when-not (and show-welcome? (views/letsubs [sync-state [:chain-sync-state]
platform/android?) latest-block-number [:latest-block-number]
[toolbar/toolbar nil nil rpc-network? [:current-network-uses-rpc?]
(when-not show-welcome? network-initialized? [:current-network-initialized?]]
(if show-sync-state (when (and network-initialized? (not rpc-network?))
[react/view {:style styles/sync-wrapper} [react/view {:style styles/sync-wrapper}
[components.common/logo styles/toolbar-logo] [react/touchable-highlight {:on-press #(re-frame/dispatch [:home.ui/sync-info-pressed])}
[react/text {:style styles/sync-info}
(str "LES: 'latest' #" latest-block-number "\n"
(if sync-state
(str "syncing " (:currentBlock sync-state) " of " (:highestBlock sync-state) " blocks...")
(str "not syncing")))]]])))
[react/touchable-highlight {:accessibility-label :new-chat-button (defn welcome []
:on-press #(re-frame/dispatch [:home.ui/sync-info-pressed])} [react/view {:style styles/welcome-view}
[react/text {:style styles/sync-info} [react/view {:flex 1}]
(str "LES: 'latest' #" latest-block-number "\n" [status-bar/status-bar {:type :main}]
(if sync-state [react/view {:style styles/welcome-image-container}
(str "syncing " (:currentBlock sync-state) " of " (:highestBlock sync-state) " blocks...") [components.common/image-contain
(str "not syncing")))]]] {:container-style {}}
[components.common/logo styles/toolbar-logo])) {:image (:welcome-image resources/ui) :width 750 :height 556}]]
(cond [react/i18n-text {:style styles/welcome-text :key :welcome-to-status}]
(and platform/ios? [react/view
logged-in?) [react/i18n-text {:style styles/welcome-text-description
[toolbar/actions :key :welcome-to-status-description}]]
[(-> (toolbar.actions/add true #(re-frame/dispatch [:navigate-to :new])) [react/view {:flex 1}]
(assoc-in [:icon-opts :accessibility-label] :new-chat-button))]] [react/view {:align-items :center :margin-bottom 52}
platform/ios? [components.common/button {:on-press #(re-frame/dispatch [:navigate-back])
[react/view {:style styles/spinner-container} :label (i18n/label :t/get-started)}]]])
[react/activity-indicator {:color colors/blue
:animating true}]])]))
(defn- home-action-button [logged-in?] (defn home-empty-view []
[react/view styles/action-button-container
[react/touchable-highlight {:accessibility-label :new-chat-button
:on-press (when logged-in? #(re-frame/dispatch [:navigate-to :new]))}
[react/view styles/action-button
(if-not logged-in?
[react/activity-indicator {:color :white
:animating true}]
[icons/icon :main-icons/add {:color :white}])]]])
(defn home-list-item [[home-item-id home-item]]
(let [delete-action (if (and (:group-chat home-item)
(not (:public? home-item)))
:group-chats.ui/remove-chat-pressed
:chat.ui/remove-chat)]
[list/deletable-list-item {:type :chats
:id home-item-id
:on-delete #(do
(re-frame/dispatch [:set-swipe-position :chats home-item-id false])
(re-frame/dispatch [delete-action home-item-id]))}
[inner-item/home-list-chat-item-inner-view home-item]]))
;;do not remove view-id and will-update or will-unmount handlers, this is how it works
(views/defview welcome [view-id]
(views/letsubs [handler #(re-frame/dispatch [:set-in [:accounts/create :show-welcome?] false])]
{:component-will-update handler
:component-will-unmount handler}
[react/view {:style styles/welcome-view}
[react/view {:style styles/welcome-image-container}
[react/image {:source (:welcome-image resources/ui)
:style styles/welcome-image}]]
[react/i18n-text {:style styles/welcome-text :key :welcome-to-status}]
[react/view
[react/i18n-text {:style styles/welcome-text-description
:key :welcome-to-status-description}]]]))
(defn search-input
[search-filter {:keys [on-cancel on-focus on-change]}]
(let [input-is-focused? (reagent/atom false)
input-ref (reagent/atom nil)]
(fn [search-filter]
(let [show-cancel? (or @input-is-focused?
search-filter)]
[react/view {:style styles/search-container}
[react/view {:style styles/search-input-container}
[icons/icon :main-icons/search {:color colors/gray
:container-style {:margin-left 6
:margin-right 2}}]
[react/text-input {:placeholder (i18n/label :t/search)
:blur-on-submit true
:multiline false
:ref #(reset! input-ref %)
:style styles/search-input
:default-value search-filter
:on-focus
#(do
(when on-focus
(on-focus search-filter))
(reset! input-is-focused? true))
:on-change
(fn [e]
(let [native-event (.-nativeEvent e)
text (.-text native-event)]
(when on-change
(on-change text))))}]]
(when show-cancel?
[react/touchable-highlight
{:on-press #(do
(when on-cancel
(on-cancel))
(.blur @input-ref)
(reset! input-is-focused? false))
:style {:margin-left 16}}
[react/text {:style {:color colors/blue
:font-size 15}}
(i18n/label :t/cancel)]])]))))
(defonce search-input-state
(reagent/atom {:show? false
:height (animation/create-value 0)}))
(defn show-search!
[]
(swap! search-input-state assoc :show? true)
(animation/start
(animation/timing (:height @search-input-state)
{:toValue styles/search-input-height
:duration 350
:easing (.out (animation/easing)
(.-quad (animation/easing)))})))
(defn hide-search!
[]
(utils/set-timeout
#(swap! search-input-state assoc :show? false)
350)
(animation/start
(animation/timing (:height @search-input-state)
{:toValue 0
:duration 350
:easing (.in (animation/easing)
(.-quad (animation/easing)))})))
(defn set-search-state-visible!
[visible?]
(swap! search-input-state assoc :show? visible?)
(animation/set-value (:height @search-input-state)
(if visible?
styles/search-input-height
0)))
(defn animated-search-input
[search-filter]
(reagent/create-class
{:component-will-unmount
#(set-search-state-visible! false)
:component-did-mount
#(when search-filter
(set-search-state-visible! true))
:reagent-render
(fn [search-filter]
(let [{:keys [show? height]} @search-input-state]
(when (or show?
search-filter)
[react/animated-view
{:style {:height height}}
[search-input search-filter
{:on-cancel #(do
(re-frame/dispatch [:search/filter-changed nil])
(hide-search!))
:on-focus (fn [search-filter]
(when-not search-filter
(re-frame/dispatch [:search/filter-changed ""])))
:on-change (fn [text]
(re-frame/dispatch [:search/filter-changed text]))}]])))}))
(defn home-empty-view
[]
[react/view styles/no-chats [react/view styles/no-chats
[react/i18n-text {:style styles/no-chats-text :key :no-recent-chats}]]) [react/i18n-text {:style styles/no-chats-text :key :no-recent-chats}]
[react/view {:align-items :center :margin-top 20}
[components.common/button {:on-press #(list-selection/open-share {:message (i18n/label :t/get-status-at)})
:label (i18n/label :t/invite-friends)}]]])
(defn home-filtered-items-list (defn home-items-view [_ _ _]
[chats] (let [previous-touch (reagent/atom nil)
[list/section-list
{:sections [{:title :t/chats
:data chats}
{:title :t/messages
:data []}]
:key-fn first
;; true by default on iOS
:stickySectionHeadersEnabled false
:render-section-header-fn
(fn [{:keys [title data]}]
[react/view {:style {:height 40}}
[react/text {:style styles/filter-section-title}
(i18n/label title)]])
:render-section-footer-fn
(fn [{:keys [title data]}]
(when (empty? data)
[list/big-list-item
{:text (i18n/label (if (= title "messages")
:t/messages-search-coming-soon
:t/no-result))
:text-color colors/gray
:hide-chevron? true
:action-fn #()
:icon (case title
"messages" :main-icons/private-chat
"browser" :main-icons/browser
"chats" :main-icons/message)
:icon-color colors/gray}]))
:render-fn (fn [home-item]
[home-list-item home-item])}])
(defn home-items-view
[search-filter chats all-home-items]
(let [previous-touch (reagent/atom nil)
scrolling-from-top? (reagent/atom true)] scrolling-from-top? (reagent/atom true)]
(fn [search-filter chats all-home-items] (fn [search-filter chats all-home-items]
(if (not-empty search-filter) (if (not-empty search-filter)
[home-filtered-items-list chats] [filter.views/home-filtered-items-list chats]
[react/view [react/view
(merge {:style {:flex 1}} (merge {:style {:flex 1}}
(when (and @scrolling-from-top? (when (and @scrolling-from-top?
(not (:show? @search-input-state))) (not (:show? @filter.views/search-input-state)))
{:on-start-should-set-responder-capture {:on-start-should-set-responder-capture
(fn [event] (fn [event]
(let [current-position (.-pageY (.-nativeEvent event)) (let [current-position (.-pageY (.-nativeEvent event))
current-timestamp (.-timestamp (.-nativeEvent event))] current-timestamp (.-timestamp (.-nativeEvent event))]
(reset! previous-touch (reset! previous-touch
[current-position current-timestamp])) [current-position current-timestamp]))
@ -243,14 +77,14 @@
false) false)
:on-move-should-set-responder :on-move-should-set-responder
(fn [event] (fn [event]
(let [current-position (.-pageY (.-nativeEvent event)) (let [current-position (.-pageY (.-nativeEvent event))
current-timestamp (.-timestamp (.-nativeEvent event)) current-timestamp (.-timestamp (.-nativeEvent event))
[previous-position previous-timestamp] @previous-touch] [previous-position previous-timestamp] @previous-touch]
(when (and previous-position (when (and previous-position
(> 100 (- current-timestamp previous-timestamp)) (> 100 (- current-timestamp previous-timestamp))
(< 10 (- current-position (< 10 (- current-position
previous-position))) previous-position)))
(show-search!))) (filter.views/show-search!)))
false)})) false)}))
[list/flat-list {:data all-home-items [list/flat-list {:data all-home-items
:key-fn first :key-fn first
@ -265,34 +99,31 @@
(zero? (.-y (.-contentOffset (.-nativeEvent e)))))) (zero? (.-y (.-contentOffset (.-nativeEvent e))))))
:render-fn :render-fn
(fn [home-item] (fn [home-item]
[home-list-item home-item])}]])))) [inner-item/home-list-item home-item])}]]))))
(views/defview home-action-button []
(views/letsubs [logging-in? [:get :accounts/login]]
[react/view styles/action-button-container
[react/touchable-highlight {:accessibility-label :new-chat-button
:on-press (when-not logging-in? #(re-frame/dispatch [:bottom-sheet/show-sheet :add-new]))}
[react/view styles/action-button
(if logging-in?
[react/activity-indicator {:color :white
:animating true}]
[icons/icon :main-icons/add {:color :white}])]]]))
(views/defview home [loading?] (views/defview home [loading?]
(views/letsubs [show-welcome? [:get-in [:accounts/create :show-welcome?]] (views/letsubs [{:keys [search-filter chats all-home-items]} [:home-items]]
view-id [:get :view-id] {:component-did-mount (fn [this]
logging-in? [:get :accounts/login] (let [[_ loading?] (.. this -props -argv)]
sync-state [:chain-sync-state] (when loading? (utils/set-timeout #(re-frame/dispatch [:init-rest-of-chats]) 100))))}
latest-block-number [:latest-block-number]
rpc-network? [:current-network-uses-rpc?]
network-initialized? [:current-network-initialized?]
{:keys [search-filter chats all-home-items]} [:home-items]]
{:component-did-mount
(fn [this]
(let [[_ loading?] (.. this -props -argv)]
(when loading?
(utils/set-timeout
#(re-frame/dispatch [:init-rest-of-chats])
100))))}
[react/view {:flex 1} [react/view {:flex 1}
[status-bar/status-bar {:type :main}] [status-bar/status-bar {:type :main}]
[react/keyboard-avoiding-view {:style {:flex 1 [react/keyboard-avoiding-view {:style {:flex 1
:background-color :white}} :background-color :white}}
[toolbar show-welcome? (and network-initialized? (not rpc-network?)) [toolbar/toolbar nil nil [toolbar/content-title (i18n/label :t/chat)]]
sync-state latest-block-number (not logging-in?)] [les-debug-info]
(cond show-welcome? (cond loading?
[welcome view-id]
loading?
[react/view {:style {:flex 1 [react/view {:style {:flex 1
:justify-content :center :justify-content :center
:align-items :center}} :align-items :center}}
@ -303,13 +134,12 @@
:else :else
[react/view {:style {:flex 1}} [react/view {:style {:flex 1}}
[connectivity/connectivity-view] [connectivity/connectivity-view]
[animated-search-input search-filter] [filter.views/animated-search-input search-filter]
(if (and (not search-filter) (if (and (not search-filter)
(empty? all-home-items)) (empty? all-home-items))
[home-empty-view] [home-empty-view]
[home-items-view search-filter chats all-home-items])]) [home-items-view search-filter chats all-home-items])])
(when platform/android? [home-action-button]]]))
[home-action-button (not logging-in?)])]]))
(views/defview home-wrapper [] (views/defview home-wrapper []
(views/letsubs [loading? [:get :chats/loading?]] (views/letsubs [loading? [:get :chats/loading?]]

View File

@ -16,7 +16,8 @@
[status-im.ui.components.common.common :as components.common] [status-im.ui.components.common.common :as components.common]
[status-im.ui.components.list-item.views :as list-item] [status-im.ui.components.list-item.views :as list-item]
[clojure.string :as string] [clojure.string :as string]
[status-im.ui.components.chat-icon.screen :as chat-icon])) [status-im.ui.components.chat-icon.screen :as chat-icon]
[status-im.ui.components.list.views :as list]))
(defview command-short-preview [message] (defview command-short-preview [message]
(letsubs [id->command [:chats/id->command] (letsubs [id->command [:chats/id->command]
@ -112,6 +113,18 @@
:content-type last-message-content-type}] :content-type last-message-content-type}]
[unviewed-indicator chat-id]]]]])) [unviewed-indicator chat-id]]]]]))
(defn home-list-item [[home-item-id home-item]]
(let [delete-action (if (and (:group-chat home-item)
(not (:public? home-item)))
:group-chats.ui/remove-chat-pressed
:chat.ui/remove-chat)]
[list/deletable-list-item {:type :chats
:id home-item-id
:on-delete #(do
(re-frame/dispatch [:set-swipe-position :chats home-item-id false])
(re-frame/dispatch [delete-action home-item-id]))}
[home-list-chat-item-inner-view home-item]]))
(defn home-list-browser-item-inner-view [{:keys [dapp url name browser-id]}] (defn home-list-browser-item-inner-view [{:keys [dapp url name browser-id]}]
(let [photo-path (:photo-path dapp)] (let [photo-path (:photo-path dapp)]
[list-item/list-item (merge [list-item/list-item (merge

View File

@ -20,4 +20,5 @@
:wallet-settings-assets :wallet-settings-assets
:wallet-transaction-fee :wallet-transaction-fee
:wallet-transactions-filter :wallet-transactions-filter
:profile-qr-viewer]) :profile-qr-viewer
:welcome])

View File

@ -142,7 +142,8 @@
:tribute-to-talk tr-to-talk/tribute-to-talk :tribute-to-talk tr-to-talk/tribute-to-talk
:reset-card hardwallet.settings/reset-card :reset-card hardwallet.settings/reset-card
:keycard-settings hardwallet.settings/keycard-settings :keycard-settings hardwallet.settings/keycard-settings
:mobile-network-settings mobile-network-settings/mobile-network-settings}) :mobile-network-settings mobile-network-settings/mobile-network-settings
:welcome [:modal home/welcome]})
(defn get-screen [screen] (defn get-screen [screen]
(get all-screens screen #(throw (str "Screen " screen " is not defined.")))) (get all-screens screen #(throw (str "Screen " screen " is not defined."))))

View File

@ -12,6 +12,7 @@
[taoensso.timbre :as log] [taoensso.timbre :as log]
[status-im.utils.platform :as platform] [status-im.utils.platform :as platform]
[status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings] [status-im.ui.screens.mobile-network-settings.view :as mobile-network-settings]
[status-im.ui.screens.home.sheet.views :as home.sheet]
[status-im.ui.screens.routing.core :as routing])) [status-im.ui.screens.routing.core :as routing]))
(defonce rand-label (rand/id)) (defonce rand-label (rand/id))
@ -27,7 +28,11 @@
(merge mobile-network-settings/settings-sheet) (merge mobile-network-settings/settings-sheet)
(= view :mobile-network-offline) (= view :mobile-network-offline)
(merge mobile-network-settings/offline-sheet))] (merge mobile-network-settings/offline-sheet)
(= view :add-new)
(merge home.sheet/add-new))]
[bottom-sheet/bottom-sheet opts]))) [bottom-sheet/bottom-sheet opts])))
(defn main [] (defn main []

View File

@ -265,7 +265,7 @@
"mailserver-connection-error": "Could not connect to mailserver", "mailserver-connection-error": "Could not connect to mailserver",
"mailserver-automatic": "Automatic selection", "mailserver-automatic": "Automatic selection",
"currency-display-name-kzt": "Kazakhstan Tenge", "currency-display-name-kzt": "Kazakhstan Tenge",
"no-recent-chats": "Your Home screen will house your recent chats and DApp history. Tap the plus (+) button to get started.", "no-recent-chats": "There are no recent chats here yet. \nUse the (+) button to discover people \nto chat with",
"install": "Install", "install": "Install",
"command-requesting": "Requesting {{amount}} {{asset}}", "command-requesting": "Requesting {{amount}} {{asset}}",
"mailserver-details": "Mailserver details", "mailserver-details": "Mailserver details",
@ -677,7 +677,7 @@
"ethereum-node-started-incorrectly-title": "Ethereum node started incorrectly", "ethereum-node-started-incorrectly-title": "Ethereum node started incorrectly",
"ethereum-node-started-incorrectly-description": "Ethereum node was started with incorrect configuration, application will be stopped to recover from that condition. Configured network id = {{network-id}}, actual = {{fetched-network-id}}", "ethereum-node-started-incorrectly-description": "Ethereum node was started with incorrect configuration, application will be stopped to recover from that condition. Configured network id = {{network-id}}, actual = {{fetched-network-id}}",
"browser-not-secure": "Connection is not secure! Do not sign transactions or send personal data on this site.", "browser-not-secure": "Connection is not secure! Do not sign transactions or send personal data on this site.",
"welcome-to-status-description": "Tap the plus (+) button to get started", "welcome-to-status-description": "Here you can chat with people in a secure private chat, browse and interact with DApps.",
"recovery-phrase-invalid": "Recovery phrase is invalid", "recovery-phrase-invalid": "Recovery phrase is invalid",
"currency-display-name-cny": "China Yuan Renminbi", "currency-display-name-cny": "China Yuan Renminbi",
"clear-history-confirmation-content": "Are you sure you want to clear this chat history?", "clear-history-confirmation-content": "Are you sure you want to clear this chat history?",