Merge pull request #223 from status-im/feature/group-chat-delivery-status-#205
Group chat delivery statuses (#205)
Former-commit-id: 21963e47de
This commit is contained in:
commit
d234817599
|
@ -8,9 +8,8 @@
|
||||||
[reagent "0.5.1" :exclusions [cljsjs/react]]
|
[reagent "0.5.1" :exclusions [cljsjs/react]]
|
||||||
[re-frame "0.7.0"]
|
[re-frame "0.7.0"]
|
||||||
[prismatic/schema "1.0.4"]
|
[prismatic/schema "1.0.4"]
|
||||||
^{:voom {:repo "git@github.com:status-im/status-lib.git"
|
^{:voom {:repo "git@github.com:status-im/status-lib.git" :branch "group-chat-statuses"}}
|
||||||
:branch "master"}}
|
[status-im/protocol "0.2.3-20160914_155558-gfed628a"]
|
||||||
[status-im/protocol "0.2.2-20160909_082306-gcfbb92b"]
|
|
||||||
[natal-shell "0.3.0"]
|
[natal-shell "0.3.0"]
|
||||||
[com.andrewmcveigh/cljs-time "0.4.0"]
|
[com.andrewmcveigh/cljs-time "0.4.0"]
|
||||||
[tailrecursion/cljs-priority-map "1.2.0"]
|
[tailrecursion/cljs-priority-map "1.2.0"]
|
||||||
|
|
|
@ -36,9 +36,19 @@
|
||||||
status-im.chat.handlers.wallet-chat
|
status-im.chat.handlers.wallet-chat
|
||||||
[status-im.utils.logging :as log]))
|
[status-im.utils.logging :as log]))
|
||||||
|
|
||||||
(register-handler :set-show-actions
|
(register-handler :set-chat-ui-props
|
||||||
(fn [db [_ show-actions]]
|
(fn [db [_ ui-element value]]
|
||||||
(assoc db :show-actions show-actions)))
|
(assoc-in db [:chat-ui-props ui-element] value)))
|
||||||
|
|
||||||
|
(register-handler :set-show-info
|
||||||
|
(fn [db [_ show-info]]
|
||||||
|
(assoc db :show-info show-info)))
|
||||||
|
|
||||||
|
(register-handler :show-message-details
|
||||||
|
(u/side-effect!
|
||||||
|
(fn [_ [_ details]]
|
||||||
|
(dispatch [:set-chat-ui-props :show-bottom-info? true])
|
||||||
|
(dispatch [:set-chat-ui-props :bottom-info details]))))
|
||||||
|
|
||||||
(register-handler :load-more-messages
|
(register-handler :load-more-messages
|
||||||
(fn [{:keys [current-chat-id loading-allowed] :as db} _]
|
(fn [{:keys [current-chat-id loading-allowed] :as db} _]
|
||||||
|
@ -296,7 +306,6 @@
|
||||||
[{:keys [new-chat]} _]
|
[{:keys [new-chat]} _]
|
||||||
(chats/create-chat new-chat))
|
(chats/create-chat new-chat))
|
||||||
|
|
||||||
|
|
||||||
(defn open-chat!
|
(defn open-chat!
|
||||||
[_ [_ chat-id _ navigation-type]]
|
[_ [_ chat-id _ navigation-type]]
|
||||||
(dispatch [(or navigation-type :navigate-to) :chat chat-id]))
|
(dispatch [(or navigation-type :navigate-to) :chat chat-id]))
|
||||||
|
@ -395,11 +404,10 @@
|
||||||
(fn [db [_ h]]
|
(fn [db [_ h]]
|
||||||
(assoc db :layout-height h)))
|
(assoc db :layout-height h)))
|
||||||
|
|
||||||
|
|
||||||
(register-handler :send-seen!
|
(register-handler :send-seen!
|
||||||
(after (fn [_ [_ chat-id message-id]]
|
(after (fn [_ [_ chat-id message-id]]
|
||||||
(when-not (console? chat-id))
|
(dispatch [:message-seen {:message-id message-id
|
||||||
(dispatch [:message-seen chat-id message-id])))
|
:chat-id chat-id}])))
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
(fn [_ [_ chat-id message-id]]
|
(fn [_ [_ chat-id message-id]]
|
||||||
(when-not (console? chat-id)
|
(when-not (console? chat-id)
|
||||||
|
@ -419,16 +427,16 @@
|
||||||
(fn [db [_ chat-id mode]]
|
(fn [db [_ chat-id mode]]
|
||||||
(assoc-in db [:kb-mode chat-id] mode)))
|
(assoc-in db [:kb-mode chat-id] mode)))
|
||||||
|
|
||||||
(defn save-chat!
|
(defn update-chat!
|
||||||
[_ [_ chat]]
|
[_ [_ chat]]
|
||||||
(chats/create-chat chat))
|
(chats/update-chat chat))
|
||||||
|
|
||||||
(register-handler :update-chat!
|
(register-handler :update-chat!
|
||||||
(-> (fn [db [_ {:keys [chat-id] :as chat}]]
|
(-> (fn [db [_ {:keys [chat-id] :as chat}]]
|
||||||
(if (get-in db [:chats chat-id])
|
(if (get-in db [:chats chat-id])
|
||||||
(update-in db [:chats chat-id] merge chat)
|
(update-in db [:chats chat-id] merge chat)
|
||||||
db))
|
db))
|
||||||
((after save-chat!))))
|
((after update-chat!))))
|
||||||
|
|
||||||
(register-handler :check-autorun
|
(register-handler :check-autorun
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
[status-im.commands.utils :refer [generate-hiccup]]
|
[status-im.commands.utils :refer [generate-hiccup]]
|
||||||
[status-im.constants :refer [content-type-command-request]]
|
[status-im.constants :refer [content-type-command-request]]
|
||||||
[cljs.reader :refer [read-string]]
|
[cljs.reader :refer [read-string]]
|
||||||
[status-im.models.chats :as c]))
|
[status-im.models.chats :as c]
|
||||||
|
[status-im.utils.logging :as log]))
|
||||||
|
|
||||||
(defn check-preview [{:keys [content] :as message}]
|
(defn check-preview [{:keys [content] :as message}]
|
||||||
(if-let [preview (:preview content)]
|
(if-let [preview (:preview content)]
|
||||||
|
@ -34,7 +35,6 @@
|
||||||
message' (assoc (->> message
|
message' (assoc (->> message
|
||||||
(cu/check-author-direction previous-message)
|
(cu/check-author-direction previous-message)
|
||||||
(check-preview))
|
(check-preview))
|
||||||
:delivery-status :sending
|
|
||||||
:chat-id chat-id')]
|
:chat-id chat-id')]
|
||||||
(store-message message')
|
(store-message message')
|
||||||
(when-not (c/chat-exists? chat-id')
|
(when-not (c/chat-exists? chat-id')
|
||||||
|
|
|
@ -24,10 +24,10 @@
|
||||||
[{:keys [current-chat-id] :as db} [_ chat-id]]
|
[{:keys [current-chat-id] :as db} [_ chat-id]]
|
||||||
(let [chat-id' (or chat-id current-chat-id)
|
(let [chat-id' (or chat-id current-chat-id)
|
||||||
requests (-> ;; todo maybe limit is needed
|
requests (-> ;; todo maybe limit is needed
|
||||||
(realm/get-by-fields :account :request :and [[:chat-id chat-id']
|
(realm/get-by-fields :account :request :and [[:chat-id chat-id']
|
||||||
[:status "open"]])
|
[:status "open"]])
|
||||||
(realm/sorted :added :desc)
|
(realm/sorted :added :desc)
|
||||||
(realm/collection->map))
|
(realm/realm-collection->list))
|
||||||
requests' (map #(update % :type keyword) requests)]
|
requests' (map #(update % :type keyword) requests)]
|
||||||
(assoc-in db [:chats chat-id' :requests] requests')))
|
(assoc-in db [:chats chat-id' :requests] requests')))
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,6 @@
|
||||||
[status-im.protocol.api :as api]
|
[status-im.protocol.api :as api]
|
||||||
[status-im.utils.logging :as log]))
|
[status-im.utils.logging :as log]))
|
||||||
|
|
||||||
(defn default-delivery-status [chat-id]
|
|
||||||
(if (cu/console? chat-id)
|
|
||||||
:seen
|
|
||||||
:sending))
|
|
||||||
|
|
||||||
(defn prepare-message
|
(defn prepare-message
|
||||||
[{:keys [identity current-chat-id] :as db} _]
|
[{:keys [identity current-chat-id] :as db} _]
|
||||||
(let [text (get-in db [:chats current-chat-id :input-text])
|
(let [text (get-in db [:chats current-chat-id :input-text])
|
||||||
|
@ -33,7 +28,6 @@
|
||||||
:to current-chat-id
|
:to current-chat-id
|
||||||
:from identity
|
:from identity
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:delivery-status (default-delivery-status current-chat-id)
|
|
||||||
:outgoing true
|
:outgoing true
|
||||||
:timestamp (time/now-ms)})]
|
:timestamp (time/now-ms)})]
|
||||||
(if command
|
(if command
|
||||||
|
@ -49,7 +43,6 @@
|
||||||
:to chat-id
|
:to chat-id
|
||||||
:content (assoc content :preview preview-string)
|
:content (assoc content :preview preview-string)
|
||||||
:content-type content-type-command
|
:content-type content-type-command
|
||||||
:delivery-status (default-delivery-status chat-id)
|
|
||||||
:outgoing true
|
:outgoing true
|
||||||
:preview preview-string
|
:preview preview-string
|
||||||
:rendered-preview preview
|
:rendered-preview preview
|
||||||
|
@ -162,7 +155,6 @@
|
||||||
:content message
|
:content message
|
||||||
:from identity
|
:from identity
|
||||||
:content-type text-content-type
|
:content-type text-content-type
|
||||||
:delivery-status (default-delivery-status chat-id)
|
|
||||||
:outgoing true
|
:outgoing true
|
||||||
:timestamp (time/now-ms)})
|
:timestamp (time/now-ms)})
|
||||||
message'' (if group-chat
|
message'' (if group-chat
|
||||||
|
|
|
@ -1,12 +1,13 @@
|
||||||
(ns status-im.chat.handlers.unviewed-messages
|
(ns status-im.chat.handlers.unviewed-messages
|
||||||
(:require [re-frame.core :refer [after enrich path dispatch]]
|
(:require [re-frame.core :refer [after enrich path dispatch]]
|
||||||
[status-im.utils.handlers :refer [register-handler]]
|
[status-im.utils.handlers :refer [register-handler]]
|
||||||
[status-im.persistence.realm.core :as realm]))
|
[status-im.persistence.realm.core :as realm]
|
||||||
|
[status-im.utils.logging :as log]))
|
||||||
|
|
||||||
(defn delivered-messages []
|
(defn delivered-messages []
|
||||||
(-> (realm/get-by-fields :account :message :and [[:delivery-status :delivered]
|
(-> (realm/get-by-fields :account :message :and {:outgoing false
|
||||||
[:outgoing false]])
|
:message-status nil})
|
||||||
(realm/collection->map)))
|
(realm/realm-collection->list)))
|
||||||
|
|
||||||
(defn set-unviewed-messages [db]
|
(defn set-unviewed-messages [db]
|
||||||
(let [messages (->> (::raw-unviewed-messages db)
|
(let [messages (->> (::raw-unviewed-messages db)
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
[status-im.chat.views.response :refer [response-view]]
|
[status-im.chat.views.response :refer [response-view]]
|
||||||
[status-im.chat.views.new-message :refer [chat-message-new]]
|
[status-im.chat.views.new-message :refer [chat-message-new]]
|
||||||
[status-im.chat.views.actions :refer [actions-view]]
|
[status-im.chat.views.actions :refer [actions-view]]
|
||||||
|
[status-im.chat.views.bottom-info :refer [bottom-info-view]]
|
||||||
[status-im.i18n :refer [label label-pluralize]]
|
[status-im.i18n :refer [label label-pluralize]]
|
||||||
[status-im.components.animation :as anim]
|
[status-im.components.animation :as anim]
|
||||||
[reagent.core :as r]
|
[reagent.core :as r]
|
||||||
|
@ -101,7 +102,7 @@
|
||||||
|
|
||||||
(defn toolbar-content []
|
(defn toolbar-content []
|
||||||
(let [{:keys [group-chat name contacts chat-id]} (subscribe [:chat-properties [:group-chat :name :contacts :chat-id]])
|
(let [{:keys [group-chat name contacts chat-id]} (subscribe [:chat-properties [:group-chat :name :contacts :chat-id]])
|
||||||
show-actions (subscribe [:show-actions])
|
show-actions (subscribe [:chat-ui-props :show-actions?])
|
||||||
contact (subscribe [:get-in [:contacts @chat-id]])]
|
contact (subscribe [:get-in [:contacts @chat-id]])]
|
||||||
(fn []
|
(fn []
|
||||||
[view (st/chat-name-view @show-actions)
|
[view (st/chat-name-view @show-actions)
|
||||||
|
@ -123,20 +124,20 @@
|
||||||
(online-text @contact @chat-id)])])))
|
(online-text @contact @chat-id)])])))
|
||||||
|
|
||||||
(defn toolbar-action []
|
(defn toolbar-action []
|
||||||
(let [show-actions (subscribe [:show-actions])]
|
(let [show-actions (subscribe [:chat-ui-props :show-actions?])]
|
||||||
(fn []
|
(fn []
|
||||||
(if @show-actions
|
(if @show-actions
|
||||||
[touchable-highlight
|
[touchable-highlight
|
||||||
{:on-press #(dispatch [:set-show-actions false])}
|
{:on-press #(dispatch [:set-chat-ui-props :show-actions? false])}
|
||||||
[view st/action
|
[view st/action
|
||||||
[icon :up st/up-icon]]]
|
[icon :up st/up-icon]]]
|
||||||
[touchable-highlight
|
[touchable-highlight
|
||||||
{:on-press #(dispatch [:set-show-actions true])}
|
{:on-press #(dispatch [:set-chat-ui-props :show-actions? true])}
|
||||||
[view st/action
|
[view st/action
|
||||||
[chat-icon]]]))))
|
[chat-icon]]]))))
|
||||||
|
|
||||||
(defview chat-toolbar []
|
(defview chat-toolbar []
|
||||||
[show-actions [:show-actions]]
|
[show-actions [:chat-ui-props :show-actions?]]
|
||||||
[view
|
[view
|
||||||
[status-bar]
|
[status-bar]
|
||||||
[toolbar {:hide-nav? show-actions
|
[toolbar {:hide-nav? show-actions
|
||||||
|
@ -182,7 +183,8 @@
|
||||||
|
|
||||||
(defn chat []
|
(defn chat []
|
||||||
(let [group-chat (subscribe [:chat :group-chat])
|
(let [group-chat (subscribe [:chat :group-chat])
|
||||||
show-actions (subscribe [:show-actions])
|
show-actions? (subscribe [:chat-ui-props :show-actions?])
|
||||||
|
show-bottom-info? (subscribe [:chat-ui-props :show-bottom-info?])
|
||||||
command? (subscribe [:command?])
|
command? (subscribe [:command?])
|
||||||
layout-height (subscribe [:get :layout-height])]
|
layout-height (subscribe [:get :layout-height])]
|
||||||
(r/create-class
|
(r/create-class
|
||||||
|
@ -200,6 +202,10 @@
|
||||||
;; todo uncomment this
|
;; todo uncomment this
|
||||||
#_(when @group-chat [typing-all])
|
#_(when @group-chat [typing-all])
|
||||||
[response-view]
|
[response-view]
|
||||||
(when-not @command? [suggestion-container])
|
(when-not @command?
|
||||||
|
[suggestion-container])
|
||||||
[chat-message-new]
|
[chat-message-new]
|
||||||
(when @show-actions [actions-view])])})))
|
(when @show-actions?
|
||||||
|
[actions-view])
|
||||||
|
(when @show-bottom-info?
|
||||||
|
[bottom-info-view])])})))
|
||||||
|
|
|
@ -157,7 +157,6 @@
|
||||||
(def intro-status
|
(def intro-status
|
||||||
{:message-id "intro-status"
|
{:message-id "intro-status"
|
||||||
:content (label :t/intro-status)
|
:content (label :t/intro-status)
|
||||||
:delivery-status "seen"
|
|
||||||
:from "console"
|
:from "console"
|
||||||
:chat-id "console"
|
:chat-id "console"
|
||||||
:content-type content-type-status
|
:content-type content-type-status
|
||||||
|
|
|
@ -2,13 +2,15 @@
|
||||||
(:require [status-im.components.styles :refer [font
|
(:require [status-im.components.styles :refer [font
|
||||||
title-font
|
title-font
|
||||||
color-white
|
color-white
|
||||||
|
color-black
|
||||||
chat-background
|
chat-background
|
||||||
online-color
|
online-color
|
||||||
selected-message-color
|
selected-message-color
|
||||||
separator-color
|
separator-color
|
||||||
text1-color
|
text1-color
|
||||||
text2-color
|
text2-color
|
||||||
toolbar-background1]]))
|
toolbar-background1]]
|
||||||
|
[status-im.utils.logging :as log]))
|
||||||
|
|
||||||
(def chat-view
|
(def chat-view
|
||||||
{:flex 1
|
{:flex 1
|
||||||
|
@ -114,6 +116,13 @@
|
||||||
:color text2-color
|
:color text2-color
|
||||||
:font-size 12})
|
:font-size 12})
|
||||||
|
|
||||||
|
(def actions-overlay
|
||||||
|
{:position :absolute
|
||||||
|
:top 0
|
||||||
|
:bottom 0
|
||||||
|
:left 0
|
||||||
|
:right 0})
|
||||||
|
|
||||||
(def typing-all
|
(def typing-all
|
||||||
{:marginBottom 20})
|
{:marginBottom 20})
|
||||||
|
|
||||||
|
@ -137,12 +146,51 @@
|
||||||
:fontFamily font
|
:fontFamily font
|
||||||
:color text2-color})
|
:color text2-color})
|
||||||
|
|
||||||
(def actions-overlay
|
|
||||||
{:position :absolute
|
|
||||||
:top 0
|
|
||||||
:bottom 0
|
|
||||||
:left 0
|
|
||||||
:right 0})
|
|
||||||
|
|
||||||
(def overlay-highlight
|
(def overlay-highlight
|
||||||
{:flex 1})
|
{:flex 1})
|
||||||
|
|
||||||
|
;; this map looks a bit strange
|
||||||
|
;; but this way of setting elevation seems to be the only way to set z-index (in RN 0.30)
|
||||||
|
(def bottom-info-overlay
|
||||||
|
{:position :absolute
|
||||||
|
:top -16
|
||||||
|
:bottom -16
|
||||||
|
:left -16
|
||||||
|
:right -16
|
||||||
|
:background-color "#00000055"
|
||||||
|
:elevation 8})
|
||||||
|
|
||||||
|
(defn bottom-info-container [height]
|
||||||
|
{:backgroundColor toolbar-background1
|
||||||
|
:elevation 2
|
||||||
|
:position :absolute
|
||||||
|
:bottom 16
|
||||||
|
:left 16
|
||||||
|
:right 16
|
||||||
|
:height height})
|
||||||
|
|
||||||
|
(def bottom-info-list-container
|
||||||
|
{:padding-left 16
|
||||||
|
:padding-right 16
|
||||||
|
:padding-top 8
|
||||||
|
:padding-bottom 8})
|
||||||
|
|
||||||
|
(def bottom-info-row
|
||||||
|
{:flex-direction "row"
|
||||||
|
:padding-top 4
|
||||||
|
:padding-bottom 4})
|
||||||
|
|
||||||
|
(def bottom-info-row-photo
|
||||||
|
{:width 42
|
||||||
|
:height 42
|
||||||
|
:borderRadius 21})
|
||||||
|
|
||||||
|
(def bottom-info-row-text-container
|
||||||
|
{:margin-left 16
|
||||||
|
:margin-right 16})
|
||||||
|
|
||||||
|
(def bottom-info-row-text1
|
||||||
|
{:color "black"})
|
||||||
|
|
||||||
|
(def bottom-info-row-text2
|
||||||
|
{:color "#888888"})
|
|
@ -3,6 +3,7 @@
|
||||||
(:require [re-frame.core :refer [register-sub dispatch subscribe path]]
|
(:require [re-frame.core :refer [register-sub dispatch subscribe path]]
|
||||||
[status-im.utils.platform :refer [ios?]]
|
[status-im.utils.platform :refer [ios?]]
|
||||||
[status-im.models.commands :as commands]
|
[status-im.models.commands :as commands]
|
||||||
|
[status-im.models.chats :as chats]
|
||||||
[status-im.constants :refer [response-suggesstion-resize-duration]]
|
[status-im.constants :refer [response-suggesstion-resize-duration]]
|
||||||
[status-im.chat.constants :as c]
|
[status-im.chat.constants :as c]
|
||||||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||||
|
@ -19,9 +20,9 @@
|
||||||
(into {}))))
|
(into {}))))
|
||||||
|
|
||||||
(register-sub
|
(register-sub
|
||||||
:show-actions
|
:chat-ui-props
|
||||||
(fn [db _]
|
(fn [db [_ ui-element]]
|
||||||
(reaction (:show-actions @db))))
|
(reaction (get-in @db [:chat-ui-props ui-element]))))
|
||||||
|
|
||||||
(register-sub :chat
|
(register-sub :chat
|
||||||
(fn [db [_ k]]
|
(fn [db [_ k]]
|
||||||
|
@ -48,6 +49,10 @@
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(reaction (commands/get-commands @db))))
|
(reaction (commands/get-commands @db))))
|
||||||
|
|
||||||
|
(register-sub :get-chat-by-id
|
||||||
|
(fn [_ [_ chat-id]]
|
||||||
|
(reaction (chats/chat-by-id chat-id))))
|
||||||
|
|
||||||
(register-sub :get-responses
|
(register-sub :get-responses
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(let [current-chat (@db :current-chat-id)]
|
(let [current-chat (@db :current-chat-id)]
|
||||||
|
|
|
@ -105,7 +105,7 @@
|
||||||
subtitle]
|
subtitle]
|
||||||
icon-name :icon}]
|
icon-name :icon}]
|
||||||
[touchable-highlight {:on-press (fn []
|
[touchable-highlight {:on-press (fn []
|
||||||
(dispatch [:set-show-actions false])
|
(dispatch [:set-chat-ui-props :show-actions? false])
|
||||||
(when handler
|
(when handler
|
||||||
(handler)))}
|
(handler)))}
|
||||||
[view st/action-icon-row
|
[view st/action-icon-row
|
||||||
|
@ -138,5 +138,5 @@
|
||||||
^{:key action} [action-view action]))]])))
|
^{:key action} [action-view action]))]])))
|
||||||
|
|
||||||
(defn actions-view []
|
(defn actions-view []
|
||||||
[overlay {:on-click-outside #(dispatch [:set-show-actions false])}
|
[overlay {:on-click-outside #(dispatch [:set-chat-ui-props :show-actions? false])}
|
||||||
[actions-list-view]])
|
[actions-list-view]])
|
|
@ -0,0 +1,94 @@
|
||||||
|
(ns status-im.chat.views.bottom-info
|
||||||
|
(:require-macros [status-im.utils.views :refer [defview]])
|
||||||
|
(:require [re-frame.core :refer [subscribe dispatch]]
|
||||||
|
[reagent.core :as r]
|
||||||
|
[status-im.components.react :refer [view
|
||||||
|
animated-view
|
||||||
|
image
|
||||||
|
text
|
||||||
|
icon
|
||||||
|
touchable-highlight
|
||||||
|
list-view
|
||||||
|
list-item]]
|
||||||
|
[status-im.components.chat-icon.screen :refer [chat-icon-view-menu-item]]
|
||||||
|
[status-im.chat.styles.screen :as st]
|
||||||
|
[status-im.i18n :refer [label label-pluralize message-status-label]]
|
||||||
|
[status-im.components.animation :as anim]
|
||||||
|
[status-im.utils.utils :refer [truncate-str]]
|
||||||
|
[status-im.utils.identicon :refer [identicon]]
|
||||||
|
[status-im.utils.listview :as lw]
|
||||||
|
[status-im.utils.logging :as log]
|
||||||
|
[clojure.string :as str]))
|
||||||
|
|
||||||
|
(defn- container-animation-logic [{:keys [to-value val]}]
|
||||||
|
(fn [_]
|
||||||
|
(let [to-value @to-value]
|
||||||
|
(anim/start
|
||||||
|
(anim/spring val {:toValue to-value
|
||||||
|
:friction 6
|
||||||
|
:tension 40})))))
|
||||||
|
|
||||||
|
(defn overlay [{:keys [on-click-outside]} items]
|
||||||
|
[view {:style st/bottom-info-overlay}
|
||||||
|
[touchable-highlight {:on-press on-click-outside
|
||||||
|
:style st/overlay-highlight}
|
||||||
|
[view nil]]
|
||||||
|
items])
|
||||||
|
|
||||||
|
(defn container [& _]
|
||||||
|
(let [layout-height (r/atom 0)
|
||||||
|
anim-value (anim/create-value 1)
|
||||||
|
context {:to-value layout-height
|
||||||
|
:val anim-value}
|
||||||
|
on-update (container-animation-logic context)]
|
||||||
|
(r/create-class
|
||||||
|
{:component-did-update
|
||||||
|
on-update
|
||||||
|
:reagent-render
|
||||||
|
(fn [& children]
|
||||||
|
@layout-height
|
||||||
|
[animated-view {:style (st/bottom-info-container anim-value)}
|
||||||
|
(into [view {:onLayout (fn [event]
|
||||||
|
(let [height (.. event -nativeEvent -layout -height)]
|
||||||
|
(reset! layout-height height)))}]
|
||||||
|
children)])})))
|
||||||
|
|
||||||
|
(defn message-status-row [{:keys [photo-path name]} {:keys [whisper-identity status]}]
|
||||||
|
[view st/bottom-info-row
|
||||||
|
[image {:source {:uri (or photo-path (identicon whisper-identity))}
|
||||||
|
:style st/bottom-info-row-photo}]
|
||||||
|
[view st/bottom-info-row-text-container
|
||||||
|
[text {:style st/bottom-info-row-text1
|
||||||
|
:number-of-lines 1}
|
||||||
|
(truncate-str (if-not (str/blank? name)
|
||||||
|
name
|
||||||
|
whisper-identity) 30)]
|
||||||
|
[text {:style st/bottom-info-row-text2
|
||||||
|
:number-of-lines 1}
|
||||||
|
(message-status-label (or status :sending))]]])
|
||||||
|
|
||||||
|
(defn render-row [contacts]
|
||||||
|
(fn [{:keys [whisper-identity] :as row} _ _]
|
||||||
|
(let [contact (get contacts whisper-identity)]
|
||||||
|
(list-item [message-status-row contact row]))))
|
||||||
|
|
||||||
|
(defn bottom-info-view []
|
||||||
|
(let [bottom-info (subscribe [:chat-ui-props :bottom-info])
|
||||||
|
contacts (subscribe [:get-contacts])]
|
||||||
|
(r/create-class
|
||||||
|
{:reagent-render
|
||||||
|
(fn []
|
||||||
|
(let [{:keys [user-statuses message-status participants]} @bottom-info
|
||||||
|
participants (->> participants
|
||||||
|
(map (fn [{:keys [identity]}]
|
||||||
|
[identity {:whisper-identity identity
|
||||||
|
:status message-status}]))
|
||||||
|
(into {}))]
|
||||||
|
[overlay {:on-click-outside #(dispatch [:set-chat-ui-props :show-bottom-info? false])}
|
||||||
|
[container
|
||||||
|
[list-view {:dataSource (-> (merge participants user-statuses)
|
||||||
|
(vals)
|
||||||
|
(lw/to-datasource))
|
||||||
|
:enableEmptySections true
|
||||||
|
:renderRow (render-row @contacts)
|
||||||
|
:contentContainerStyle st/bottom-info-list-container}]]]))})))
|
|
@ -12,6 +12,7 @@
|
||||||
[status-im.components.animation :as anim]
|
[status-im.components.animation :as anim]
|
||||||
[status-im.chat.views.request-message :refer [message-content-command-request]]
|
[status-im.chat.views.request-message :refer [message-content-command-request]]
|
||||||
[status-im.chat.styles.message :as st]
|
[status-im.chat.styles.message :as st]
|
||||||
|
[status-im.models.chats :refer [chat-by-id]]
|
||||||
[status-im.models.commands :refer [parse-command-message-content
|
[status-im.models.commands :refer [parse-command-message-content
|
||||||
parse-command-request]]
|
parse-command-request]]
|
||||||
[status-im.resources :as res]
|
[status-im.resources :as res]
|
||||||
|
@ -20,7 +21,10 @@
|
||||||
content-type-status
|
content-type-status
|
||||||
content-type-command
|
content-type-command
|
||||||
content-type-command-request]]
|
content-type-command-request]]
|
||||||
[status-im.utils.logging :as log]))
|
[status-im.utils.logging :as log]
|
||||||
|
[status-im.protocol.api :as api]
|
||||||
|
[status-im.utils.identicon :refer [identicon]]
|
||||||
|
[status-im.chat.utils :as cu]))
|
||||||
|
|
||||||
(defn message-date [timestamp]
|
(defn message-date [timestamp]
|
||||||
[view {}
|
[view {}
|
||||||
|
@ -131,18 +135,64 @@
|
||||||
[message-content-audio {:content content
|
[message-content-audio {:content content
|
||||||
:content-type content-type}]]])
|
:content-type content-type}]]])
|
||||||
|
|
||||||
(defview message-delivery-status [{:keys [delivery-status chat-id message-id] :as message}]
|
(defview group-message-delivery-status [{:keys [message-id group-id message-status user-statuses] :as msg}]
|
||||||
[status [:get-in [:message-status chat-id message-id]]]
|
[app-db-message-user-statuses [:get-in [:message-user-statuses message-id]]
|
||||||
[view st/delivery-view
|
app-db-message-status-value [:get-in [:message-statuses message-id :status]]
|
||||||
[image {:source (case (or status delivery-status)
|
chat [:get-chat-by-id group-id]
|
||||||
:seen {:uri :icon_ok_small}
|
contacts [:get-contacts]]
|
||||||
:seen-by-everyone {:uri :icon_ok_small}
|
(let [status (or message-status app-db-message-status-value :sending)
|
||||||
:failed res/delivery-failed-icon
|
user-statuses (merge user-statuses app-db-message-user-statuses)
|
||||||
nil)
|
participants (:contacts chat)
|
||||||
:style st/delivery-image}]
|
seen-by-everyone? (and (= (count user-statuses) (count participants))
|
||||||
[text {:style st/delivery-text
|
(every? (fn [[_ {:keys [status]}]]
|
||||||
:font :default}
|
(= (keyword status) :seen)) user-statuses))]
|
||||||
(message-status-label (or status delivery-status))]])
|
(if (or (zero? (count user-statuses))
|
||||||
|
seen-by-everyone?)
|
||||||
|
[view st/delivery-view
|
||||||
|
[image {:source (case status
|
||||||
|
:seen {:uri :icon_ok_small}
|
||||||
|
:failed res/delivery-failed-icon
|
||||||
|
nil)
|
||||||
|
:style st/delivery-image}]
|
||||||
|
[text {:style st/delivery-text
|
||||||
|
:font :default}
|
||||||
|
(message-status-label
|
||||||
|
(if seen-by-everyone?
|
||||||
|
:seen-by-everyone
|
||||||
|
status))]]
|
||||||
|
[touchable-highlight
|
||||||
|
{:on-press (fn []
|
||||||
|
(dispatch [:show-message-details {:message-status status
|
||||||
|
:user-statuses user-statuses
|
||||||
|
:participants participants}]))}
|
||||||
|
[view st/delivery-view
|
||||||
|
(for [[_ {:keys [whisper-identity]}] (take 3 user-statuses)]
|
||||||
|
^{:key whisper-identity}
|
||||||
|
[image {:source {:uri (or (get-in contacts [whisper-identity :photo-path])
|
||||||
|
(identicon whisper-identity))}
|
||||||
|
:style {:width 16
|
||||||
|
:height 16
|
||||||
|
:borderRadius 8}}])
|
||||||
|
(if (> (count user-statuses) 3)
|
||||||
|
[text {:style st/delivery-text
|
||||||
|
:font :default}
|
||||||
|
(str "+ " (- (count user-statuses) 3))])]])))
|
||||||
|
|
||||||
|
(defview message-delivery-status [{:keys [message-id chat-id message-status user-statuses]}]
|
||||||
|
[app-db-message-status-value [:get-in [:message-statuses message-id :status]]]
|
||||||
|
(let [delivery-status (get-in user-statuses [chat-id :status])
|
||||||
|
status (if (cu/console? chat-id)
|
||||||
|
:seen
|
||||||
|
(or delivery-status message-status app-db-message-status-value :sending))]
|
||||||
|
[view st/delivery-view
|
||||||
|
[image {:source (case status
|
||||||
|
:seen {:uri :icon_ok_small}
|
||||||
|
:failed res/delivery-failed-icon
|
||||||
|
nil)
|
||||||
|
:style st/delivery-image}]
|
||||||
|
[text {:style st/delivery-text
|
||||||
|
:font :default}
|
||||||
|
(message-status-label status)]]))
|
||||||
|
|
||||||
(defview member-photo [from]
|
(defview member-photo [from]
|
||||||
[photo-path [:photo-path from]]
|
[photo-path [:photo-path from]]
|
||||||
|
@ -167,14 +217,16 @@
|
||||||
content
|
content
|
||||||
;; TODO show for last or selected
|
;; TODO show for last or selected
|
||||||
(when (and selected delivery-status)
|
(when (and selected delivery-status)
|
||||||
[message-delivery-status {:delivery-status delivery-status}])]]]))
|
[message-delivery-status message])]]]))
|
||||||
|
|
||||||
(defn message-body
|
(defn message-body
|
||||||
[{:keys [outgoing] :as message} content]
|
[{:keys [outgoing message-type] :as message} content]
|
||||||
[view (st/message-body message)
|
[view (st/message-body message)
|
||||||
content
|
content
|
||||||
(when outgoing
|
(when outgoing
|
||||||
[message-delivery-status message])])
|
(if (= (keyword message-type) :group-user-message)
|
||||||
|
[group-message-delivery-status message]
|
||||||
|
[message-delivery-status message]))])
|
||||||
|
|
||||||
(defn message-container-animation-logic [{:keys [to-value val callback]}]
|
(defn message-container-animation-logic [{:keys [to-value val callback]}]
|
||||||
(fn [_]
|
(fn [_]
|
||||||
|
@ -210,19 +262,18 @@
|
||||||
children)])}))
|
children)])}))
|
||||||
(into [view] children)))
|
(into [view] children)))
|
||||||
|
|
||||||
(defn chat-message [{:keys [outgoing delivery-status timestamp new-day group-chat message-id chat-id]
|
(defn chat-message [{:keys [outgoing message-id chat-id user-statuses]}]
|
||||||
:as message}]
|
(let [my-identity (api/my-identity)
|
||||||
(let [status (subscribe [:get-in [:message-status chat-id message-id]])]
|
status (subscribe [:get-in [:message-user-statuses message-id my-identity]])]
|
||||||
(r/create-class
|
(r/create-class
|
||||||
{:component-did-mount
|
{:component-did-mount
|
||||||
(fn []
|
(fn []
|
||||||
(when (and (not outgoing)
|
(when (and (not outgoing)
|
||||||
(not= :seen delivery-status)
|
(not= :seen (keyword @status))
|
||||||
(not= :seen @status))
|
(not= :seen (keyword (get-in user-statuses [my-identity :status]))))
|
||||||
(dispatch [:send-seen! chat-id message-id])))
|
(dispatch [:send-seen! chat-id message-id])))
|
||||||
:reagent-render
|
:reagent-render
|
||||||
(fn [{:keys [outgoing delivery-status timestamp new-day group-chat]
|
(fn [{:keys [outgoing timestamp new-day group-chat] :as message}]
|
||||||
:as message}]
|
|
||||||
[message-container message
|
[message-container message
|
||||||
;; TODO there is no new-day info in message
|
;; TODO there is no new-day info in message
|
||||||
(when new-day
|
(when new-day
|
||||||
|
@ -233,5 +284,4 @@
|
||||||
(if incoming-group
|
(if incoming-group
|
||||||
incoming-group-message-body
|
incoming-group-message-body
|
||||||
message-body)
|
message-body)
|
||||||
(merge message {:delivery-status (keyword delivery-status)
|
(merge message {:incoming-group incoming-group})])]])})))
|
||||||
:incoming-group incoming-group})])]])})))
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
image
|
image
|
||||||
touchable-highlight]]
|
touchable-highlight]]
|
||||||
[status-im.utils.listview :refer [to-datasource]]
|
[status-im.utils.listview :refer [to-datasource]]
|
||||||
[reagent.core :as r]
|
|
||||||
[status-im.chats-list.views.chat-list-item :refer [chat-list-item]]
|
[status-im.chats-list.views.chat-list-item :refer [chat-list-item]]
|
||||||
[status-im.components.action-button :refer [action-button
|
[status-im.components.action-button :refer [action-button
|
||||||
action-button-item]]
|
action-button-item]]
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
(ns status-im.components.status-bar
|
(ns status-im.components.status-bar
|
||||||
(:require [status-im.components.react :as ui]
|
(:require [status-im.components.react :as ui]
|
||||||
[status-im.components.styles :as cst]
|
|
||||||
[status-im.utils.platform :refer [platform-specific]]))
|
[status-im.utils.platform :refer [platform-specific]]))
|
||||||
|
|
||||||
(defn status-bar [{type :type
|
(defn status-bar [{type :type
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
(register-sub :get-contacts
|
(register-sub :get-contacts
|
||||||
(fn [db _]
|
(fn [db _]
|
||||||
(let [contacts (reaction (:contacts @db))]
|
(let [contacts (reaction (:contacts @db))]
|
||||||
(reaction (vals @contacts)))))
|
(reaction @contacts))))
|
||||||
|
|
||||||
(defn sort-contacts [contacts]
|
(defn sort-contacts [contacts]
|
||||||
(sort-by :name #(compare (clojure.string/lower-case %1)
|
(sort-by :name #(compare (clojure.string/lower-case %1)
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
(.isAddress js/Web3.prototype s))
|
(.isAddress js/Web3.prototype s))
|
||||||
|
|
||||||
(defn unique-identity? [identity]
|
(defn unique-identity? [identity]
|
||||||
(not (realm/exists? :account :contact :whisper-identity identity)))
|
(not (realm/exists? :account :contact {:whisper-identity identity})))
|
||||||
|
|
||||||
(defn valid-length? [identity]
|
(defn valid-length? [identity]
|
||||||
(let [length (count identity)]
|
(let [length (count identity)]
|
||||||
|
|
|
@ -35,7 +35,8 @@
|
||||||
:contacts-ids #{}
|
:contacts-ids #{}
|
||||||
:selected-contacts #{}
|
:selected-contacts #{}
|
||||||
:chats-updated-signal 0
|
:chats-updated-signal 0
|
||||||
:show-actions false
|
:chat-ui-props {:show-actions? false
|
||||||
|
:show-bottom-info? false}
|
||||||
:selected-participants #{}
|
:selected-participants #{}
|
||||||
:signed-up false
|
:signed-up false
|
||||||
:view-id default-view
|
:view-id default-view
|
||||||
|
|
|
@ -39,7 +39,7 @@
|
||||||
(defn discovery-list []
|
(defn discovery-list []
|
||||||
(->> (-> (r/get-all :account :discovery)
|
(->> (-> (r/get-all :account :discovery)
|
||||||
(r/sorted :priority :desc)
|
(r/sorted :priority :desc)
|
||||||
(r/collection->map))
|
(r/realm-collection->list))
|
||||||
(mapv #(update % :tags vals))))
|
(mapv #(update % :tags vals))))
|
||||||
|
|
||||||
(defn- add-discoveries [discoveries]
|
(defn- add-discoveries [discoveries]
|
||||||
|
@ -65,5 +65,5 @@
|
||||||
(defn all-tags []
|
(defn all-tags []
|
||||||
(-> (r/get-all :account :tag)
|
(-> (r/get-all :account :tag)
|
||||||
(r/sorted :count :desc)
|
(r/sorted :count :desc)
|
||||||
r/collection->map))
|
r/realm-collection->list))
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
(defn get-accounts []
|
(defn get-accounts []
|
||||||
(-> (r/get-all :base :account)
|
(-> (r/get-all :base :account)
|
||||||
r/collection->map))
|
r/realm-collection->list))
|
||||||
|
|
||||||
(defn save-account [update?]
|
(defn save-account [update?]
|
||||||
#(r/create :base :account % update?))
|
#(r/create :base :account % update?))
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
chat-id))
|
chat-id))
|
||||||
|
|
||||||
(defn chat-exists? [chat-id]
|
(defn chat-exists? [chat-id]
|
||||||
(r/exists? :account :chat :chat-id chat-id))
|
(r/exists? :account :chat {:chat-id chat-id}))
|
||||||
|
|
||||||
(defn add-status-message [chat-id]
|
(defn add-status-message [chat-id]
|
||||||
;; TODO Get real status
|
;; TODO Get real status
|
||||||
|
@ -39,29 +39,6 @@
|
||||||
:content-type content-type-status
|
:content-type content-type-status
|
||||||
:outgoing false}))
|
:outgoing false}))
|
||||||
|
|
||||||
(defn create-chat
|
|
||||||
([{:keys [last-message-id] :as chat}]
|
|
||||||
(let [chat (assoc chat :last-message-id (or last-message-id ""))]
|
|
||||||
(r/write :account #(r/create :account :chat chat true))))
|
|
||||||
([db chat-id identities group-chat? chat-name]
|
|
||||||
(when-not (chat-exists? chat-id)
|
|
||||||
(let [chat-name (or chat-name
|
|
||||||
(get-chat-name chat-id identities))
|
|
||||||
_ (log/debug "creating chat" chat-name)]
|
|
||||||
(r/write :account
|
|
||||||
(fn []
|
|
||||||
(let [contacts (mapv (fn [ident]
|
|
||||||
{:identity ident}) identities)]
|
|
||||||
(r/create :account :chat
|
|
||||||
{:chat-id chat-id
|
|
||||||
:is-active true
|
|
||||||
:name chat-name
|
|
||||||
:group-chat group-chat?
|
|
||||||
:timestamp (timestamp)
|
|
||||||
:contacts contacts
|
|
||||||
:last-message-id ""}))))
|
|
||||||
(add-status-message chat-id)))))
|
|
||||||
|
|
||||||
(defn chat-contacts [chat-id]
|
(defn chat-contacts [chat-id]
|
||||||
(-> (r/get-by-field :account :chat :chat-id chat-id)
|
(-> (r/get-by-field :account :chat :chat-id chat-id)
|
||||||
(r/single)
|
(r/single)
|
||||||
|
@ -93,7 +70,7 @@
|
||||||
(defn chats-list []
|
(defn chats-list []
|
||||||
(-> (r/get-all :account :chat)
|
(-> (r/get-all :account :chat)
|
||||||
(r/sorted :timestamp :desc)
|
(r/sorted :timestamp :desc)
|
||||||
r/collection->map
|
r/realm-collection->list
|
||||||
normalize-contacts))
|
normalize-contacts))
|
||||||
|
|
||||||
(defn chat-by-id [chat-id]
|
(defn chat-by-id [chat-id]
|
||||||
|
@ -101,6 +78,37 @@
|
||||||
(r/single-cljs)
|
(r/single-cljs)
|
||||||
(r/list-to-array :contacts)))
|
(r/list-to-array :contacts)))
|
||||||
|
|
||||||
|
(defn update-chat [{:keys [last-message-id chat-id] :as chat}]
|
||||||
|
(let [{old-chat-id :chat-id
|
||||||
|
:as old-chat} (chat-by-id chat-id)]
|
||||||
|
(when old-chat-id
|
||||||
|
(let [chat (-> (merge old-chat chat)
|
||||||
|
(assoc chat :last-message-id (or last-message-id "")))]
|
||||||
|
(r/write :account #(r/create :account :chat chat true))))))
|
||||||
|
|
||||||
|
(defn create-chat
|
||||||
|
([{:keys [last-message-id] :as chat}]
|
||||||
|
(let [chat (assoc chat :last-message-id (or last-message-id ""))]
|
||||||
|
(r/write :account #(r/create :account :chat chat true))))
|
||||||
|
([db chat-id identities group-chat? chat-name]
|
||||||
|
(when-not (chat-exists? chat-id)
|
||||||
|
(let [chat-name (or chat-name
|
||||||
|
(get-chat-name chat-id identities))
|
||||||
|
_ (log/debug "creating chat" chat-name)]
|
||||||
|
(r/write :account
|
||||||
|
(fn []
|
||||||
|
(let [contacts (mapv (fn [ident]
|
||||||
|
{:identity ident}) identities)]
|
||||||
|
(r/create :account :chat
|
||||||
|
{:chat-id chat-id
|
||||||
|
:is-active true
|
||||||
|
:name chat-name
|
||||||
|
:group-chat group-chat?
|
||||||
|
:timestamp (timestamp)
|
||||||
|
:contacts contacts
|
||||||
|
:last-message-id ""}))))
|
||||||
|
(add-status-message chat-id)))))
|
||||||
|
|
||||||
(defn chat-add-participants [chat-id identities]
|
(defn chat-add-participants [chat-id identities]
|
||||||
(r/write :account
|
(r/write :account
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
(defn get-contacts []
|
(defn get-contacts []
|
||||||
(-> (r/get-all :account :contact)
|
(-> (r/get-all :account :contact)
|
||||||
(r/sorted :name :asc)
|
(r/sorted :name :asc)
|
||||||
r/collection->map))
|
r/realm-collection->list))
|
||||||
|
|
||||||
(defn get-contact [id]
|
(defn get-contact [id]
|
||||||
(r/get-one-by-field :account :contact :whisper-identity id))
|
(r/get-one-by-field :account :contact :whisper-identity id))
|
||||||
|
|
|
@ -17,6 +17,13 @@
|
||||||
[s]
|
[s]
|
||||||
(keywordize-keys (apply hash-map (split s #"[;=]"))))
|
(keywordize-keys (apply hash-map (split s #"[;=]"))))
|
||||||
|
|
||||||
|
(defn- user-statuses-to-map
|
||||||
|
[user-statuses]
|
||||||
|
(->> (vals user-statuses)
|
||||||
|
(mapv (fn [{:keys [whisper-identity] :as status}]
|
||||||
|
[whisper-identity status]))
|
||||||
|
(into {})))
|
||||||
|
|
||||||
(def default-values
|
(def default-values
|
||||||
{:outgoing false
|
{:outgoing false
|
||||||
:to nil
|
:to nil
|
||||||
|
@ -26,10 +33,9 @@
|
||||||
|
|
||||||
(defn save-message
|
(defn save-message
|
||||||
;; todo remove chat-id parameter
|
;; todo remove chat-id parameter
|
||||||
[chat-id {:keys [delivery-status message-id content]
|
[chat-id {:keys [message-id content]
|
||||||
:or {delivery-status :sending}
|
|
||||||
:as message}]
|
:as message}]
|
||||||
(when-not (r/exists? :account :message :message-id message-id)
|
(when-not (r/exists? :account :message {:message-id message-id})
|
||||||
(r/write :account
|
(r/write :account
|
||||||
(fn []
|
(fn []
|
||||||
(let [content' (if (string? content)
|
(let [content' (if (string? content)
|
||||||
|
@ -39,7 +45,6 @@
|
||||||
message
|
message
|
||||||
{:chat-id chat-id
|
{:chat-id chat-id
|
||||||
:content content'
|
:content content'
|
||||||
:delivery-status delivery-status
|
|
||||||
:timestamp (timestamp)})]
|
:timestamp (timestamp)})]
|
||||||
(r/create :account :message message' true))))))
|
(r/create :account :message message' true))))))
|
||||||
|
|
||||||
|
@ -54,26 +59,29 @@
|
||||||
(->> (-> (r/get-by-field :account :message :chat-id chat-id)
|
(->> (-> (r/get-by-field :account :message :chat-id chat-id)
|
||||||
(r/sorted :timestamp :desc)
|
(r/sorted :timestamp :desc)
|
||||||
(r/page from (+ from c/default-number-of-messages))
|
(r/page from (+ from c/default-number-of-messages))
|
||||||
(r/collection->map))
|
(r/realm-collection->list))
|
||||||
|
(mapv #(update % :user-statuses user-statuses-to-map))
|
||||||
(into '())
|
(into '())
|
||||||
reverse
|
reverse
|
||||||
(keep (fn [{:keys [content-type preview] :as message}]
|
(keep (fn [{:keys [content-type preview] :as message}]
|
||||||
(if (command-type? content-type)
|
(if (command-type? content-type)
|
||||||
(-> message
|
(-> message
|
||||||
(update :content str-to-map)
|
(update :content str-to-map)
|
||||||
(assoc :rendered-preview
|
(assoc :rendered-preview
|
||||||
(when preview
|
(when preview
|
||||||
(generate-hiccup (read-string preview)))))
|
(generate-hiccup (read-string preview)))))
|
||||||
message))))))
|
message))))))
|
||||||
|
|
||||||
(defn update-message! [{:keys [message-id] :as message}]
|
(defn update-message! [{:keys [message-id] :as message}]
|
||||||
(r/write :account
|
(r/write :account
|
||||||
(fn []
|
(fn []
|
||||||
(when (r/exists? :account :message :message-id message-id)
|
(when (r/exists? :account :message {:message-id message-id})
|
||||||
(r/create :account :message message true)))))
|
(let [message (update message :user-statuses vals)]
|
||||||
|
(r/create :account :message message true))))))
|
||||||
|
|
||||||
(defn get-message [id]
|
(defn get-message [id]
|
||||||
(r/get-one-by-field :account :message :message-id id))
|
(some-> (r/get-one-by-field :account :message :message-id id)
|
||||||
|
(update :user-statuses user-statuses-to-map)))
|
||||||
|
|
||||||
(defn get-last-message [chat-id]
|
(defn get-last-message [chat-id]
|
||||||
(-> (r/get-by-field :account :message :chat-id chat-id)
|
(-> (r/get-by-field :account :message :chat-id chat-id)
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
[:status :sent]
|
[:status :sent]
|
||||||
[:status :failed]])
|
[:status :failed]])
|
||||||
(r/sorted :timestamp :desc)
|
(r/sorted :timestamp :desc)
|
||||||
(r/collection->map))]
|
(r/realm-collection->list))]
|
||||||
(->> collection
|
(->> collection
|
||||||
(map (fn [{:keys [message-id] :as message}]
|
(map (fn [{:keys [message-id] :as message}]
|
||||||
(let [message (-> message
|
(let [message (-> message
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
(defn get-requests []
|
(defn get-requests []
|
||||||
(-> (r/get-all :account :request)
|
(-> (r/get-all :account :request)
|
||||||
r/collection->map))
|
r/realm-collection->list))
|
||||||
|
|
||||||
(defn create-request [request]
|
(defn create-request [request]
|
||||||
(r/create :account :request request true))
|
(r/create :account :request request true))
|
||||||
|
|
|
@ -168,8 +168,8 @@
|
||||||
(defn delete [schema obj]
|
(defn delete [schema obj]
|
||||||
(.delete (realm schema) obj))
|
(.delete (realm schema) obj))
|
||||||
|
|
||||||
(defn exists? [schema schema-name field value]
|
(defn exists? [schema schema-name fields]
|
||||||
(pos? (.-length (get-by-field schema schema-name field value))))
|
(pos? (.-length (get-by-fields schema schema-name :and fields))))
|
||||||
|
|
||||||
(defn get-count [objs]
|
(defn get-count [objs]
|
||||||
(.-length objs))
|
(.-length objs))
|
||||||
|
@ -177,7 +177,7 @@
|
||||||
(defn get-list [schema schema-name]
|
(defn get-list [schema schema-name]
|
||||||
(vals (js->clj (.objects (realm schema) (to-string schema-name)) :keywordize-keys true)))
|
(vals (js->clj (.objects (realm schema) (to-string schema-name)) :keywordize-keys true)))
|
||||||
|
|
||||||
(defn collection->map [collection]
|
(defn realm-collection->list [collection]
|
||||||
(-> (.map collection (fn [object _ _] object))
|
(-> (.map collection (fn [object _ _] object))
|
||||||
(js->clj :keywordize-keys true)))
|
(js->clj :keywordize-keys true)))
|
||||||
|
|
||||||
|
|
|
@ -52,30 +52,38 @@
|
||||||
:primaryKey :key
|
:primaryKey :key
|
||||||
:properties {:key "string"
|
:properties {:key "string"
|
||||||
:value "string"}}
|
:value "string"}}
|
||||||
|
{:name :user-status
|
||||||
|
:primaryKey :id
|
||||||
|
:properties {:id "string"
|
||||||
|
:whisper-identity {:type "string"
|
||||||
|
:default ""}
|
||||||
|
:status "string"}}
|
||||||
{:name :message
|
{:name :message
|
||||||
:primaryKey :message-id
|
:primaryKey :message-id
|
||||||
:properties {:message-id "string"
|
:properties {:message-id "string"
|
||||||
:from "string"
|
:from "string"
|
||||||
:to {:type "string"
|
:to {:type "string"
|
||||||
:optional true}
|
:optional true}
|
||||||
:group-id {:type "string"
|
:group-id {:type "string"
|
||||||
:optional true}
|
:optional true}
|
||||||
:content "string" ;; TODO make it ArrayBuffer
|
:content "string" ;; TODO make it ArrayBuffer
|
||||||
:content-type "string"
|
:content-type "string"
|
||||||
:timestamp "int"
|
:timestamp "int"
|
||||||
:chat-id {:type "string"
|
:chat-id {:type "string"
|
||||||
:indexed true}
|
:indexed true}
|
||||||
:outgoing "bool"
|
:outgoing "bool"
|
||||||
:delivery-status {:type "string"
|
:retry-count {:type :int
|
||||||
:optional true}
|
:default 0}
|
||||||
:retry-count {:type :int
|
:same-author "bool"
|
||||||
:default 0}
|
:same-direction "bool"
|
||||||
:same-author "bool"
|
:preview {:type :string
|
||||||
:same-direction "bool"
|
:optional true}
|
||||||
:preview {:type :string
|
:message-type {:type :string
|
||||||
:optional true}
|
:optional true}
|
||||||
:message-type {:type :string
|
:message-status {:type :string
|
||||||
:optional true}}}
|
:optional true}
|
||||||
|
:user-statuses {:type :list
|
||||||
|
:objectType "user-status"}}}
|
||||||
{:name :pending-message
|
{:name :pending-message
|
||||||
:primaryKey :message-id
|
:primaryKey :message-id
|
||||||
:properties {:message-id "string"
|
:properties {:message-id "string"
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
(r/single-cljs)
|
(r/single-cljs)
|
||||||
(r/decode-value)))
|
(r/decode-value)))
|
||||||
(contains-key? [_ key]
|
(contains-key? [_ key]
|
||||||
(r/exists? schema :kv-store :key key))
|
(r/exists? schema :kv-store {:key key}))
|
||||||
(delete [_ key]
|
(delete [_ key]
|
||||||
(r/write schema
|
(r/write schema
|
||||||
(fn []
|
(fn []
|
||||||
|
|
|
@ -15,7 +15,8 @@
|
||||||
[status-im.models.protocol :refer [update-identity
|
[status-im.models.protocol :refer [update-identity
|
||||||
set-initialized]]
|
set-initialized]]
|
||||||
[status-im.constants :refer [text-content-type]]
|
[status-im.constants :refer [text-content-type]]
|
||||||
[status-im.i18n :refer [label]]))
|
[status-im.i18n :refer [label]]
|
||||||
|
[status-im.utils.random :as random]))
|
||||||
|
|
||||||
(register-handler :initialize-protocol
|
(register-handler :initialize-protocol
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
|
@ -104,49 +105,54 @@
|
||||||
(log/debug action message-id from group-id identity)
|
(log/debug action message-id from group-id identity)
|
||||||
(participant-invited-to-group-message group-id identity from message-id))))
|
(participant-invited-to-group-message group-id identity from message-id))))
|
||||||
|
|
||||||
(defn update-message! [status]
|
(defn save-message-status! [status]
|
||||||
(fn [_ [_ _ message-id]]
|
(fn [_ [_ {:keys [message-id whisper-identity]}]]
|
||||||
(messages/update-message! {:message-id message-id
|
(when-let [message (messages/get-message message-id)]
|
||||||
:delivery-status status})))
|
(let [message (if whisper-identity
|
||||||
|
(update-in message
|
||||||
|
[:user-statuses whisper-identity]
|
||||||
|
(fn [{old-status :status}]
|
||||||
|
{:id (random/id)
|
||||||
|
:whisper-identity whisper-identity
|
||||||
|
:status (if (= (keyword old-status) :seen)
|
||||||
|
old-status
|
||||||
|
status)}))
|
||||||
|
(assoc message :message-status status))]
|
||||||
|
(messages/update-message! message)))))
|
||||||
|
|
||||||
(defn update-message-status [status]
|
(defn update-message-status [status]
|
||||||
(fn [db [_ chat-id message-id]]
|
(fn [db [_ {:keys [message-id whisper-identity]}]]
|
||||||
(let [current-status (get-in db [:message-status chat-id message-id])]
|
(let [db-key (if whisper-identity
|
||||||
|
[:message-user-statuses message-id whisper-identity]
|
||||||
|
[:message-statuses message-id])
|
||||||
|
current-status (get-in db db-key)]
|
||||||
(if-not (= :seen current-status)
|
(if-not (= :seen current-status)
|
||||||
(assoc-in db [:message-status chat-id message-id] status)
|
(assoc-in db db-key {:whisper-identity whisper-identity
|
||||||
|
:status status})
|
||||||
db))))
|
db))))
|
||||||
|
|
||||||
(register-handler :message-delivered
|
|
||||||
(after (update-message! :delivered))
|
|
||||||
(update-message-status :delivered))
|
|
||||||
|
|
||||||
(register-handler :message-failed
|
(register-handler :message-failed
|
||||||
(after (update-message! :failed))
|
(after (save-message-status! :failed))
|
||||||
(update-message-status :failed))
|
(update-message-status :failed))
|
||||||
|
|
||||||
(register-handler :message-sent
|
(register-handler :message-sent
|
||||||
(after (update-message! :sent))
|
(after (save-message-status! :sent))
|
||||||
(update-message-status :sent))
|
(update-message-status :sent))
|
||||||
|
|
||||||
|
(register-handler :message-delivered
|
||||||
|
(after (save-message-status! :delivered))
|
||||||
|
(update-message-status :delivered))
|
||||||
|
|
||||||
(register-handler :message-seen
|
(register-handler :message-seen
|
||||||
[(after (update-message! :seen))
|
[(after (save-message-status! :seen))
|
||||||
(after (fn [_ [_ chat-id]]
|
(after (fn [_ [_ {:keys [chat-id]}]]
|
||||||
(dispatch [:remove-unviewed-messages chat-id])))]
|
(dispatch [:remove-unviewed-messages chat-id])))]
|
||||||
(update-message-status :seen))
|
(update-message-status :seen))
|
||||||
|
|
||||||
(register-handler :pending-message-upsert
|
(register-handler :pending-message-upsert
|
||||||
(after
|
(u/side-effect!
|
||||||
(fn [_ [_ {:keys [message-id status] :as pending-message}]]
|
(fn [_ [_ pending-message]]
|
||||||
(pending-messages/upsert-pending-message! pending-message)
|
(pending-messages/upsert-pending-message! pending-message))))
|
||||||
(messages/update-message! {:message-id message-id
|
|
||||||
:delivery-status status})))
|
|
||||||
(fn [db [_ {:keys [message-id chat-id status] :as pending-message}]]
|
|
||||||
(if chat-id
|
|
||||||
(let [current-status (get-in db [:message-status chat-id message-id])]
|
|
||||||
(if-not (= :seen current-status)
|
|
||||||
(assoc-in db [:message-status chat-id message-id] status)
|
|
||||||
db))
|
|
||||||
db)))
|
|
||||||
|
|
||||||
(register-handler :pending-message-remove
|
(register-handler :pending-message-remove
|
||||||
(u/side-effect!
|
(u/side-effect!
|
||||||
|
|
|
@ -23,14 +23,18 @@
|
||||||
:to to)]))
|
:to to)]))
|
||||||
:contact-request (let [{:keys [from payload]} event]
|
:contact-request (let [{:keys [from payload]} event]
|
||||||
(dispatch [:contact-request-received (assoc payload :from from)]))
|
(dispatch [:contact-request-received (assoc payload :from from)]))
|
||||||
:message-delivered (let [{:keys [message-id from]} event]
|
:message-delivered (let [{:keys [from message-id]} event]
|
||||||
(dispatch [:message-delivered from message-id]))
|
(dispatch [:message-delivered {:whisper-identity from
|
||||||
:message-seen (let [{:keys [message-id from]} event]
|
:message-id message-id}]))
|
||||||
(dispatch [:message-seen from message-id]))
|
:message-seen (let [{:keys [from message-id]} event]
|
||||||
:message-failed (let [{:keys [message-id chat-id] :as event} event]
|
(dispatch [:message-seen {:whisper-identity from
|
||||||
(dispatch [:message-failed chat-id message-id]))
|
:message-id message-id}]))
|
||||||
:message-sent (let [{:keys [message-id chat-id]} event]
|
:message-failed (let [{:keys [chat-id message-id]} event]
|
||||||
(dispatch [:message-sent chat-id message-id]))
|
(dispatch [:message-failed {:chat-id chat-id
|
||||||
|
:message-id message-id}]))
|
||||||
|
:message-sent (let [{:keys [chat-id message-id] :as data} event]
|
||||||
|
(dispatch [:message-sent {:chat-id chat-id
|
||||||
|
:message-id message-id}]))
|
||||||
:user-discovery-keypair (let [{:keys [from]} event]
|
:user-discovery-keypair (let [{:keys [from]} event]
|
||||||
(dispatch [:contact-keypair-received from]))
|
(dispatch [:contact-keypair-received from]))
|
||||||
:pending-message-upsert (let [{message :message} event]
|
:pending-message-upsert (let [{message :message} event]
|
||||||
|
|
Loading…
Reference in New Issue