[#7454] fix add basic copy to public chat empty screen state + related issues/feature regarding chat message-views intro screens for all chats types
[#7454] fix add basic copy to public chat empty screen state + chat messages-views intro screens for all chats Signed-off-by: Igor Mandrigin <i@mandrigin.ru>
This commit is contained in:
parent
c9a8fb2684
commit
6aae0b76b9
|
@ -17,10 +17,16 @@
|
|||
(let [pending-invite-inviter-name
|
||||
(group-chats.db/get-pending-invite-inviter-name contacts
|
||||
chat
|
||||
current-public-key)]
|
||||
current-public-key)
|
||||
inviter-name
|
||||
(group-chats.db/get-inviter-name contacts
|
||||
chat
|
||||
current-public-key)]
|
||||
(cond-> chat
|
||||
pending-invite-inviter-name
|
||||
(assoc :pending-invite-inviter-name pending-invite-inviter-name)
|
||||
inviter-name
|
||||
(assoc :inviter-name inviter-name)
|
||||
:always
|
||||
(assoc :chat-name (group-chat-name chat))))
|
||||
(let [{contact-name :name :as contact}
|
||||
|
|
|
@ -56,6 +56,22 @@
|
|||
[{:keys [current-chat-id] :as db} ui-element]
|
||||
(update-in db [:chat-ui-props current-chat-id ui-element] not))
|
||||
|
||||
(defn join-time-messages-checked
|
||||
"The key :might-have-join-time-messages? in public chats signals that
|
||||
the public chat is freshly (re)created and requests for messages to the
|
||||
mailserver for the topic has not completed yet. Likewise, the key
|
||||
:join-time-mail-request-id is associated a little bit after, to signal that
|
||||
the request to mailserver was a success. When request is signalled complete
|
||||
by mailserver, corresponding event :chat.ui/join-time-messages-checked
|
||||
dissociates these two fileds via this function, thereby signalling that the
|
||||
public chat is not fresh anymore."
|
||||
[{:keys [chats] :as db} chat-id]
|
||||
(if (:might-have-join-time-messages? (get chats chat-id))
|
||||
(-> db
|
||||
(update-in [:chats chat-id] dissoc :join-time-mail-request-id)
|
||||
(update-in [:chats chat-id] dissoc :might-have-join-time-messages?))
|
||||
db))
|
||||
|
||||
(defn- create-new-chat
|
||||
[chat-id {:keys [db now]}]
|
||||
(let [name (get-in db [:contacts/contacts chat-id :name])]
|
||||
|
@ -84,14 +100,15 @@
|
|||
"Adds new public group chat to db & realm"
|
||||
[cofx topic]
|
||||
(upsert-chat cofx
|
||||
{:chat-id topic
|
||||
:is-active true
|
||||
:name topic
|
||||
:group-chat true
|
||||
:contacts #{}
|
||||
:public? true
|
||||
:unviewed-messages-count 0
|
||||
:loaded-unviewed-messages-ids #{}}))
|
||||
{:chat-id topic
|
||||
:is-active true
|
||||
:name topic
|
||||
:group-chat true
|
||||
:contacts #{}
|
||||
:public? true
|
||||
:might-have-join-time-messages? true
|
||||
:unviewed-messages-count 0
|
||||
:loaded-unviewed-messages-ids #{}}))
|
||||
|
||||
(fx/defn add-group-chat
|
||||
"Adds new private group chat to db & realm"
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
[status-im.chat.models.message-content :as message-content]
|
||||
[status-im.chat.commands.receiving :as commands-receiving]
|
||||
[status-im.chat.db :as chat.db]
|
||||
[status-im.mailserver.core :as mailserver]
|
||||
[status-im.utils.clocks :as utils.clocks]
|
||||
[status-im.utils.money :as money]
|
||||
[status-im.utils.types :as types]
|
||||
|
@ -287,35 +288,51 @@
|
|||
(apply fx/merge cofx
|
||||
(map (partial update-last-message (:chats db)) chat-ids)))
|
||||
|
||||
(fx/defn declare-syncd-public-chats!
|
||||
[{:keys [db] :as cofx} chat-ids]
|
||||
(apply fx/merge cofx
|
||||
(map (partial chat-model/join-time-messages-checked db) chat-ids)))
|
||||
|
||||
(defn- chat-ids->never-synced-public-chat-ids [chats chat-ids]
|
||||
(let [never-synced-public-chat-ids (mailserver/chats->never-synced-public-chats chats)]
|
||||
(when (seq never-synced-public-chat-ids)
|
||||
(-> never-synced-public-chat-ids
|
||||
(select-keys (vec chat-ids))
|
||||
keys))))
|
||||
|
||||
(fx/defn receive-many
|
||||
[{:keys [now] :as cofx} messages]
|
||||
(let [valid-messages (keep #(when-let [chat-id (extract-chat-id cofx %)]
|
||||
(assoc % :chat-id chat-id)) messages)
|
||||
filtered-messages (filter-messages cofx valid-messages)
|
||||
deduped-messages (:messages filtered-messages)
|
||||
old-id->message (:by-old-message-id filtered-messages)
|
||||
chat->message (group-by :chat-id deduped-messages)
|
||||
chat-ids (keys chat->message)
|
||||
chats-fx-fns (map (fn [chat-id]
|
||||
(let [unviewed-messages-count
|
||||
(calculate-unviewed-messages-count
|
||||
cofx
|
||||
chat-id
|
||||
(get chat->message chat-id))]
|
||||
(chat-model/upsert-chat
|
||||
{:chat-id chat-id
|
||||
:is-active true
|
||||
:timestamp now
|
||||
:unviewed-messages-count unviewed-messages-count})))
|
||||
chat-ids)
|
||||
messages-fx-fns (map #(add-received-message old-id->message %) deduped-messages)
|
||||
groups-fx-fns (map #(update-group-messages chat->message %) chat-ids)]
|
||||
(let [valid-messages (keep #(when-let [chat-id (extract-chat-id cofx %)]
|
||||
(assoc % :chat-id chat-id)) messages)
|
||||
filtered-messages (filter-messages cofx valid-messages)
|
||||
deduped-messages (:messages filtered-messages)
|
||||
old-id->message (:by-old-message-id filtered-messages)
|
||||
chat->message (group-by :chat-id deduped-messages)
|
||||
chat-ids (keys chat->message)
|
||||
never-synced-public-chat-ids (chat-ids->never-synced-public-chat-ids
|
||||
(get-in cofx [:db :chats]) chat-ids)
|
||||
chats-fx-fns (map (fn [chat-id]
|
||||
(let [unviewed-messages-count
|
||||
(calculate-unviewed-messages-count
|
||||
cofx
|
||||
chat-id
|
||||
(get chat->message chat-id))]
|
||||
(chat-model/upsert-chat
|
||||
{:chat-id chat-id
|
||||
:is-active true
|
||||
:timestamp now
|
||||
:unviewed-messages-count unviewed-messages-count})))
|
||||
chat-ids)
|
||||
messages-fx-fns (map #(add-received-message old-id->message %) deduped-messages)
|
||||
groups-fx-fns (map #(update-group-messages chat->message %) chat-ids)]
|
||||
(apply fx/merge cofx (concat chats-fx-fns
|
||||
messages-fx-fns
|
||||
groups-fx-fns
|
||||
(when platform/desktop?
|
||||
[(chat-model/update-dock-badge-label)])
|
||||
[(update-last-messages chat-ids)]))))
|
||||
[(update-last-messages chat-ids)]
|
||||
(when (seq never-synced-public-chat-ids)
|
||||
[(declare-syncd-public-chats! never-synced-public-chat-ids)])))))
|
||||
|
||||
(defn system-message [{:keys [now] :as cofx} {:keys [clock-value chat-id content from]}]
|
||||
(let [{:keys [last-clock-value]} (get-in cofx [:db :chats chat-id])
|
||||
|
|
|
@ -7,8 +7,10 @@
|
|||
[status-im.chat.db :as chat.db]
|
||||
[status-im.models.transactions :as transactions]
|
||||
[status-im.utils.platform :as platform]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs-styles]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]))
|
||||
[status-im.utils.universal-links.core :as links]
|
||||
[status-im.ui.components.bottom-bar.styles :as tabs.styles]
|
||||
[status-im.ui.components.toolbar.styles :as toolbar.styles]
|
||||
[status-im.ui.screens.chat.stickers.styles :as stickers.styles]))
|
||||
|
||||
(re-frame/reg-sub ::chats :chats)
|
||||
(re-frame/reg-sub ::access-scope->command-id :access-scope->command-id)
|
||||
|
@ -53,6 +55,32 @@
|
|||
(fn [chats [_ chat-id]]
|
||||
(get chats chat-id)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/content-layout-height
|
||||
:<- [:get :content-layout-height]
|
||||
:<- [:chats/current-chat-ui-prop :input-height]
|
||||
:<- [:chats/current-chat-ui-prop :input-focused?]
|
||||
:<- [:get :keyboard-height]
|
||||
:<- [:chats/current-chat-ui-prop :show-stickers?]
|
||||
(fn [[home-content-layout-height input-height input-focused? kheight stickers?]]
|
||||
(- (+ home-content-layout-height tabs.styles/tabs-height)
|
||||
(if platform/iphone-x?
|
||||
(* 2 toolbar.styles/toolbar-height)
|
||||
toolbar.styles/toolbar-height)
|
||||
(if input-height input-height 0)
|
||||
(if stickers?
|
||||
(stickers.styles/stickers-panel-height)
|
||||
kheight)
|
||||
(if input-focused?
|
||||
(cond
|
||||
platform/iphone-x? 0
|
||||
platform/ios? tabs.styles/tabs-diff
|
||||
:else 0)
|
||||
(cond
|
||||
platform/iphone-x? (* 2 tabs.styles/minimized-tabs-height)
|
||||
platform/ios? tabs.styles/tabs-height
|
||||
:else tabs.styles/minimized-tabs-height)))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-ui-props
|
||||
:<- [::chat-ui-props]
|
||||
|
@ -100,7 +128,13 @@
|
|||
:<- [:chats/active-chats]
|
||||
:<- [:chats/current-chat-id]
|
||||
(fn [[chats current-chat-id]]
|
||||
(get chats current-chat-id)))
|
||||
(let [current-chat (get chats current-chat-id)
|
||||
messages (:messages current-chat)]
|
||||
(if (empty? messages)
|
||||
(assoc current-chat
|
||||
:universal-link
|
||||
(links/generate-link :public-chat :external current-chat-id))
|
||||
current-chat))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-message
|
||||
|
@ -143,6 +177,17 @@
|
|||
(chat.db/messages-with-datemarks-and-statuses messages message-statuses referenced-messages)
|
||||
chat.db/messages-stream)))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/current-chat-intro-status
|
||||
:<- [:chats/current-chat]
|
||||
:<- [:chats/current-chat-messages]
|
||||
(fn [[{:keys [might-have-join-time-messages?]} messages]]
|
||||
(if might-have-join-time-messages?
|
||||
:loading
|
||||
(if (empty? messages)
|
||||
:empty
|
||||
:messages))))
|
||||
|
||||
(re-frame/reg-sub
|
||||
:chats/available-commands
|
||||
:<- [::get-commands-for-chat]
|
||||
|
|
|
@ -729,6 +729,11 @@
|
|||
(fn [{:keys [db]} [_ kvs]]
|
||||
{:db (chat/set-chat-ui-props db kvs)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/join-time-messages-checked
|
||||
(fn [{:keys [db]} [_ chat-id]]
|
||||
{:db (chat/join-time-messages-checked db chat-id)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:chat.ui/show-message-details
|
||||
(fn [{:keys [db]} [_ details]]
|
||||
|
|
|
@ -44,3 +44,13 @@
|
|||
(let [inviter-pk (get-inviter-pk my-public-key chat)]
|
||||
(get-in contacts [inviter-pk :name]
|
||||
(gfycat/generate-gfy inviter-pk)))))
|
||||
|
||||
(defn get-inviter-name
|
||||
"when the chat is a private group chat in which the user has been
|
||||
invited and didn't accept the invitation yet, return inviter-name"
|
||||
[contacts chat my-public-key]
|
||||
(when (and (models.chat/group-chat? chat)
|
||||
(joined? my-public-key chat))
|
||||
(let [inviter-pk (get-inviter-pk my-public-key chat)]
|
||||
(get-in contacts [inviter-pk :name]
|
||||
(gfycat/generate-gfy inviter-pk)))))
|
||||
|
|
|
@ -277,9 +277,26 @@
|
|||
(log/debug "Adjusting mailserver request" "from:" from "adjusted-from:" adjusted-from)
|
||||
adjusted-from))
|
||||
|
||||
(fx/defn handle-request-success [{:keys [db]} {:keys [request-id]}]
|
||||
(defn chats->never-synced-public-chats [chats]
|
||||
(into {} (filter (fn [[k v]] (:might-have-join-time-messages? v)) chats)))
|
||||
|
||||
(fx/defn handle-request-success [{{:keys [chats] :as db} :db}
|
||||
{:keys [request-id topics]}]
|
||||
(when (:mailserver/current-request db)
|
||||
{:db (assoc-in db [:mailserver/current-request :request-id] request-id)}))
|
||||
(let [by-topic-never-synced-chats (reduce-kv
|
||||
#(assoc %1 (transport.utils/get-topic %2) %3)
|
||||
{}
|
||||
(chats->never-synced-public-chats chats))
|
||||
never-synced-chats-in-this-request (select-keys by-topic-never-synced-chats (vec topics))]
|
||||
(if (seq never-synced-chats-in-this-request)
|
||||
{:db (-> db
|
||||
((fn [db] (reduce
|
||||
(fn [db chat]
|
||||
(assoc-in db [:chats (:chat-id chat) :join-time-mail-request-id] request-id))
|
||||
db
|
||||
(vals never-synced-chats-in-this-request))))
|
||||
(assoc-in [:mailserver/current-request :request-id] request-id))}
|
||||
{:db (assoc-in db [:mailserver/current-request :request-id] request-id)}))))
|
||||
|
||||
(defn request-messages! [web3 {:keys [sym-key-id address]} {:keys [topics cursor to from] :as request}]
|
||||
;; Add some room to from, unless we break day boundaries so that messages that have
|
||||
|
@ -304,7 +321,7 @@
|
|||
(if-not error
|
||||
(do
|
||||
(log/info "mailserver: messages request success for topic " topics "from" from "to" to)
|
||||
(re-frame/dispatch [:mailserver.callback/request-success {:request-id request-id}]))
|
||||
(re-frame/dispatch [:mailserver.callback/request-success {:request-id request-id :topics topics}]))
|
||||
(do
|
||||
(log/error "mailserver: messages request error for topic " topics ": " error)
|
||||
(utils/set-timeout #(re-frame/dispatch [:mailserver.callback/resend-request {:request-id nil}])
|
||||
|
@ -521,22 +538,47 @@
|
|||
(fx/defn handle-request-error
|
||||
[{:keys [db]} error]
|
||||
{:db (-> db
|
||||
(assoc :mailserver/request-error error)
|
||||
(assoc :mailserver/request-error error)
|
||||
(dissoc :mailserver/current-request
|
||||
:mailserver/pending-requests))})
|
||||
|
||||
(fx/defn handle-request-completed
|
||||
[cofx event]
|
||||
[{{:keys [chats] :as db} :db :as cofx}
|
||||
{:keys [requestID lastEnvelopeHash cursor errorMessage] :as event}]
|
||||
(when (accounts.db/logged-in? cofx)
|
||||
(let [error (:errorMessage event)]
|
||||
(if (empty? error)
|
||||
(fx/merge
|
||||
cofx
|
||||
{:mailserver/increase-limit []}
|
||||
(update-mailserver-topics {:request-id (:requestID event)
|
||||
:cursor (:cursor event)}))
|
||||
|
||||
(handle-request-error cofx error)))))
|
||||
(if (empty? errorMessage)
|
||||
(let [never-synced-chats-in-request
|
||||
(->> (chats->never-synced-public-chats chats)
|
||||
(filter (fn [[k v]] (= requestID (:join-time-mail-request-id v))))
|
||||
keys)]
|
||||
(if (seq never-synced-chats-in-request)
|
||||
(if (= lastEnvelopeHash
|
||||
"0x0000000000000000000000000000000000000000000000000000000000000000")
|
||||
(fx/merge
|
||||
cofx
|
||||
{:mailserver/increase-limit []
|
||||
:dispatch-n (map
|
||||
#(identity [:chat.ui/join-time-messages-checked %])
|
||||
never-synced-chats-in-request)}
|
||||
(update-mailserver-topics {:request-id requestID
|
||||
:cursor cursor}))
|
||||
(fx/merge
|
||||
cofx
|
||||
{:mailserver/increase-limit []
|
||||
:dispatch-later (vec
|
||||
(map
|
||||
#(identity
|
||||
{:ms 1000
|
||||
:dispatch [:chat.ui/join-time-messages-checked %]})
|
||||
never-synced-chats-in-request))}
|
||||
(update-mailserver-topics {:request-id requestID
|
||||
:cursor cursor})))
|
||||
(fx/merge
|
||||
cofx
|
||||
{:mailserver/increase-limit []}
|
||||
(update-mailserver-topics {:request-id requestID
|
||||
:cursor cursor}))))
|
||||
(handle-request-error cofx errorMessage))))
|
||||
|
||||
(fx/defn show-request-error-popup
|
||||
[{:keys [db]}]
|
||||
|
|
|
@ -122,6 +122,12 @@
|
|||
:default-chat-icon (styles/default-chat-icon-profile colors/default-chat-color size)
|
||||
:default-chat-icon-text styles/default-chat-icon-text}])
|
||||
|
||||
(defn chat-intro-icon-view [icon-text chat-id styles]
|
||||
(let [photo-path (re-frame.core/subscribe [:contacts/chat-photo chat-id])]
|
||||
(if-not (string/blank? @photo-path)
|
||||
[photos/photo @photo-path styles]
|
||||
[default-chat-icon icon-text styles])))
|
||||
|
||||
(defn profile-icon-view [photo-path name color edit? size override-styles]
|
||||
(let [styles (merge {:container {:width size :height size}
|
||||
:online-view styles/online-view-profile
|
||||
|
|
|
@ -191,9 +191,6 @@
|
|||
{:opacity opacity
|
||||
:flex 1})
|
||||
|
||||
(def empty-chat-container-one-to-one
|
||||
{:margin-top 10})
|
||||
|
||||
(def empty-chat-container
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
|
@ -202,17 +199,53 @@
|
|||
:padding-vertical 50
|
||||
:margin-right 6})
|
||||
|
||||
(def empty-chat-text
|
||||
{:color colors/gray
|
||||
:width 280
|
||||
:text-align :center})
|
||||
(defn intro-header-container
|
||||
[height status no-messages]
|
||||
(let [adjusted-height (if (< height 280) 324 height)]
|
||||
(if (or no-messages (= status (or :loading :empty)))
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:height adjusted-height
|
||||
:padding-horizontal 32}
|
||||
{:flex 1
|
||||
:flex-direction :column
|
||||
:justify-content :center
|
||||
:align-items :center
|
||||
:padding-horizontal 32})))
|
||||
|
||||
(def empty-chat-text-name
|
||||
{:margin-bottom 5})
|
||||
(defn intro-header-icon [diameter color]
|
||||
{:width diameter
|
||||
:height diameter
|
||||
:align-items :center
|
||||
:justify-content :center
|
||||
:border-radius (/ diameter 2)
|
||||
:background-color color})
|
||||
|
||||
(def join-button
|
||||
{:margin-top 24
|
||||
:margin-bottom 15})
|
||||
(def intro-header-icon-text
|
||||
{:color colors/white
|
||||
:font-size 52
|
||||
:font-weight "700"
|
||||
:opacity 0.8
|
||||
:line-height 72})
|
||||
|
||||
(def intro-header-chat-name
|
||||
{:font-size 22
|
||||
:font-weight "700"
|
||||
:line-height 28
|
||||
:margin-bottom 8
|
||||
:color colors/black})
|
||||
|
||||
(def intro-header-description-container
|
||||
{:flex-wrap :wrap
|
||||
:align-items :flex-start
|
||||
:flex-direction :row})
|
||||
|
||||
(def intro-header-description
|
||||
{:color colors/gray
|
||||
:line-height 22
|
||||
:text-align :center})
|
||||
|
||||
(def group-chat-icon
|
||||
{:color colors/white
|
||||
|
@ -220,18 +253,20 @@
|
|||
:font-weight "700"})
|
||||
|
||||
(def group-chat-join-footer
|
||||
{:position :absolute
|
||||
:justify-content :center
|
||||
:margin-bottom 30
|
||||
:bottom 0})
|
||||
|
||||
(def group-chat-join-name
|
||||
{:typography :header})
|
||||
{:flex 1
|
||||
:justify-content :center})
|
||||
|
||||
(def group-chat-join-container
|
||||
{:flex 1
|
||||
:align-items :center
|
||||
:justify-content :center})
|
||||
|
||||
(def group-chat-join-name
|
||||
{:typography :header})
|
||||
|
||||
(def join-button
|
||||
{:margin-bottom 15})
|
||||
|
||||
(def decline-chat
|
||||
{:color colors/blue})
|
||||
{:color colors/blue
|
||||
:margin-bottom 40})
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
colors/blue
|
||||
(if outgoing colors/white colors/blue))
|
||||
:text-decoration-line :underline}
|
||||
:on-press #(re-frame/dispatch [:chat.ui/start-public-chat (subs text 1)])})})
|
||||
:on-press #(re-frame/dispatch [:chat.ui/start-public-chat (subs text 1) {:navigation-reset? true}])})})
|
||||
|
||||
(defn- lookup-props [text-chunk message kind]
|
||||
(let [prop (get styling->prop kind)
|
||||
|
|
|
@ -44,26 +44,25 @@
|
|||
(list-selection/show {:title chat-name
|
||||
:options (actions/actions group-chat? chat-id public?)}))
|
||||
|
||||
(defview chat-toolbar [public? modal?]
|
||||
(letsubs [{:keys [chat-name group-chat chat-id contact]} [:chats/current-chat]]
|
||||
[react/view
|
||||
[status-bar/status-bar (when modal? {:type :modal-white})]
|
||||
[toolbar/toolbar
|
||||
{:chat? true}
|
||||
(if modal?
|
||||
[toolbar/nav-button
|
||||
(toolbar.actions/close toolbar.actions/default-handler)]
|
||||
toolbar/nav-back-home)
|
||||
[toolbar-content/toolbar-content-view]
|
||||
(when-not modal?
|
||||
[toolbar/actions [{:icon :main-icons/more
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id chat-name group-chat public?)}]])]
|
||||
[connectivity/connectivity-view]
|
||||
(when (and (not group-chat)
|
||||
(not (contact.db/added? contact)))
|
||||
[add-contact-bar chat-id])]))
|
||||
(defn chat-toolbar [{:keys [chat-name group-chat chat-id contact]} public? modal?]
|
||||
[react/view
|
||||
[status-bar/status-bar (when modal? {:type :modal-white})]
|
||||
[toolbar/toolbar
|
||||
{:chat? true}
|
||||
(if modal?
|
||||
[toolbar/nav-button
|
||||
(toolbar.actions/close toolbar.actions/default-handler)]
|
||||
toolbar/nav-back-home)
|
||||
[toolbar-content/toolbar-content-view]
|
||||
(when-not modal?
|
||||
[toolbar/actions [{:icon :main-icons/more
|
||||
:icon-opts {:color :black
|
||||
:accessibility-label :chat-menu-button}
|
||||
:handler #(on-options chat-id chat-name group-chat public?)}]])]
|
||||
[connectivity/connectivity-view]
|
||||
(when (and (not group-chat)
|
||||
(not (contact.db/added? contact)))
|
||||
[add-contact-bar chat-id])])
|
||||
|
||||
(defmulti message-row (fn [{{:keys [type]} :row}] type))
|
||||
|
||||
|
@ -101,22 +100,6 @@
|
|||
[react/animated-view {:style (style/message-view-animated opacity)}
|
||||
message-view]]]))
|
||||
|
||||
(defn empty-chat-container
|
||||
[]
|
||||
[react/view style/empty-chat-container
|
||||
[react/text {:style style/empty-chat-text}
|
||||
(i18n/label :t/empty-chat-description)]])
|
||||
|
||||
(defn empty-chat-container-one-to-one
|
||||
[contact-name]
|
||||
[react/view style/empty-chat-container
|
||||
[vector-icons/icon :tiny-icons/tiny-lock]
|
||||
[react/nested-text {:style style/empty-chat-text}
|
||||
[{:style style/empty-chat-container-one-to-one}
|
||||
(i18n/label :t/empty-chat-description-one-to-one)]
|
||||
[{:style style/empty-chat-text-name}
|
||||
contact-name]]])
|
||||
|
||||
(defn join-chat-button [chat-id]
|
||||
[buttons/secondary-button {:style style/join-button
|
||||
:on-press #(re-frame/dispatch [:group-chats.ui/join-pressed chat-id])}
|
||||
|
@ -129,6 +112,14 @@
|
|||
[react/text {:style style/decline-chat}
|
||||
(i18n/label :t/group-chat-decline-invitation)]])
|
||||
|
||||
(defn group-chat-footer
|
||||
[chat-id]
|
||||
[react/view {:style style/group-chat-join-footer}
|
||||
[react/view {:style style/group-chat-join-container}
|
||||
[join-chat-button chat-id]
|
||||
[decline-chat chat-id]]])
|
||||
|
||||
;; TODO this is now used only in Desktop - unnecessary for mobile
|
||||
(defn group-chat-join-section
|
||||
[inviter-name {:keys [name group-chat color chat-id]}]
|
||||
[react/view style/empty-chat-container
|
||||
|
@ -138,15 +129,95 @@
|
|||
[react/view {:style style/group-chat-join-container}
|
||||
[react/view
|
||||
[react/text {:style style/group-chat-join-name} name]]
|
||||
[react/text {:style style/empty-chat-text}
|
||||
[react/text style/empty-chat-container-one-to-one
|
||||
(i18n/label :t/join-group-chat-description {:username inviter-name
|
||||
:group-name name})]]
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/join-group-chat-description {:username inviter-name
|
||||
:group-name name})]
|
||||
[join-chat-button chat-id]
|
||||
[decline-chat chat-id]]]])
|
||||
|
||||
;; TODO refactor this big view into chunks
|
||||
(defview chat-intro-header-container
|
||||
[{:keys [group-chat name pending-invite-inviter-name
|
||||
inviter-name color chat-id chat-name public?
|
||||
universal-link]} no-messages]
|
||||
(letsubs [intro-status [:chats/current-chat-intro-status]
|
||||
height [:chats/content-layout-height]
|
||||
input-height [:chats/current-chat-ui-prop :input-height]]
|
||||
(let [icon-text (if public? chat-id name)
|
||||
intro-name (if public? chat-name name)]
|
||||
;; TODO This when check ought to be unnecessary but for now it prevents
|
||||
;; jerky motion when fresh chat is created, when input-height can be null
|
||||
;; affecting the calculation of content-layout-height to be briefly adjusted
|
||||
(when (or input-height pending-invite-inviter-name)
|
||||
[react/touchable-without-feedback
|
||||
{:style {:flex 1
|
||||
:align-items :flex-start}
|
||||
:on-press (fn [_]
|
||||
(re-frame/dispatch
|
||||
[:chat.ui/set-chat-ui-props {:messages-focused? true
|
||||
:show-stickers? false}])
|
||||
(react/dismiss-keyboard!))}
|
||||
[react/view
|
||||
(style/intro-header-container height intro-status no-messages)
|
||||
;; Icon section
|
||||
[react/view {:style {:margin-top 42
|
||||
:margin-bottom 24}}
|
||||
[chat-icon.screen/chat-intro-icon-view
|
||||
icon-text chat-id
|
||||
{:default-chat-icon (style/intro-header-icon 120 color)
|
||||
:default-chat-icon-text style/intro-header-icon-text
|
||||
:size 120}]]
|
||||
;; Chat title section
|
||||
[react/text {:style style/intro-header-chat-name} intro-name]
|
||||
;; Description section
|
||||
(if group-chat
|
||||
(cond
|
||||
(= intro-status :loading)
|
||||
[react/view {:style (merge style/intro-header-description-container
|
||||
{:margin-bottom 36
|
||||
:height 44})}
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/loading)]
|
||||
[react/activity-indicator {:animating true
|
||||
:size :small
|
||||
:color colors/gray}]]
|
||||
|
||||
(= intro-status :empty)
|
||||
(when public?
|
||||
[react/nested-text {:style (merge style/intro-header-description
|
||||
{:margin-bottom 36})}
|
||||
(i18n/label :t/empty-chat-description-public)
|
||||
[{:style {:color colors/blue}
|
||||
:on-press #(list-selection/open-share
|
||||
{:message
|
||||
(i18n/label
|
||||
:t/share-public-chat-text {:link universal-link})})}
|
||||
(i18n/label :t/empty-chat-description-public-share-this)]])
|
||||
|
||||
(= intro-status :messages)
|
||||
(when (not public?)
|
||||
(if pending-invite-inviter-name
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
[{:style {:color :black}} pending-invite-inviter-name]
|
||||
(i18n/label :t/join-group-chat-description
|
||||
{:username ""
|
||||
:group-name intro-name})]
|
||||
(if (not= inviter-name "Unknown")
|
||||
[react/nested-text {:style style/intro-header-description}
|
||||
(i18n/label :t/joined-group-chat-description
|
||||
{:username ""
|
||||
:group-name intro-name})
|
||||
[{:style {:color :black}} inviter-name]]
|
||||
[react/text {:style style/intro-header-description}
|
||||
(i18n/label :t/created-group-chat-description
|
||||
{:group-name intro-name})]))))
|
||||
[react/nested-text {:style (merge style/intro-header-description
|
||||
{:margin-bottom 36})}
|
||||
(i18n/label :t/empty-chat-description-one-to-one)
|
||||
[{} intro-name]])]]))))
|
||||
|
||||
(defview messages-view
|
||||
[{:keys [group-chat name pending-invite-inviter-name messages-initialized?] :as chat}
|
||||
[{:keys [group-chat chat-id pending-invite-inviter-name] :as chat}
|
||||
modal?]
|
||||
(letsubs [messages [:chats/current-chat-messages-stream]
|
||||
current-public-key [:account/public-key]]
|
||||
|
@ -157,63 +228,63 @@
|
|||
(re-frame/dispatch [:chat.ui/set-chat-ui-props
|
||||
{:messages-focused? true
|
||||
:input-focused? false}]))}
|
||||
(cond
|
||||
pending-invite-inviter-name
|
||||
[group-chat-join-section pending-invite-inviter-name chat]
|
||||
|
||||
(and (empty? messages)
|
||||
messages-initialized?)
|
||||
(if group-chat
|
||||
[empty-chat-container]
|
||||
[empty-chat-container-one-to-one name])
|
||||
|
||||
:else
|
||||
[list/flat-list {:data messages
|
||||
:key-fn #(or (:message-id %) (:value %))
|
||||
:render-fn (fn [message]
|
||||
[message-row {:group-chat group-chat
|
||||
:modal? modal?
|
||||
:current-public-key current-public-key
|
||||
:row message}])
|
||||
:inverted true
|
||||
:onEndReached #(re-frame/dispatch [:chat.ui/load-more-messages])
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps :handled}])))
|
||||
|
||||
(defview messages-view-wrapper [modal?]
|
||||
(letsubs [chat [:chats/current-chat]]
|
||||
[messages-view chat modal?]))
|
||||
(let [no-messages (empty? messages)
|
||||
flat-list-conf
|
||||
{:data messages
|
||||
:footer [chat-intro-header-container chat no-messages]
|
||||
:key-fn #(or (:message-id %) (:value %))
|
||||
:render-fn (fn [message]
|
||||
[message-row
|
||||
{:group-chat group-chat
|
||||
:modal? modal?
|
||||
:current-public-key current-public-key
|
||||
:row message}])
|
||||
:inverted true
|
||||
:onEndReached #(re-frame/dispatch
|
||||
[:chat.ui/load-more-messages])
|
||||
:enableEmptySections true
|
||||
:keyboardShouldPersistTaps :handled}
|
||||
group-header {:header [group-chat-footer chat-id]}]
|
||||
(if pending-invite-inviter-name
|
||||
[list/flat-list (merge flat-list-conf group-header)]
|
||||
[list/flat-list flat-list-conf]))))
|
||||
|
||||
(defn show-input-container? [my-public-key current-chat]
|
||||
(or (not (models.chat/group-chat? current-chat))
|
||||
(group-chats.db/joined? my-public-key current-chat)))
|
||||
|
||||
(defview chat-root [modal?]
|
||||
(letsubs [{:keys [public?] :as current-chat} [:chats/current-chat]
|
||||
my-public-key [:account/public-key]
|
||||
show-bottom-info? [:chats/current-chat-ui-prop :show-bottom-info?]
|
||||
show-message-options? [:chats/current-chat-ui-prop :show-message-options?]
|
||||
show-stickers? [:chats/current-chat-ui-prop :show-stickers?]]
|
||||
;; this scroll-view is a hack that allows us to use on-blur and on-focus on Android
|
||||
;; more details here: https://github.com/facebook/react-native/issues/11071
|
||||
[react/scroll-view {:scroll-enabled false
|
||||
:style style/scroll-root
|
||||
:content-container-style style/scroll-root
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style style/chat-view
|
||||
:on-layout (fn [e]
|
||||
(re-frame/dispatch [:set :layout-height (-> e .-nativeEvent .-layout .-height)]))}
|
||||
[chat-toolbar public? modal?]
|
||||
[messages-view-animation
|
||||
[messages-view-wrapper modal?]]
|
||||
(when (show-input-container? my-public-key current-chat)
|
||||
[input/container])
|
||||
(when show-stickers?
|
||||
[stickers/stickers-view])
|
||||
(when show-bottom-info?
|
||||
[bottom-info/bottom-info-view])
|
||||
(when show-message-options?
|
||||
[message-options/view])]]))
|
||||
(letsubs [{:keys [public? chat-id] :as current-chat} [:chats/current-chat]
|
||||
current-chat-id [:chats/current-chat-id]
|
||||
my-public-key [:account/public-key]
|
||||
show-bottom-info? [:chats/current-chat-ui-prop :show-bottom-info?]
|
||||
show-message-options? [:chats/current-chat-ui-prop :show-message-options?]
|
||||
show-stickers? [:chats/current-chat-ui-prop :show-stickers?]]
|
||||
;; this check of current-chat-id is necessary only because in a fresh public chat creation sometimes
|
||||
;; this component renders before current-chat-id is set to current chat-id. Hence further down in sub
|
||||
;; components (e.g. chat-toolbar) there can be a brief visual inconsistancy like showing 'add contact'
|
||||
;; in public chat
|
||||
(when (= chat-id current-chat-id)
|
||||
;; this scroll-view is a hack that allows us to use on-blur and on-focus on Android
|
||||
;; more details here: https://github.com/facebook/react-native/issues/11071
|
||||
[react/scroll-view {:scroll-enabled false
|
||||
:style style/scroll-root
|
||||
:content-container-style style/scroll-root
|
||||
:keyboard-should-persist-taps :handled}
|
||||
[react/view {:style style/chat-view
|
||||
:on-layout (fn [e]
|
||||
(re-frame/dispatch [:set :layout-height (-> e .-nativeEvent .-layout .-height)]))}
|
||||
[chat-toolbar current-chat public? modal?]
|
||||
[messages-view-animation
|
||||
[messages-view current-chat modal?]]
|
||||
(when (show-input-container? my-public-key current-chat)
|
||||
[input/container])
|
||||
(when show-stickers?
|
||||
[stickers/stickers-view])
|
||||
(when show-bottom-info?
|
||||
[bottom-info/bottom-info-view])
|
||||
(when show-message-options?
|
||||
[message-options/view])]])))
|
||||
|
||||
(defview chat []
|
||||
[chat-root false])
|
||||
|
|
|
@ -120,6 +120,12 @@
|
|||
(fn [{:keys [db]} [_ k v]]
|
||||
{:db (assoc db k v)}))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:set-once
|
||||
(fn [{:keys [db]} [_ k v]]
|
||||
(when-not (get db k)
|
||||
{:db (assoc db k v)})))
|
||||
|
||||
(handlers/register-handler-fx
|
||||
:set-in
|
||||
(fn [{:keys [db]} [_ path v]]
|
||||
|
|
|
@ -118,7 +118,11 @@
|
|||
(when loading? (utils/set-timeout #(re-frame/dispatch [:init-rest-of-chats]) 100))))}
|
||||
[react/view {:flex 1}
|
||||
[status-bar/status-bar {:type :main}]
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}}
|
||||
[react/keyboard-avoiding-view {:style {:flex 1}
|
||||
:on-layout (fn [e]
|
||||
(re-frame/dispatch
|
||||
[:set-once :content-layout-height
|
||||
(-> e .-nativeEvent .-layout .-height)]))}
|
||||
[toolbar/toolbar nil nil [toolbar/content-title (i18n/label :t/chat)]]
|
||||
[les-debug-info]
|
||||
(cond loading?
|
||||
|
|
|
@ -375,6 +375,187 @@
|
|||
(is (not (mailserver/resend-request {:db {:mailserver/current-request {:request-id "a"}}}
|
||||
{:request-id "b"}))))))
|
||||
|
||||
(def cofx-no-pub-topic
|
||||
{:db
|
||||
{:account/account {:public-key "me"}
|
||||
:chats
|
||||
{"chat-id-1" {:is-active true
|
||||
:messages {}
|
||||
:might-have-join-time-messages? true
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-1"}
|
||||
"chat-id-2" {:is-active true
|
||||
:messages {}
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-2"}}}})
|
||||
|
||||
(def cofx-single-pub-topic
|
||||
{:db
|
||||
{:account/account {:public-key "me"}
|
||||
:chats
|
||||
{"chat-id-1" {:is-active true
|
||||
:messages {}
|
||||
:join-time-mail-request-id "a"
|
||||
:might-have-join-time-messages? true
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-1"}
|
||||
"chat-id-2" {:is-active true
|
||||
:messages {}
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-2"}}}})
|
||||
|
||||
(def cofx-multiple-pub-topic
|
||||
{:db
|
||||
{:account/account {:public-key "me"}
|
||||
:chats
|
||||
{"chat-id-1" {:is-active true
|
||||
:messages {}
|
||||
:join-time-mail-request-id "a"
|
||||
:might-have-join-time-messages? true
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-1"}
|
||||
"chat-id-2" {:is-active true
|
||||
:messages {}
|
||||
:join-time-mail-request-id "a"
|
||||
:might-have-join-time-messages? true
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-2"}
|
||||
"chat-id-3" {:is-active true
|
||||
:messages {}
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-3"}
|
||||
"chat-id-4" {:is-active true
|
||||
:messages {}
|
||||
:join-time-mail-request-id "a"
|
||||
:might-have-join-time-messages? true
|
||||
:group-chat true
|
||||
:public? true
|
||||
:chat-id "chat-id-4"}}}})
|
||||
|
||||
(def mailserver-completed-event
|
||||
{:requestID "a"
|
||||
:lastEnvelopeHash "0xC0FFEE"
|
||||
:cursor ""
|
||||
:errorMessage ""})
|
||||
|
||||
(def mailserver-completed-event-zero-for-envelope
|
||||
{:requestID "a"
|
||||
:lastEnvelopeHash "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
:cursor ""
|
||||
:errorMessage ""})
|
||||
|
||||
(deftest test-public-chat-related-handling-of-request-completed
|
||||
(testing "Request does not include any public chat topic"
|
||||
(testing "It does not dispatch any event"
|
||||
(is (not (or (contains?
|
||||
(mailserver/handle-request-completed cofx-no-pub-topic mailserver-completed-event)
|
||||
:dispatch-n)
|
||||
(contains?
|
||||
(mailserver/handle-request-completed cofx-no-pub-topic mailserver-completed-event)
|
||||
:dispatch-later)))))
|
||||
(testing "It has :mailserver/increase-limit effect"
|
||||
(is (contains? (mailserver/handle-request-completed cofx-no-pub-topic mailserver-completed-event)
|
||||
:mailserver/increase-limit))))
|
||||
(testing "Request includes one public chat topic"
|
||||
(testing "Event has non-zero envelope"
|
||||
(let [handeled-effects (mailserver/handle-request-completed
|
||||
cofx-single-pub-topic
|
||||
mailserver-completed-event)]
|
||||
(testing "It has no :dispatch-n event"
|
||||
(is (not (contains?
|
||||
handeled-effects
|
||||
:dispatch-n))))
|
||||
(testing "It has one :dispatch-later event"
|
||||
(is (= 1 (count (get
|
||||
handeled-effects
|
||||
:dispatch-later)))))
|
||||
(testing "The :dispatch-later event is :chat.ui/join-time-messages-checked"
|
||||
(is (= :chat.ui/join-time-messages-checked
|
||||
(-> (get
|
||||
handeled-effects
|
||||
:dispatch-later)
|
||||
first
|
||||
:dispatch
|
||||
first))))
|
||||
(testing "The :dispatch-later event argument is the chat-id/topic that the request included"
|
||||
(is (= "chat-id-1"
|
||||
(-> (get
|
||||
handeled-effects
|
||||
:dispatch-later)
|
||||
first
|
||||
:dispatch
|
||||
second))))
|
||||
(testing "It has :mailserver/increase-limit effect"
|
||||
(is (contains? handeled-effects
|
||||
:mailserver/increase-limit)))))
|
||||
(testing "Event has zero-valued envelope"
|
||||
(let [handeled-effects (mailserver/handle-request-completed
|
||||
cofx-single-pub-topic
|
||||
mailserver-completed-event-zero-for-envelope)]
|
||||
(testing "It has one :dispatch-n event"
|
||||
(is (= 1 (count (get
|
||||
handeled-effects
|
||||
:dispatch-n)))))
|
||||
(testing "It has no :dispatch-later event"
|
||||
(is (not (contains?
|
||||
handeled-effects
|
||||
:dispatch-later))))
|
||||
(testing "The :dispatch-n event is :chat.ui/join-time-messages-checked"
|
||||
(is (= :chat.ui/join-time-messages-checked
|
||||
(-> (get
|
||||
handeled-effects
|
||||
:dispatch-n)
|
||||
first
|
||||
first))))
|
||||
(testing "The :dispatch-n event argument is the chat-id/topic that the request included"
|
||||
(is (= "chat-id-1"
|
||||
(-> (get
|
||||
handeled-effects
|
||||
:dispatch-n)
|
||||
first
|
||||
second))))
|
||||
(testing "It has :mailserver/increase-limit effect"
|
||||
(is (contains? handeled-effects
|
||||
:mailserver/increase-limit))))))
|
||||
(testing "Request includes multiple public chat topics (3)"
|
||||
(testing "Event has non-zero envelope"
|
||||
(let [handeled-effects (mailserver/handle-request-completed
|
||||
cofx-multiple-pub-topic
|
||||
mailserver-completed-event)]
|
||||
(testing "It has no :dispatch-n event"
|
||||
(is (not (contains?
|
||||
handeled-effects
|
||||
:dispatch-n))))
|
||||
(testing "It has one :dispatch-later event"
|
||||
(is (= 3 (count (get
|
||||
handeled-effects
|
||||
:dispatch-later)))))
|
||||
(testing "It has :mailserver/increase-limit effect"
|
||||
(is (contains? handeled-effects
|
||||
:mailserver/increase-limit)))))
|
||||
(testing "Event has zero-valued envelope"
|
||||
(let [handeled-effects (mailserver/handle-request-completed
|
||||
cofx-multiple-pub-topic
|
||||
mailserver-completed-event-zero-for-envelope)]
|
||||
(testing "It has one :dispatch-n event"
|
||||
(is (= 3 (count (get
|
||||
handeled-effects
|
||||
:dispatch-n)))))
|
||||
(testing "It has no :dispatch-later event"
|
||||
(is (not (contains?
|
||||
handeled-effects
|
||||
:dispatch-later))))
|
||||
(testing "It has :mailserver/increase-limit effect"
|
||||
(is (contains? handeled-effects
|
||||
:mailserver/increase-limit)))))))
|
||||
|
||||
(deftest peers-summary-change
|
||||
(testing "Mailserver added, sym-key doesn't exist"
|
||||
(let [result (peers-summary-change-result false true false)]
|
||||
|
|
|
@ -233,7 +233,9 @@
|
|||
"other": "You can select {{count}} more participants"
|
||||
},
|
||||
"no-more-participants-available": "You can't add anymore participants",
|
||||
"created-group-chat-description": "You created the group {{group-name}}",
|
||||
"join-group-chat-description": "{{username}} invited you to join the group {{group-name}}",
|
||||
"joined-group-chat-description": "You've joined {{group-name}} from invitation by {{username}}",
|
||||
"join-group-chat": "Join group",
|
||||
"create-group-chat": "Create group chat",
|
||||
"group-chat-decline-invitation": "Decline invitation",
|
||||
|
@ -279,7 +281,10 @@
|
|||
"currency-display-name-mzn": "Mozambique Metical",
|
||||
"block": "Block",
|
||||
"wallet-set-up-title": "Set up your wallet",
|
||||
"loading": "Loading... ",
|
||||
"empty-chat-description": "There are no messages \nin this chat yet",
|
||||
"empty-chat-description-public": "It's been quiet here for the last 24h. Start the conversation or ",
|
||||
"empty-chat-description-public-share-this": "share this chat.",
|
||||
"camera-access-error": "To grant the required camera permission, please go to your system settings and make sure that Status > Camera is selected.",
|
||||
"wallet-invalid-address": "Invalid address: \n {{data}}",
|
||||
"wallet-invalid-address-checksum": "Error in address: \n {{data}}",
|
||||
|
|
Loading…
Reference in New Issue