Merge pull request #541 from status-im/feature/toolbar-fixes-and-search
Toolbar refactoring, unification; search for contacts (#448); processed-messages cache (#552); fix for #554
This commit is contained in:
commit
63e352020d
|
@ -1,5 +1,6 @@
|
|||
(ns status-im.accounts.handlers
|
||||
(:require [status-im.data-store.accounts :as accounts-store]
|
||||
[status-im.data-store.processed-messages :as processed-messages]
|
||||
[re-frame.core :refer [register-handler after dispatch dispatch-sync debug]]
|
||||
[taoensso.timbre :as log]
|
||||
[status-im.protocol.core :as protocol]
|
||||
|
@ -18,6 +19,7 @@
|
|||
[status-im.utils.gfycat.core :refer [generate-gfy]]
|
||||
[status-im.constants :refer [console-chat-id]]
|
||||
[status-im.utils.scheduler :as s]
|
||||
[status-im.protocol.message-cache :as cache]
|
||||
[status-im.navigation.handlers :as nav]))
|
||||
|
||||
|
||||
|
@ -149,6 +151,15 @@
|
|||
|
||||
(register-handler :console-create-account console-create-account)
|
||||
|
||||
(register-handler
|
||||
:load-processed-messages
|
||||
(u/side-effect!
|
||||
(fn [_]
|
||||
(let [now (time/now-ms)
|
||||
messages (processed-messages/get-filtered (str "ttl > " now))]
|
||||
(cache/init! messages)
|
||||
(processed-messages/delete (str "ttl <=" now))))))
|
||||
|
||||
(defmethod nav/preload-data! :qr-code-view
|
||||
[{:keys [current-account-id] :as db} [_ _ {:keys [contact qr-source amount?]}]]
|
||||
(assoc db :qr-modal {:contact (or contact
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
get-dimensions]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-title-container
|
||||
toolbar-title-text]]
|
||||
[status-im.components.text-field.view :refer [text-field]]
|
||||
|
@ -66,9 +67,7 @@
|
|||
:style st/gradient-background}]
|
||||
[status-bar {:type :transparent}]
|
||||
[toolbar {:background-color :transparent
|
||||
:nav-action {:image {:source {:uri :icon_back_white}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:nav-action (act/back-white #(dispatch [:navigate-back]))
|
||||
:custom-content [toolbar-title]
|
||||
:actions [{:image {:style icon-search}
|
||||
:handler #()}]}]
|
||||
|
|
|
@ -9,13 +9,12 @@
|
|||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.text-field.view :refer [text-field]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-gradient
|
||||
toolbar-title-container
|
||||
toolbar-title-text]]
|
||||
[status-im.components.styles :refer [color-purple
|
||||
color-white
|
||||
icon-back
|
||||
icon-search
|
||||
button-input]]
|
||||
[status-im.components.react :refer [linear-gradient]]
|
||||
[status-im.i18n :refer [label]]
|
||||
|
@ -78,12 +77,8 @@
|
|||
[view st/screen-container
|
||||
[status-bar {:type :transparent}]
|
||||
[toolbar {:background-color :transparent
|
||||
:nav-action {:image {:source {:uri :icon_back}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:custom-content [toolbar-title]
|
||||
:actions [{:image {:style icon-search}
|
||||
:handler #()}]}]
|
||||
:nav-action (act/back #(dispatch [:navigate-back]))
|
||||
:custom-content [toolbar-title]}]
|
||||
[linear-gradient {:locations [0 0.6 1]
|
||||
:colors gradient-colors
|
||||
:style toolbar-gradient}]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
touchable-highlight]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.styles :refer [color-purple
|
||||
color-white
|
||||
icon-search
|
||||
|
@ -61,9 +62,9 @@
|
|||
:style st/gradient-background}
|
||||
[status-bar {:type :transparent}]
|
||||
[toolbar {:background-color :transparent
|
||||
:nav-action {:image {:source (if show-back? {:uri :icon_back_white} nil)
|
||||
:style icon-back}
|
||||
:handler (if show-back? #(dispatch [:navigate-back]) nil)}
|
||||
:nav-action (if show-back?
|
||||
(act/back-white #(dispatch [:navigate-back]))
|
||||
act/nothing)
|
||||
:custom-content [toolbar-title]
|
||||
:actions [{:image {:style icon-search}
|
||||
:handler #()}]}]]
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
modal
|
||||
splash-screen]]
|
||||
[status-im.components.main-tabs :refer [main-tabs]]
|
||||
[status-im.contacts.search-results :refer [contacts-search-results]]
|
||||
[status-im.contacts.views.contact-list :refer [contact-list]]
|
||||
[status-im.contacts.views.new-contact :refer [new-contact]]
|
||||
[status-im.qr-scanner.screen :refer [qr-scanner]]
|
||||
|
@ -95,6 +96,7 @@
|
|||
:new-group new-group
|
||||
:group-settings group-settings
|
||||
:contact-list main-tabs
|
||||
:contact-list-search-results contacts-search-results
|
||||
:group-contacts contact-list
|
||||
:new-contact new-contact
|
||||
:qr-scanner qr-scanner
|
||||
|
|
|
@ -8,43 +8,36 @@
|
|||
text
|
||||
image
|
||||
touchable-highlight]]
|
||||
[status-im.utils.listview :refer [to-datasource]]
|
||||
[status-im.chats-list.views.chat-list-item :refer [chat-list-item]]
|
||||
[status-im.components.action-button :refer [action-button
|
||||
action-button-item]]
|
||||
[status-im.components.drawer.view :refer [open-drawer]]
|
||||
[status-im.components.styles :refer [color-blue]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background1
|
||||
toolbar-background2]]
|
||||
[status-im.components.toolbar.view :refer [toolbar-with-search]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.icons.custom-icons :refer [ion-icon]]
|
||||
[status-im.components.react :refer [linear-gradient]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.chats-list.styles :as st]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.components.sync-state.offline :refer [offline-view]]
|
||||
[status-im.utils.listview :refer [to-datasource]]
|
||||
[status-im.chats-list.views.chat-list-item :refer [chat-list-item]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.chats-list.styles :as st]
|
||||
[status-im.components.tabs.styles :refer [tabs-height]]))
|
||||
|
||||
(defview chats-list-toolbar []
|
||||
(defview toolbar-view []
|
||||
[chats-scrolled? [:get :chats-scrolled?]]
|
||||
(let [new-chat? (get-in platform-specific [:chats :new-chat-in-toolbar?])
|
||||
actions (cond->> [{:image {:source {:uri :icon_search}
|
||||
:style st/toolbar-icon}
|
||||
:handler (fn [])}]
|
||||
new-chat?
|
||||
(into [{:image {:source {:uri :icon_add}
|
||||
:style st/toolbar-icon}
|
||||
:handler #(dispatch [:navigate-to :group-contacts :people])}]))]
|
||||
[toolbar {:nav-action {:image {:source {:uri :icon_hamburger}
|
||||
:style st/hamburger-icon}
|
||||
:handler open-drawer}
|
||||
:title (label :t/chats)
|
||||
:style (get-in platform-specific [:component-styles :toolbar])
|
||||
:background-color (if chats-scrolled?
|
||||
toolbar-background1
|
||||
toolbar-background2)
|
||||
:actions actions}]))
|
||||
actions (if new-chat?
|
||||
[(act/add #(dispatch [:navigate-to :group-contacts :people]))])]
|
||||
[toolbar-with-search
|
||||
{:show-search? false
|
||||
:search-key :chat-list
|
||||
:title (label :t/chats)
|
||||
:search-placeholder (label :t/search-for)
|
||||
:nav-action (act/hamburger open-drawer)
|
||||
:actions actions
|
||||
:style (st/toolbar chats-scrolled?)}]))
|
||||
|
||||
(defn chats-action-button []
|
||||
[view {:style (st/action-buttons-container false 0)
|
||||
|
@ -75,7 +68,7 @@
|
|||
(defview chats-list []
|
||||
[chats [:get :chats]]
|
||||
[view st/chats-container
|
||||
[chats-list-toolbar]
|
||||
[toolbar-view]
|
||||
[list-view {:dataSource (to-datasource chats)
|
||||
:renderRow (fn [[id :as row] _ _]
|
||||
(list-item ^{:key id} [chat-list-item row]))
|
||||
|
|
|
@ -7,8 +7,16 @@
|
|||
text2-color
|
||||
new-messages-count-color]]
|
||||
[status-im.components.tabs.styles :refer [tabs-height]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background1
|
||||
toolbar-background2]]
|
||||
[status-im.utils.platform :as p]))
|
||||
|
||||
(defn toolbar [chats-scrolled?]
|
||||
(merge {:background-color (if chats-scrolled?
|
||||
toolbar-background1
|
||||
toolbar-background2)}
|
||||
(get-in p/platform-specific [:component-styles :toolbar])))
|
||||
|
||||
(def gradient-top-bottom-shadow
|
||||
["rgba(24, 52, 76, 0.165)"
|
||||
"rgba(24, 52, 76, 0.03)"
|
||||
|
@ -103,14 +111,6 @@
|
|||
:color color-blue
|
||||
:textAlign :center})
|
||||
|
||||
(def hamburger-icon
|
||||
{:width 16
|
||||
:height 12})
|
||||
|
||||
(def toolbar-icon
|
||||
{:width 17
|
||||
:height 17})
|
||||
|
||||
(def chats-container
|
||||
{:flex 1})
|
||||
|
||||
|
|
|
@ -107,8 +107,8 @@
|
|||
:onScrollBeginDrag #(reset! dragging? true)
|
||||
:on-momentum-scroll-end (on-scroll-end swiped? dragging?)})
|
||||
[chats-list]
|
||||
[discover (= @view-id :discover)]
|
||||
[contact-list]]
|
||||
[discover (= @view-id :discover)]
|
||||
[contact-list (= @view-id :contact-list)]]
|
||||
[tabs {:selected-view-id @view-id
|
||||
:prev-view-id @prev-view-id
|
||||
:tab-list tab-list}]
|
||||
|
|
|
@ -31,10 +31,6 @@
|
|||
(def flex
|
||||
{:flex 1})
|
||||
|
||||
(def hamburger-icon
|
||||
{:width 16
|
||||
:height 12})
|
||||
|
||||
(def icon-search
|
||||
{:width 17
|
||||
:height 17})
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
(ns status-im.components.toolbar.actions
|
||||
(:require [status-im.components.toolbar.styles :as st]))
|
||||
|
||||
(def nothing
|
||||
{:image {:source nil
|
||||
:style st/action-search}})
|
||||
|
||||
(defn hamburger [handler]
|
||||
{:image {:source {:uri :icon_hamburger}
|
||||
:style st/action-hamburger}
|
||||
:handler handler})
|
||||
|
||||
(defn add [handler]
|
||||
{:image {:source {:uri :icon_add}
|
||||
:style st/action-add}
|
||||
:handler handler})
|
||||
|
||||
(defn search [handler]
|
||||
{:image {:source {:uri :icon_search}
|
||||
:style st/action-search}
|
||||
:handler handler})
|
||||
|
||||
(defn back [handler]
|
||||
{:image {:source {:uri :icon_back}
|
||||
:style st/action-back}
|
||||
:handler handler})
|
||||
|
||||
(defn back-white [handler]
|
||||
{:image {:source {:uri :icon_back_white}
|
||||
:style st/action-back}
|
||||
:handler handler})
|
|
@ -41,7 +41,7 @@
|
|||
:justifyContent :center})
|
||||
|
||||
(def toolbar-title-text
|
||||
{:margin-top -2.5
|
||||
{:margin-top 0
|
||||
:color text1-color
|
||||
:font-size 16})
|
||||
|
||||
|
@ -58,3 +58,45 @@
|
|||
:margin-right toolbar-icon-spacing
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def toolbar-with-search
|
||||
{:background-color toolbar-background2
|
||||
:elevation 0})
|
||||
|
||||
(def toolbar-with-search-content
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def toolbar-search-input
|
||||
{:flex 1
|
||||
:align-self :stretch
|
||||
:margin-left 18
|
||||
:margin-top 2
|
||||
:font-size 14
|
||||
:color "#7099e6"})
|
||||
|
||||
(def toolbar-with-search-title
|
||||
{:color "#000000de"
|
||||
:align-self :center
|
||||
:text-align :center
|
||||
:font-size 16})
|
||||
|
||||
|
||||
;; Specific actions
|
||||
|
||||
(def action-hamburger
|
||||
{:width 16
|
||||
:height 12})
|
||||
|
||||
(def action-add
|
||||
{:width 17
|
||||
:height 17})
|
||||
|
||||
(def action-search
|
||||
{:width 17
|
||||
:height 17})
|
||||
|
||||
(def action-back
|
||||
{:width 8
|
||||
:height 14})
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
[status-im.components.react :refer [view
|
||||
icon
|
||||
text
|
||||
text-input
|
||||
image
|
||||
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
|
||||
icon-search]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :as st]
|
||||
[status-im.utils.platform :refer [platform-specific]]))
|
||||
|
||||
|
@ -48,3 +51,43 @@
|
|||
custom-action)]]
|
||||
[sync-state-gradient-view]]))
|
||||
|
||||
(defn- toolbar-search-submit [on-search-submit]
|
||||
(let [text @(subscribe [:get-in [:toolbar-search :text]])]
|
||||
(on-search-submit text)
|
||||
(dispatch [:set-in [:toolbar-search :text] nil])))
|
||||
|
||||
(defn- toolbar-with-search-content [{:keys [show-search?
|
||||
search-key
|
||||
search-placeholder
|
||||
title
|
||||
on-search-submit]}]
|
||||
[view st/toolbar-with-search-content
|
||||
(if show-search?
|
||||
[text-input
|
||||
{:style st/toolbar-search-input
|
||||
:auto-focus true
|
||||
:placeholder search-placeholder
|
||||
:on-change-text #(dispatch [:set-in [:toolbar-search :text] %])
|
||||
:on-submit-editing #(toolbar-search-submit on-search-submit)}]
|
||||
[view
|
||||
[text {:style st/toolbar-with-search-title
|
||||
:font :toolbar-title}
|
||||
title]])])
|
||||
|
||||
(defn toolbar-with-search [{:keys [show-search?
|
||||
search-key
|
||||
nav-action
|
||||
actions
|
||||
style
|
||||
on-search-submit]
|
||||
:as opts}]
|
||||
(let [toggle-search-fn #(dispatch [:set-in [:toolbar-search :show] %])
|
||||
actions (if show-search?
|
||||
[(act/search #(toolbar-search-submit on-search-submit))]
|
||||
(into actions [(act/search #(toggle-search-fn search-key))]))]
|
||||
[toolbar {:style (merge st/toolbar-with-search style)
|
||||
:nav-action (if show-search?
|
||||
(act/back #(toggle-search-fn nil))
|
||||
nav-action)
|
||||
:custom-content [toolbar-with-search-content opts]
|
||||
:actions actions}]))
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[status-im.utils.utils :refer [require]]
|
||||
[status-im.navigation.handlers :as nav]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.i18n :refer [label]]
|
||||
[taoensso.timbre :as log]
|
||||
[cljs.reader :refer [read-string]]))
|
||||
|
||||
|
@ -31,9 +32,10 @@
|
|||
|
||||
(defmethod nav/preload-data! :contact-list
|
||||
[db [_ _ click-handler]]
|
||||
(assoc db :contacts-click-handler click-handler
|
||||
:contacts-filter nil))
|
||||
|
||||
(-> db
|
||||
(assoc-in [:toolbar-search :show] nil)
|
||||
(assoc :contacts-click-handler click-handler
|
||||
:contacts-filter nil)))
|
||||
|
||||
(register-handler :remove-contacts-click-handler
|
||||
(fn [db]
|
||||
|
@ -56,6 +58,13 @@
|
|||
|
||||
(register-handler :watch-contact (u/side-effect! watch-contact))
|
||||
|
||||
(defn stop-watching-contact
|
||||
[{:keys [web3]} [_ {:keys [whisper-identity]}]]
|
||||
(protocol/stop-watching-user! {:web3 web3
|
||||
:identity whisper-identity}))
|
||||
|
||||
(register-handler :stop-watching-contact (u/side-effect! stop-watching-contact))
|
||||
|
||||
(defn send-contact-request
|
||||
[{:keys [current-public-key web3 current-account-id accounts]} [_ contact]]
|
||||
(let [{:keys [whisper-identity]} contact
|
||||
|
@ -199,11 +208,13 @@
|
|||
|
||||
(register-handler :add-pending-contact
|
||||
(u/side-effect!
|
||||
(fn [{:keys [chats]} [_ chat-id]]
|
||||
(let [contact (read-string (get-in chats [chat-id :contact-info]))]
|
||||
(fn [{:keys [chats contacts]} [_ chat-id]]
|
||||
(let [contact (if-let [contact-info (get-in chats [chat-id :contact-info])]
|
||||
(read-string contact-info)
|
||||
(-> (get contacts chat-id)
|
||||
(assoc :pending false)))]
|
||||
(dispatch [::prepare-contact contact])
|
||||
(dispatch [:update-chat! {:chat-id chat-id
|
||||
:contact-info nil
|
||||
:pending-contact? false}])
|
||||
(dispatch [:watch-contact contact])
|
||||
(dispatch [:discoveries-send-portions chat-id])))))
|
||||
|
@ -242,3 +253,22 @@
|
|||
(dispatch [:update-contact! {:whisper-identity from
|
||||
:last-online timestamp}]))))))
|
||||
|
||||
(register-handler :remove-contact
|
||||
(-> (u/side-effect!
|
||||
(fn [_ [_ {:keys [whisper-identity] :as contact}]]
|
||||
(dispatch [:update-chat! {:chat-id whisper-identity
|
||||
:pending-contact? true}])
|
||||
(dispatch [:update-contact! (assoc contact :pending true)])))
|
||||
((after stop-watching-contact))))
|
||||
|
||||
(register-handler :open-contact-menu
|
||||
(u/side-effect!
|
||||
(fn [_ [_ list-selection-fn {:keys [name] :as contact}]]
|
||||
(list-selection-fn {:title name
|
||||
:options [(label :t/remove-contact)]
|
||||
:callback (fn [index]
|
||||
(case index
|
||||
0 (dispatch [:remove-contact contact])
|
||||
:default))
|
||||
:cancel-text (label :t/cancel)}))))
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
(ns status-im.contacts.screen
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[reagent.core :as r]
|
||||
(:require [reagent.core :as r]
|
||||
[clojure.string :as str]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
image
|
||||
|
@ -12,38 +13,40 @@
|
|||
list-item] :as react]
|
||||
[status-im.components.action-button :refer [action-button
|
||||
action-button-item]]
|
||||
[status-im.contacts.views.contact :refer [contact-extended-view on-press]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background2]]
|
||||
[status-im.components.toolbar.view :refer [toolbar-with-search]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.drawer.view :refer [open-drawer]]
|
||||
[status-im.components.icons.custom-icons :refer [ion-icon]]
|
||||
[status-im.components.styles :refer [color-blue
|
||||
hamburger-icon
|
||||
icon-search
|
||||
create-icon]]
|
||||
[status-im.contacts.styles :as st]
|
||||
[status-im.contacts.views.contact :refer [contact-view]]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.utils.platform :refer [platform-specific]]))
|
||||
[status-im.contacts.styles :as st]
|
||||
[status-im.components.styles :refer [color-blue
|
||||
create-icon
|
||||
icon-search]]))
|
||||
|
||||
(def contacts-limit 50)
|
||||
|
||||
(defn toolbar-view []
|
||||
(defn toolbar-view [show-search?]
|
||||
(let [new-contact? (get-in platform-specific [:contacts :new-contact-in-toolbar?])
|
||||
actions (cond->> [{:image {:source {:uri :icon_search}
|
||||
:style icon-search}
|
||||
:handler (fn [])}]
|
||||
new-contact?
|
||||
(into [{:image {:source {:uri :icon_add}
|
||||
:style icon-search}
|
||||
:handler #(dispatch [:navigate-to :new-contact])}]))]
|
||||
[toolbar {:nav-action {:image {:source {:uri :icon_hamburger}
|
||||
:style hamburger-icon}
|
||||
:handler open-drawer}
|
||||
:title (label :t/contacts)
|
||||
:background-color toolbar-background2
|
||||
:style {:elevation 0}
|
||||
:actions actions}]))
|
||||
actions (if new-contact?
|
||||
[(act/add #(dispatch [:navigate-to :new-contact]))])]
|
||||
(toolbar-with-search
|
||||
{:show-search? show-search?
|
||||
:search-key :contact-list
|
||||
:title (label :t/contacts)
|
||||
:search-placeholder (label :t/search-for)
|
||||
:nav-action (act/hamburger open-drawer)
|
||||
:actions actions
|
||||
:on-search-submit (fn [text]
|
||||
(when-not (str/blank? text)
|
||||
(dispatch [:set :contacts-filter #(let [name (-> (or (:name %) "")
|
||||
(str/lower-case))
|
||||
text (str/lower-case text)]
|
||||
(not= (.indexOf name text) -1))])
|
||||
(dispatch [:set :contact-list-search-text text])
|
||||
(dispatch [:navigate-to :contact-list-search-results])))})))
|
||||
|
||||
(defn subtitle-view [subtitle contacts-count]
|
||||
[view st/contact-group-header-inner
|
||||
|
@ -81,9 +84,11 @@
|
|||
[view
|
||||
(doall
|
||||
(map (fn [contact]
|
||||
(let [click-handler (or click-handler on-press)]
|
||||
^{:key contact}
|
||||
[contact-extended-view contact nil (click-handler contact) nil]))
|
||||
^{:key contact}
|
||||
[contact-view {:contact contact
|
||||
:extended? true
|
||||
:on-click click-handler
|
||||
:more-on-click nil}])
|
||||
contacts))]
|
||||
(when (<= contacts-limit (count contacts))
|
||||
[view st/show-all
|
||||
|
@ -110,16 +115,18 @@
|
|||
[ion-icon {:name :md-create
|
||||
:style create-icon}]]]])
|
||||
|
||||
(defn contact-list []
|
||||
(defn contact-list [_]
|
||||
(let [peoples (subscribe [:get-added-people-with-limit contacts-limit])
|
||||
dapps (subscribe [:get-added-dapps-with-limit contacts-limit])
|
||||
people-count (subscribe [:added-people-count])
|
||||
dapps-count (subscribe [:added-dapps-count])
|
||||
click-handler (subscribe [:get :contacts-click-handler])
|
||||
show-search (subscribe [:get-in [:toolbar-search :show]])
|
||||
show-toolbar-shadow? (r/atom false)]
|
||||
(fn []
|
||||
(fn [current-view?]
|
||||
[view st/contacts-list-container
|
||||
[toolbar-view]
|
||||
[toolbar-view (and current-view?
|
||||
(= @show-search :contact-list))]
|
||||
[view {:style st/toolbar-shadow}
|
||||
(when @show-toolbar-shadow?
|
||||
[linear-gradient {:style st/contact-group-header-gradient-bottom
|
||||
|
@ -128,7 +135,8 @@
|
|||
[scroll-view {:style st/contact-groups
|
||||
:onScroll (fn [e]
|
||||
(let [offset (.. e -nativeEvent -contentOffset -y)]
|
||||
(reset! show-toolbar-shadow? (<= st/contact-group-header-height offset))))}
|
||||
(reset! show-toolbar-shadow?
|
||||
(<= st/contact-group-header-height offset))))}
|
||||
(when (pos? @dapps-count)
|
||||
[contact-group-view
|
||||
@dapps
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
(ns status-im.contacts.search-results
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.react :refer [view
|
||||
text
|
||||
icon
|
||||
list-view
|
||||
list-item]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.contacts.views.contact :refer [contact-view]]
|
||||
[status-im.utils.listview :refer [to-datasource]]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.contacts.styles :as st]))
|
||||
|
||||
(defview contacts-search-results []
|
||||
[search-text [:get :contact-list-search-text]
|
||||
contacts [:contacts-with-letters]]
|
||||
[view st/search-container
|
||||
[status-bar]
|
||||
[toolbar {:nav-action (act/back #(dispatch [:navigate-back]))
|
||||
:title search-text
|
||||
:style (get-in platform-specific [:component-styles :toolbar])}]
|
||||
(if (empty? contacts)
|
||||
[view st/search-empty-view
|
||||
;; todo change icon
|
||||
[icon :group_big st/empty-contacts-icon]
|
||||
[text {:style st/empty-contacts-text}
|
||||
"No contacts found"]]
|
||||
[list-view {:dataSource (to-datasource contacts)
|
||||
:renderRow (fn [row _ _]
|
||||
(list-item [contact-view {:contact row
|
||||
:letter? true
|
||||
:extended? true}]))}])])
|
|
@ -10,17 +10,19 @@
|
|||
color-gray2]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background2]]))
|
||||
|
||||
(def contacts-list-container
|
||||
{:flex 1})
|
||||
;; Contacts list
|
||||
|
||||
(def toolbar-shadow
|
||||
{:height 2
|
||||
:backgroundColor toolbar-background2})
|
||||
{:height 2
|
||||
:background-color toolbar-background2})
|
||||
|
||||
(def contact-groups
|
||||
{:flex 1
|
||||
:background-color toolbar-background2})
|
||||
|
||||
(def contacts-list-container
|
||||
{:flex 1})
|
||||
|
||||
(def empty-contact-groups
|
||||
(merge contact-groups
|
||||
{:align-items :center
|
||||
|
@ -170,7 +172,7 @@
|
|||
{:width 4
|
||||
:height 16})
|
||||
|
||||
; new contact
|
||||
; New contact
|
||||
|
||||
(def contact-form-container
|
||||
{:flex 1
|
||||
|
@ -222,3 +224,17 @@
|
|||
:margin-top 18
|
||||
:width 20
|
||||
:height 20})
|
||||
|
||||
;; Contacts search
|
||||
|
||||
(def search-container
|
||||
{:flex 1
|
||||
:background-color color-white})
|
||||
|
||||
(def search-empty-view
|
||||
{:flex 1
|
||||
:background-color color-white
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.contacts.subs
|
||||
(:require-macros [reagent.ratom :refer [reaction]])
|
||||
(:require [re-frame.core :refer [register-sub subscribe]]
|
||||
[clojure.string :as str]
|
||||
[status-im.utils.identicon :refer [identicon]]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
|
@ -34,7 +35,6 @@
|
|||
(let [contacts (subscribe [:all-added-contacts])]
|
||||
(reaction (filter :dapp? @contacts)))))
|
||||
|
||||
|
||||
(register-sub :get-added-people-with-limit
|
||||
(fn [_ [_ limit]]
|
||||
(let [contacts (subscribe [:all-added-people])]
|
||||
|
|
|
@ -7,8 +7,11 @@
|
|||
(defn is-address? [s]
|
||||
(.isAddress web3.prototype s))
|
||||
|
||||
(defn unique-identity? [identity]
|
||||
(not (contacts/exists? identity)))
|
||||
(defn contact-can-be-added? [identity]
|
||||
(if (contacts/exists? identity)
|
||||
(-> (contacts/get-by-id identity)
|
||||
(get :pending))
|
||||
true))
|
||||
|
||||
(defn valid-length? [identity]
|
||||
(let [length (count identity)]
|
||||
|
@ -18,11 +21,11 @@
|
|||
(is-address? identity))))
|
||||
|
||||
(s/def ::identity-length valid-length?)
|
||||
(s/def ::unique-identity unique-identity?)
|
||||
(s/def ::contact-can-be-added contact-can-be-added?)
|
||||
(s/def ::not-empty-string (s/and string? not-empty))
|
||||
(s/def ::name ::not-empty-string)
|
||||
(s/def ::whisper-identity (s/and ::not-empty-string
|
||||
::unique-identity
|
||||
::contact-can-be-added
|
||||
::identity-length))
|
||||
|
||||
(s/def ::contact (s/keys :req-un [::name ::whisper-identity]
|
||||
|
|
|
@ -3,37 +3,31 @@
|
|||
(:require [status-im.components.react :refer [view text icon touchable-highlight]]
|
||||
[re-frame.core :refer [dispatch]]
|
||||
[status-im.contacts.styles :as st]
|
||||
[status-im.contacts.views.contact-inner :refer [contact-inner-view]]))
|
||||
[status-im.contacts.views.contact-inner :refer [contact-inner-view]]
|
||||
[status-im.utils.platform :refer [platform-specific]]))
|
||||
|
||||
(defn on-press [{:keys [whisper-identity]}]
|
||||
#(dispatch [:start-chat whisper-identity {} :navigation-replace]))
|
||||
(defn- on-press [{:keys [whisper-identity]}]
|
||||
(dispatch [:start-chat whisper-identity {} :navigation-replace]))
|
||||
|
||||
(defn- more-on-press [contact]
|
||||
(dispatch [:open-contact-menu (:list-selection-fn platform-specific) contact]))
|
||||
|
||||
(defn letter-view [letter]
|
||||
[view st/letter-container
|
||||
(when letter
|
||||
[text {:style st/letter-text} letter])])
|
||||
|
||||
(defview contact-view-with-letter [{:keys [whisper-identity letter] :as contact} click-handler action params]
|
||||
[touchable-highlight
|
||||
{:onPress #(click-handler contact action params)}
|
||||
[view st/contact-container
|
||||
[letter-view letter]
|
||||
[contact-inner-view contact]]])
|
||||
|
||||
(defview contact-view [{:keys [whisper-identity] :as contact}]
|
||||
(defview contact-view [{{:keys [whisper-identity letter dapp?] :as contact} :contact
|
||||
:keys [extended? letter? on-click more-on-click info]}]
|
||||
[chat [:get-chat whisper-identity]]
|
||||
[touchable-highlight
|
||||
{:onPress (on-press contact)}
|
||||
[view st/contact-container
|
||||
[contact-inner-view contact]]])
|
||||
|
||||
(defview contact-extended-view [{:keys [whisper-identity] :as contact} info click-handler more-click-handler]
|
||||
[chat [:get-chat whisper-identity]]
|
||||
[touchable-highlight
|
||||
{:onPress click-handler}
|
||||
{:on-press #((or on-click on-press) contact)}
|
||||
[view st/contact-container
|
||||
(when letter?
|
||||
[letter-view letter])
|
||||
[contact-inner-view contact info]
|
||||
[touchable-highlight
|
||||
{:on-press more-click-handler}
|
||||
[view st/more-btn
|
||||
[icon :more_vertical st/more-btn-icon]]]]])
|
||||
(when (and extended? (not dapp?))
|
||||
[touchable-highlight
|
||||
{:on-press #((or more-on-click more-on-press) contact)}
|
||||
[view st/more-btn
|
||||
[icon :more_vertical st/more-btn-icon]]])]])
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
touchable-highlight
|
||||
list-view
|
||||
list-item]]
|
||||
[status-im.contacts.views.contact :refer [contact-view
|
||||
on-press
|
||||
contact-view-with-letter]]
|
||||
[status-im.contacts.views.contact :refer [contact-view]]
|
||||
[status-im.components.text-field.view :refer [text-field]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background1]]
|
||||
[status-im.components.drawer.view :refer [drawer-view open-drawer]]
|
||||
[status-im.components.styles :refer [icon-search
|
||||
|
@ -42,11 +41,10 @@
|
|||
(defn render-row [chat-modal click-handler action params]
|
||||
(fn [row _ _]
|
||||
(list-item
|
||||
(if chat-modal
|
||||
[contact-view-with-letter row click-handler action params]
|
||||
[contact-view row
|
||||
(or click-handler
|
||||
(on-press row))]))))
|
||||
[contact-view {:contact row
|
||||
:letter? chat-modal
|
||||
:on-click (if click-handler
|
||||
#(click-handler row action params))}])))
|
||||
|
||||
(defn contact-list-entry [{:keys [click-handler icon icon-style label]}]
|
||||
[touchable-highlight
|
||||
|
@ -71,14 +69,10 @@
|
|||
:t/contacts-group-dapps
|
||||
:t/contacts-group-new-chat)))
|
||||
:nav-action (when modal
|
||||
{:handler #(dispatch [:navigate-back])
|
||||
:image {:source {:uri :icon_back}
|
||||
:style icon-back}})
|
||||
(act/back #(dispatch [:navigate-back])))
|
||||
:background-color toolbar-background1
|
||||
:style (get-in platform-specific [:component-styles :toolbar])
|
||||
:actions [{:image {:source {:uri :icon_search}
|
||||
:style icon-search}
|
||||
:handler (fn [])}]}]])
|
||||
:actions [(act/search #())]}]])
|
||||
|
||||
(defview contact-list []
|
||||
[contacts [:contacts-with-letters]
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
[status-im.utils.identicon :refer [identicon]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-title-container
|
||||
toolbar-title-text
|
||||
toolbar-background1]]
|
||||
|
@ -24,6 +25,7 @@
|
|||
[cljs.spec :as s]
|
||||
[status-im.contacts.validations :as v]
|
||||
[status-im.contacts.styles :as st]
|
||||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.utils.gfycat.core :refer [generate-gfy]]
|
||||
[status-im.utils.hex :refer [normalize-hex]]
|
||||
[status-im.utils.platform :refer [platform-specific]]))
|
||||
|
@ -44,11 +46,15 @@
|
|||
:address id
|
||||
:photo-path (identicon whisper-identity)
|
||||
:whisper-identity whisper-identity}]
|
||||
(dispatch [:add-new-contact contact]))
|
||||
(if (contacts/exists? whisper-identity)
|
||||
(dispatch [:add-pending-contact whisper-identity])
|
||||
(dispatch [:add-new-contact contact])))
|
||||
(dispatch [:set :new-contact-public-key-error (label :t/unknown-address)]))))
|
||||
(dispatch [:add-new-contact {:name (generate-gfy)
|
||||
:photo-path (identicon id)
|
||||
:whisper-identity id}])))
|
||||
(if (contacts/exists? id)
|
||||
(dispatch [:add-pending-contact id])
|
||||
(dispatch [:add-new-contact {:name (generate-gfy)
|
||||
:photo-path (identicon id)
|
||||
:whisper-identity id}]))))
|
||||
|
||||
(defn- validation-error-message
|
||||
[whisper-identity {:keys [address public-key]} error]
|
||||
|
@ -57,7 +63,7 @@
|
|||
(normalize-hex whisper-identity))
|
||||
(label :t/can-not-add-yourself)
|
||||
|
||||
(not (s/valid? ::v/unique-identity whisper-identity))
|
||||
(not (s/valid? ::v/contact-can-be-added whisper-identity))
|
||||
(label :t/contact-already-added)
|
||||
|
||||
(not (s/valid? ::v/whisper-identity whisper-identity))
|
||||
|
@ -103,9 +109,7 @@
|
|||
[status-bar]
|
||||
[toolbar {:background-color toolbar-background1
|
||||
:style (get-in platform-specific [:component-styles :toolbar])
|
||||
:nav-action {:image {:source {:uri :icon_back}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:nav-action (act/back #(dispatch [:navigate-back]))
|
||||
:title (label :t/add-new-contact)
|
||||
:actions (toolbar-actions new-contact-identity account error)}]
|
||||
[view st/form-container
|
||||
|
|
|
@ -9,26 +9,25 @@
|
|||
|
||||
(defn get-by-id
|
||||
[whisper-identity]
|
||||
(data-store/get-by-id whisper-identity))
|
||||
(data-store/get-by-id-cljs whisper-identity))
|
||||
|
||||
(defn save
|
||||
[{:keys [whisper-identity pending] :as contact}]
|
||||
(let [{pending-db :pending
|
||||
:as contact-db} (data-store/get-by-id whisper-identity)
|
||||
contact (assoc contact :pending (boolean (if contact-db
|
||||
;; TODO:
|
||||
;; this is temporary fix for pending users
|
||||
;; we need to change this (if ...) to (and pending-db pending)
|
||||
(if (nil? pending)
|
||||
pending-db
|
||||
(and pending-db pending))
|
||||
pending)))]
|
||||
contact (assoc contact :pending
|
||||
(boolean (if contact-db
|
||||
(if (nil? pending) pending-db pending)
|
||||
pending)))]
|
||||
(data-store/save contact (if contact-db true false))))
|
||||
|
||||
(defn save-all
|
||||
[contacts]
|
||||
(mapv save contacts))
|
||||
|
||||
(defn delete [contact]
|
||||
(data-store/delete contact))
|
||||
|
||||
(defn exists?
|
||||
[whisper-identity]
|
||||
(data-store/exists? whisper-identity))
|
|
@ -0,0 +1,15 @@
|
|||
(ns status-im.data-store.processed-messages
|
||||
(:require [status-im.data-store.realm.processed-messages :as data-store]
|
||||
[taoensso.timbre :as log])
|
||||
(:refer-clojure :exclude [exists?]))
|
||||
|
||||
(defn get-filtered
|
||||
[condition]
|
||||
(data-store/get-filtered-as-list condition))
|
||||
|
||||
(defn save
|
||||
[processed-message]
|
||||
(data-store/save processed-message))
|
||||
|
||||
(defn delete [condition]
|
||||
(data-store/delete condition))
|
|
@ -14,12 +14,21 @@
|
|||
|
||||
(defn get-by-id
|
||||
[whisper-identity]
|
||||
(realm/get-one-by-field-clj @realm/account-realm :contact :whisper-identity whisper-identity))
|
||||
(realm/get-one-by-field @realm/account-realm :contact :whisper-identity whisper-identity))
|
||||
|
||||
(defn get-by-id-cljs
|
||||
[whisper-identity]
|
||||
(some-> (get-by-id whisper-identity)
|
||||
(js->clj :keywordize-keys true)))
|
||||
|
||||
(defn save
|
||||
[contact update?]
|
||||
(realm/save @realm/account-realm :contact contact update?))
|
||||
|
||||
(defn delete
|
||||
[{:keys [whisper-identity]}]
|
||||
(realm/delete @realm/account-realm (get-by-id whisper-identity)))
|
||||
|
||||
(defn exists?
|
||||
[whisper-identity]
|
||||
(realm/exists? @realm/account-realm :contact {:whisper-identity whisper-identity}))
|
|
@ -0,0 +1,25 @@
|
|||
(ns status-im.data-store.realm.processed-messages
|
||||
(:require [status-im.data-store.realm.core :as realm])
|
||||
(:refer-clojure :exclude [exists?]))
|
||||
|
||||
(defn get-all
|
||||
[]
|
||||
(-> (realm/get-all @realm/account-realm :processed-message)
|
||||
(realm/sorted :ttl :asc)))
|
||||
|
||||
(defn get-filtered
|
||||
[condition]
|
||||
(realm/filtered (get-all) condition))
|
||||
|
||||
(defn get-filtered-as-list
|
||||
[condition]
|
||||
(-> (get-filtered condition)
|
||||
realm/realm-collection->list))
|
||||
|
||||
(defn save
|
||||
[processed-message]
|
||||
(realm/save @realm/account-realm :processed-message processed-message))
|
||||
|
||||
(defn delete
|
||||
[condition]
|
||||
(realm/delete @realm/account-realm (get-filtered condition)))
|
|
@ -7,6 +7,7 @@
|
|||
[status-im.data-store.realm.schemas.account.v1.kv-store :as kv-store]
|
||||
[status-im.data-store.realm.schemas.account.v1.message :as message]
|
||||
[status-im.data-store.realm.schemas.account.v1.pending-message :as pending-message]
|
||||
[status-im.data-store.realm.schemas.account.v1.processed-message :as processed-message]
|
||||
[status-im.data-store.realm.schemas.account.v1.request :as request]
|
||||
[status-im.data-store.realm.schemas.account.v1.tag :as tag]
|
||||
[status-im.data-store.realm.schemas.account.v1.user-status :as user-status]
|
||||
|
@ -20,6 +21,7 @@
|
|||
kv-store/schema
|
||||
message/schema
|
||||
pending-message/schema
|
||||
processed-message/schema
|
||||
request/schema
|
||||
tag/schema
|
||||
user-status/schema])
|
||||
|
@ -34,6 +36,7 @@
|
|||
(kv-store/migration old-realm new-realm)
|
||||
(message/migration old-realm new-realm)
|
||||
(pending-message/migration old-realm new-realm)
|
||||
(processed-message/migration old-realm new-realm)
|
||||
(request/migration old-realm new-realm)
|
||||
(tag/migration old-realm new-realm)
|
||||
(user-status/migration old-realm new-realm))
|
|
@ -0,0 +1,13 @@
|
|||
(ns status-im.data-store.realm.schemas.account.v1.processed-message
|
||||
(:require [taoensso.timbre :as log]))
|
||||
|
||||
(def schema {:name :processed-message
|
||||
:primaryKey :id
|
||||
:properties {:id :string
|
||||
:message-id :string
|
||||
:type {:type "string"
|
||||
:optional true}
|
||||
:ttl :int}})
|
||||
|
||||
(defn migration [old-realm new-realm]
|
||||
(log/debug "migrating processed-message schema"))
|
|
@ -25,8 +25,8 @@
|
|||
|
||||
(defmethod nav/preload-data! :discover
|
||||
[db _]
|
||||
(dispatch [:set :discover-show-search? false])
|
||||
(-> db
|
||||
(assoc-in [:toolbar-search :show] nil)
|
||||
(assoc :tags (discoveries/get-all-tags))
|
||||
(assoc :discoveries (->> (discoveries/get-all :desc)
|
||||
(map (fn [{:keys [message-id] :as discover}]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
(ns status-im.discover.screen
|
||||
(:require-macros [status-im.utils.views :refer [defview]])
|
||||
(:require
|
||||
[reagent.core :as r]
|
||||
[re-frame.core :refer [dispatch subscribe]]
|
||||
[clojure.string :as str]
|
||||
[status-im.components.react :refer [view
|
||||
|
@ -8,52 +9,33 @@
|
|||
text
|
||||
text-input
|
||||
icon]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar-with-search]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.drawer.view :refer [open-drawer]]
|
||||
[status-im.discover.styles :as st]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.components.carousel.carousel :refer [carousel]]
|
||||
[status-im.discover.views.popular-list :refer [discover-popular-list]]
|
||||
[status-im.discover.views.discover-list-item :refer [discover-list-item]]
|
||||
[status-im.contacts.styles :as contacts-styles]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[reagent.core :as r]))
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.discover.styles :as st]
|
||||
[status-im.contacts.styles :as contacts-st]))
|
||||
|
||||
(defn get-hashtags [status]
|
||||
(let [hashtags (map #(str/lower-case (str/replace % #"#" "")) (re-seq #"[^ !?,;:.]+" status))]
|
||||
(or hashtags [])))
|
||||
|
||||
(defn title-content [show-search?]
|
||||
[view st/discover-toolbar-content
|
||||
(if show-search?
|
||||
[text-input {:style st/discover-search-input
|
||||
:auto-focus true
|
||||
:placeholder (label :t/search-tags)
|
||||
:on-blur (fn [e]
|
||||
(dispatch [:set :discover-show-search? false]))
|
||||
:on-submit-editing (fn [e]
|
||||
(let [search (aget e "nativeEvent" "text")
|
||||
hashtags (get-hashtags search)]
|
||||
(dispatch [:set :discover-search-tags hashtags])
|
||||
(dispatch [:navigate-to :discover-search-results])))}]
|
||||
[view
|
||||
[text {:style st/discover-title
|
||||
:font :toolbar-title}
|
||||
(label :t/discover)]])])
|
||||
|
||||
(defn toogle-search [current-value]
|
||||
(dispatch [:set :discover-show-search? (not current-value)]))
|
||||
|
||||
(defn discover-toolbar [show-search?]
|
||||
[toolbar
|
||||
{:style st/discover-toolbar
|
||||
:nav-action {:image {:source {:uri :icon_hamburger}
|
||||
:style st/hamburger-icon}
|
||||
:handler open-drawer}
|
||||
:custom-content [title-content show-search?]
|
||||
:actions [{:image {:source {:uri :icon_search}
|
||||
:style st/search-icon}
|
||||
:handler #(toogle-search show-search?)}]}])
|
||||
(defn toolbar-view [show-search?]
|
||||
[toolbar-with-search
|
||||
{:show-search? show-search?
|
||||
:search-key :discover
|
||||
:title (label :t/discover)
|
||||
:search-placeholder (label :t/search-tags)
|
||||
:nav-action (act/hamburger open-drawer)
|
||||
:on-search-submit (fn [text]
|
||||
(when-not (str/blank? text)
|
||||
(let [hashtags (get-hashtags text)]
|
||||
(dispatch [:set :discover-search-tags hashtags])
|
||||
(dispatch [:navigate-to :discover-search-results]))))}])
|
||||
|
||||
(defn title [label-kw spacing?]
|
||||
[view st/section-spacing
|
||||
|
@ -91,19 +73,20 @@
|
|||
:current-account current-account}]))]]))
|
||||
|
||||
(defview discover [current-view?]
|
||||
[show-search? [:get :discover-show-search?]
|
||||
[show-search [:get-in [:toolbar-search :show]]
|
||||
contacts [:get :contacts]
|
||||
current-account [:get-current-account]
|
||||
discoveries [:get-recent-discoveries]]
|
||||
[view st/discover-container
|
||||
[discover-toolbar (and current-view? show-search?)]
|
||||
[toolbar-view (and current-view?
|
||||
(= show-search :discover))]
|
||||
(if discoveries
|
||||
[scroll-view st/scroll-view-container
|
||||
[discover-popular {:contacts contacts
|
||||
:current-account current-account}]
|
||||
[discover-recent {:current-account current-account}]]
|
||||
[view contacts-styles/empty-contact-groups
|
||||
[view contacts-st/empty-contact-groups
|
||||
;; todo change icon
|
||||
[icon :group_big contacts-styles/empty-contacts-icon]
|
||||
[text {:style contacts-styles/empty-contacts-text}
|
||||
[icon :group_big contacts-st/empty-contacts-icon]
|
||||
[text {:style contacts-st/empty-contacts-text}
|
||||
(label :t/no-statuses-discovered)]])])
|
||||
|
|
|
@ -9,12 +9,13 @@
|
|||
list-view
|
||||
list-item
|
||||
scroll-view]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.discover.views.discover-list-item :refer [discover-list-item]]
|
||||
[status-im.discover.styles :as st]
|
||||
[status-im.utils.platform :refer [platform-specific]]
|
||||
[status-im.contacts.styles :as contacts-styles]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.discover.styles :as st]
|
||||
[status-im.contacts.styles :as contacts-st]
|
||||
[taoensso.timbre :as log]))
|
||||
|
||||
(defn render-separator [_ row-id _]
|
||||
|
@ -43,20 +44,19 @@
|
|||
datasource (to-datasource discoveries)]
|
||||
[view st/discover-tag-container
|
||||
[status-bar]
|
||||
[toolbar {:nav-action {:image {:source {:uri :icon_back}
|
||||
:style st/icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
[toolbar {:nav-action (act/back #(dispatch [:navigate-back]))
|
||||
:custom-content (title-content tags)
|
||||
:style st/discover-tag-toolbar}]
|
||||
(if (empty? discoveries)
|
||||
[view st/empty-view
|
||||
;; todo change icon
|
||||
[icon :group_big contacts-styles/empty-contacts-icon]
|
||||
[text {:style contacts-styles/empty-contacts-text}
|
||||
[icon :group_big contacts-st/empty-contacts-icon]
|
||||
[text {:style contacts-st/empty-contacts-text}
|
||||
(label :t/no-statuses-found)]]
|
||||
[list-view {:dataSource datasource
|
||||
:renderRow (fn [row _ _]
|
||||
(list-item [discover-list-item {:message row
|
||||
:current-account current-account}]))
|
||||
(list-item [discover-list-item
|
||||
{:message row
|
||||
:current-account current-account}]))
|
||||
:renderSeparator render-separator
|
||||
:style st/recent-list}])]))
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
(ns status-im.discover.styles
|
||||
(:require [status-im.components.styles :refer [color-gray2
|
||||
color-white]]
|
||||
color-white
|
||||
color-light-gray]]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background2]]))
|
||||
|
||||
;; common
|
||||
;; Common
|
||||
|
||||
(def row-separator
|
||||
{:border-bottom-width 1
|
||||
|
@ -22,30 +23,6 @@
|
|||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
;; Toolbar
|
||||
|
||||
(def discover-toolbar-content
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def discover-toolbar
|
||||
{:background-color toolbar-background2
|
||||
:elevation 0})
|
||||
|
||||
(def discover-search-input
|
||||
{:flex 1
|
||||
:align-self "stretch"
|
||||
:margin-left 18
|
||||
:font-size 14
|
||||
:color "#7099e6"})
|
||||
|
||||
(def discover-title
|
||||
{:color "#000000de"
|
||||
:align-self :center
|
||||
:text-align :center
|
||||
:font-size 16})
|
||||
|
||||
(def section-spacing
|
||||
{:padding 16})
|
||||
|
||||
|
@ -134,7 +111,7 @@
|
|||
|
||||
(def discover-tag-container
|
||||
{:flex 1
|
||||
:backgroundColor "#eef2f5"})
|
||||
:backgroundColor color-light-gray})
|
||||
|
||||
(def tag-title-scroll
|
||||
{:flex 1
|
||||
|
@ -165,10 +142,6 @@
|
|||
{:flex 1
|
||||
:backgroundColor color-white})
|
||||
|
||||
(def hamburger-icon
|
||||
{:width 16
|
||||
:height 12})
|
||||
|
||||
(def search-icon
|
||||
{:width 17
|
||||
:height 17})
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
(ns status-im.group-settings.views.member
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[status-im.contacts.views.contact :refer [contact-extended-view]]
|
||||
[status-im.contacts.views.contact :refer [contact-view]]
|
||||
[status-im.i18n :refer [label]]))
|
||||
|
||||
(defn member-view [{:keys [whisper-identity role] :as contact}]
|
||||
;; TODO implement :role property for group chat contact
|
||||
[contact-extended-view contact role
|
||||
#(dispatch [:set :selected-participants #{whisper-identity}])])
|
||||
[contact-view
|
||||
{:contact contact
|
||||
:extended? true
|
||||
:info role
|
||||
:on-click #(dispatch [:set :selected-participants #{whisper-identity}])}])
|
||||
|
|
|
@ -68,6 +68,7 @@
|
|||
(u/side-effect!
|
||||
(fn [_ [_ address]]
|
||||
(dispatch [:initialize-account-db])
|
||||
(dispatch [:load-processed-messages])
|
||||
(dispatch [:initialize-protocol address])
|
||||
(dispatch [:initialize-sync-listener])
|
||||
(dispatch [:initialize-chats])
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
orientation
|
||||
splash-screen]]
|
||||
[status-im.components.main-tabs :refer [main-tabs]]
|
||||
[status-im.contacts.search-results :refer [contacts-search-results]]
|
||||
[status-im.contacts.views.contact-list :refer [contact-list]]
|
||||
[status-im.contacts.views.new-contact :refer [new-contact]]
|
||||
[status-im.qr-scanner.screen :refer [qr-scanner]]
|
||||
|
@ -82,6 +83,7 @@
|
|||
:new-group new-group
|
||||
:group-settings group-settings
|
||||
:contact-list main-tabs
|
||||
:contact-list-search-results contacts-search-results
|
||||
:group-contacts contact-list
|
||||
:new-contact new-contact
|
||||
:qr-scanner qr-scanner
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
[status-im.components.icons.custom-icons :refer [ion-icon]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background1]]
|
||||
[status-im.utils.image-processing :refer [img->base64]]
|
||||
[status-im.profile.photo-capture.styles :as st]
|
||||
|
@ -35,9 +36,7 @@
|
|||
[view st/container
|
||||
[status-bar]
|
||||
[toolbar {:title (label :t/image-source-title)
|
||||
:nav-action {:image {:source {:uri :icon_back}
|
||||
:style icon-back}
|
||||
:handler #(dispatch [:navigate-back])}
|
||||
:nav-action (act/back #(dispatch [:navigate-back]))
|
||||
:background-color toolbar-background1}]
|
||||
[camera {:style {:flex 1}
|
||||
:aspect (:fill aspects)
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
;; discoveries
|
||||
(def watch-user! discoveries/watch-user!)
|
||||
(def stop-watching-user! discoveries/stop-watching-user!)
|
||||
(def contact-request! discoveries/contact-request!)
|
||||
(def broadcast-profile! discoveries/broadcast-profile!)
|
||||
(def send-status! discoveries/send-status!)
|
||||
|
|
|
@ -46,6 +46,13 @@
|
|||
:topics [(make-discover-topic identity)]}
|
||||
(l/message-listener (dissoc options :identity))))
|
||||
|
||||
(defn stop-watching-user!
|
||||
[{:keys [web3 identity] :as options}]
|
||||
(f/remove-filter!
|
||||
web3
|
||||
{:from identity
|
||||
:topics [(make-discover-topic identity)]}))
|
||||
|
||||
(s/def :contact-request/contact map?)
|
||||
|
||||
(s/def :contact-request/payload
|
||||
|
|
|
@ -5,12 +5,15 @@
|
|||
[status-im.data-store.contacts :as contacts]
|
||||
[status-im.data-store.messages :as messages]
|
||||
[status-im.data-store.pending-messages :as pending-messages]
|
||||
[status-im.data-store.processed-messages :as processed-messages]
|
||||
[status-im.data-store.chats :as chats]
|
||||
[status-im.protocol.core :as protocol]
|
||||
[status-im.constants :refer [text-content-type
|
||||
blocks-per-hour]]
|
||||
[status-im.i18n :refer [label]]
|
||||
[status-im.utils.random :as random]
|
||||
[status-im.protocol.message-cache :as cache]
|
||||
[status-im.utils.datetime :as dt]
|
||||
[taoensso.timbre :as log :refer-macros [debug]]
|
||||
[status-im.constants :as c]
|
||||
[status-im.components.status :as status]))
|
||||
|
@ -77,33 +80,41 @@
|
|||
|
||||
(register-handler :incoming-message
|
||||
(u/side-effect!
|
||||
(fn [_ [_ type {:keys [payload] :as message}]]
|
||||
(debug :incoming-message type)
|
||||
(case type
|
||||
:message (dispatch [:received-protocol-message! message])
|
||||
:group-message (dispatch [:received-protocol-message! message])
|
||||
:ack (if (#{:message :group-message} (:type payload))
|
||||
(dispatch [:message-delivered message])
|
||||
(dispatch [:pending-message-remove message]))
|
||||
:seen (dispatch [:message-seen message])
|
||||
:group-invitation (dispatch [:group-chat-invite-received message])
|
||||
:update-group (dispatch [:update-group-message message])
|
||||
:add-group-identity (dispatch [:participant-invited-to-group message])
|
||||
:remove-group-identity (dispatch [:participant-removed-from-group message])
|
||||
:leave-group (dispatch [:participant-left-group message])
|
||||
:contact-request (dispatch [:contact-request-received message])
|
||||
:discover (dispatch [:status-received message])
|
||||
:discoveries-request (dispatch [:discoveries-request-received message])
|
||||
:discoveries-response (dispatch [:discoveries-response-received message])
|
||||
:profile (dispatch [:contact-update-received message])
|
||||
:online (dispatch [:contact-online-received message])
|
||||
:pending (dispatch [:pending-message-upsert message])
|
||||
:sent (let [{:keys [to id group-id]} message
|
||||
message' {:from to
|
||||
:payload {:message-id id
|
||||
:group-id group-id}}]
|
||||
(dispatch [:message-sent message']))
|
||||
(debug "Unknown message type" type)))))
|
||||
(fn [_ [_ type {:keys [payload ttl id] :as message}]]
|
||||
(let [message-id (or id (:message-id payload))]
|
||||
(when-not (cache/exists? message-id type)
|
||||
(let [ttl-s (* 1000 (or ttl 120))
|
||||
processed-message {:id (random/id)
|
||||
:message-id message-id
|
||||
:type type
|
||||
:ttl (+ (dt/now-ms) ttl-s)}]
|
||||
(cache/add! processed-message)
|
||||
(processed-messages/save processed-message))
|
||||
(case type
|
||||
:message (dispatch [:received-protocol-message! message])
|
||||
:group-message (dispatch [:received-protocol-message! message])
|
||||
:ack (if (#{:message :group-message} (:type payload))
|
||||
(dispatch [:message-delivered message])
|
||||
(dispatch [:pending-message-remove message]))
|
||||
:seen (dispatch [:message-seen message])
|
||||
:group-invitation (dispatch [:group-chat-invite-received message])
|
||||
:update-group (dispatch [:update-group-message message])
|
||||
:add-group-identity (dispatch [:participant-invited-to-group message])
|
||||
:remove-group-identity (dispatch [:participant-removed-from-group message])
|
||||
:leave-group (dispatch [:participant-left-group message])
|
||||
:contact-request (dispatch [:contact-request-received message])
|
||||
:discover (dispatch [:status-received message])
|
||||
:discoveries-request (dispatch [:discoveries-request-received message])
|
||||
:discoveries-response (dispatch [:discoveries-response-received message])
|
||||
:profile (dispatch [:contact-update-received message])
|
||||
:online (dispatch [:contact-online-received message])
|
||||
:pending (dispatch [:pending-message-upsert message])
|
||||
:sent (let [{:keys [to id group-id]} message
|
||||
message' {:from to
|
||||
:payload {:message-id id
|
||||
:group-id group-id}}]
|
||||
(dispatch [:message-sent message']))
|
||||
(debug "Unknown message type" type)))))))
|
||||
|
||||
(defn system-message
|
||||
([message-id timestamp content]
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
(ns status-im.protocol.message-cache)
|
||||
|
||||
(defonce messages-set (atom #{}))
|
||||
(defonce messages-map (atom {}))
|
||||
|
||||
(defn init!
|
||||
[messages]
|
||||
(reset! messages-set (into #{} messages))
|
||||
(reset! messages-map (->> messages
|
||||
(map (fn [{:keys [message-id type] :as message}]
|
||||
[[message-id type] message]))
|
||||
(into {}))))
|
||||
|
||||
(defn add!
|
||||
[{:keys [message-id type] :as message}]
|
||||
(swap! messages-set conj message)
|
||||
(swap! messages-map conj [[message-id type] message]))
|
||||
|
||||
(defn exists?
|
||||
[message-id type]
|
||||
(get @messages-map [message-id type]))
|
|
@ -28,7 +28,8 @@
|
|||
(assoc :content content')
|
||||
prn-str
|
||||
u/from-utf8)]
|
||||
(-> message (select-keys [:from :to :topics :ttl])
|
||||
(-> message
|
||||
(select-keys [:from :to :topics :ttl])
|
||||
(assoc :payload payload'))))
|
||||
|
||||
(s/def :shh/pending-message
|
||||
|
@ -110,7 +111,7 @@
|
|||
(let [message (get-in messages [id to])
|
||||
message' (when message
|
||||
(assoc message :was-sent? true
|
||||
:attemps 1))]
|
||||
:attempts 1))]
|
||||
(if message'
|
||||
(assoc-in messages [id to] message')
|
||||
messages))))]
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
icon-back]]
|
||||
[status-im.components.status-bar :refer [status-bar]]
|
||||
[status-im.components.toolbar.view :refer [toolbar]]
|
||||
[status-im.components.toolbar.actions :as act]
|
||||
[status-im.components.toolbar.styles :refer [toolbar-background1]]
|
||||
[status-im.qr-scanner.styles :as st]
|
||||
[status-im.utils.types :refer [json->clj]]
|
||||
|
@ -20,12 +21,7 @@
|
|||
[toolbar {:title title
|
||||
:background-color toolbar-background1
|
||||
:nav-action (when modal
|
||||
{:handler #(dispatch [:navigate-back])
|
||||
:image {:source {:uri :icon_back}
|
||||
:style icon-back}})
|
||||
:actions [{:image {:source {:uri :icon_lock_white}
|
||||
:style icon-search}
|
||||
:handler #()}]}]])
|
||||
(act/back #(dispatch [:navigate-back])))}]])
|
||||
|
||||
(defview qr-scanner []
|
||||
[identifier [:get :current-qr-context]]
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
:chat-name "Chat name"
|
||||
:notifications-title "Notifications and sounds"
|
||||
:offline "Offline"
|
||||
:search-for "Search for..."
|
||||
:cancel "Cancel"
|
||||
|
||||
;drawer
|
||||
:invite-friends "Invite friends"
|
||||
|
@ -108,7 +110,6 @@
|
|||
:new-group-chat "New group chat"
|
||||
|
||||
;discover
|
||||
|
||||
:discover "Discover"
|
||||
:none "None"
|
||||
:search-tags "Type your search tags here"
|
||||
|
@ -123,6 +124,7 @@
|
|||
;contacts
|
||||
:contacts "Contacts"
|
||||
:new-contact "New Contact"
|
||||
:remove-contact "Remove contact"
|
||||
:show-all "SHOW ALL"
|
||||
:contacts-group-dapps "ÐApps"
|
||||
:contacts-group-people "People"
|
||||
|
|
Loading…
Reference in New Issue