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]]
|
||||
[re-frame "0.7.0"]
|
||||
[prismatic/schema "1.0.4"]
|
||||
^{:voom {:repo "git@github.com:status-im/status-lib.git"
|
||||
:branch "master"}}
|
||||
[status-im/protocol "0.2.2-20160909_082306-gcfbb92b"]
|
||||
^{:voom {:repo "git@github.com:status-im/status-lib.git" :branch "group-chat-statuses"}}
|
||||
[status-im/protocol "0.2.3-20160914_155558-gfed628a"]
|
||||
[natal-shell "0.3.0"]
|
||||
[com.andrewmcveigh/cljs-time "0.4.0"]
|
||||
[tailrecursion/cljs-priority-map "1.2.0"]
|
||||
|
|
|
@ -36,9 +36,19 @@
|
|||
status-im.chat.handlers.wallet-chat
|
||||
[status-im.utils.logging :as log]))
|
||||
|
||||
(register-handler :set-show-actions
|
||||
(fn [db [_ show-actions]]
|
||||
(assoc db :show-actions show-actions)))
|
||||
(register-handler :set-chat-ui-props
|
||||
(fn [db [_ ui-element value]]
|
||||
(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
|
||||
(fn [{:keys [current-chat-id loading-allowed] :as db} _]
|
||||
|
@ -296,7 +306,6 @@
|
|||
[{:keys [new-chat]} _]
|
||||
(chats/create-chat new-chat))
|
||||
|
||||
|
||||
(defn open-chat!
|
||||
[_ [_ chat-id _ navigation-type]]
|
||||
(dispatch [(or navigation-type :navigate-to) :chat chat-id]))
|
||||
|
@ -395,11 +404,10 @@
|
|||
(fn [db [_ h]]
|
||||
(assoc db :layout-height h)))
|
||||
|
||||
|
||||
(register-handler :send-seen!
|
||||
(after (fn [_ [_ chat-id message-id]]
|
||||
(when-not (console? chat-id))
|
||||
(dispatch [:message-seen chat-id message-id])))
|
||||
(dispatch [:message-seen {:message-id message-id
|
||||
:chat-id chat-id}])))
|
||||
(u/side-effect!
|
||||
(fn [_ [_ chat-id message-id]]
|
||||
(when-not (console? chat-id)
|
||||
|
@ -419,16 +427,16 @@
|
|||
(fn [db [_ chat-id mode]]
|
||||
(assoc-in db [:kb-mode chat-id] mode)))
|
||||
|
||||
(defn save-chat!
|
||||
(defn update-chat!
|
||||
[_ [_ chat]]
|
||||
(chats/create-chat chat))
|
||||
(chats/update-chat chat))
|
||||
|
||||
(register-handler :update-chat!
|
||||
(-> (fn [db [_ {:keys [chat-id] :as chat}]]
|
||||
(if (get-in db [:chats chat-id])
|
||||
(update-in db [:chats chat-id] merge chat)
|
||||
db))
|
||||
((after save-chat!))))
|
||||
((after update-chat!))))
|
||||
|
||||
(register-handler :check-autorun
|
||||
(u/side-effect!
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
[status-im.commands.utils :refer [generate-hiccup]]
|
||||
[status-im.constants :refer [content-type-command-request]]
|
||||
[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}]
|
||||
(if-let [preview (:preview content)]
|
||||
|
@ -34,7 +35,6 @@
|
|||
message' (assoc (->> message
|
||||
(cu/check-author-direction previous-message)
|
||||
(check-preview))
|
||||
:delivery-status :sending
|
||||
:chat-id chat-id')]
|
||||
(store-message message')
|
||||
(when-not (c/chat-exists? chat-id')
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
[{:keys [current-chat-id] :as db} [_ chat-id]]
|
||||
(let [chat-id' (or chat-id current-chat-id)
|
||||
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"]])
|
||||
(realm/sorted :added :desc)
|
||||
(realm/collection->map))
|
||||
(realm/sorted :added :desc)
|
||||
(realm/realm-collection->list))
|
||||
requests' (map #(update % :type keyword) requests)]
|
||||
(assoc-in db [:chats chat-id' :requests] requests')))
|
||||
|
||||
|
|
|
@ -16,11 +16,6 @@
|
|||
[status-im.protocol.api :as api]
|
||||
[status-im.utils.logging :as log]))
|
||||
|
||||
(defn default-delivery-status [chat-id]
|
||||
(if (cu/console? chat-id)
|
||||
:seen
|
||||
:sending))
|
||||
|
||||
(defn prepare-message
|
||||
[{:keys [identity current-chat-id] :as db} _]
|
||||
(let [text (get-in db [:chats current-chat-id :input-text])
|
||||
|
@ -33,7 +28,6 @@
|
|||
:to current-chat-id
|
||||
:from identity
|
||||
:content-type text-content-type
|
||||
:delivery-status (default-delivery-status current-chat-id)
|
||||
:outgoing true
|
||||
:timestamp (time/now-ms)})]
|
||||
(if command
|
||||
|
@ -49,7 +43,6 @@
|
|||
:to chat-id
|
||||
:content (assoc content :preview preview-string)
|
||||
:content-type content-type-command
|
||||
:delivery-status (default-delivery-status chat-id)
|
||||
:outgoing true
|
||||
:preview preview-string
|
||||
:rendered-preview preview
|
||||
|
@ -162,7 +155,6 @@
|
|||
:content message
|
||||
:from identity
|
||||
:content-type text-content-type
|
||||
:delivery-status (default-delivery-status chat-id)
|
||||
:outgoing true
|
||||
:timestamp (time/now-ms)})
|
||||
message'' (if group-chat
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
(ns status-im.chat.handlers.unviewed-messages
|
||||
(:require [re-frame.core :refer [after enrich path dispatch]]
|
||||
[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 []
|
||||
(-> (realm/get-by-fields :account :message :and [[:delivery-status :delivered]
|
||||
[:outgoing false]])
|
||||
(realm/collection->map)))
|
||||
(-> (realm/get-by-fields :account :message :and {:outgoing false
|
||||
:message-status nil})
|
||||
(realm/realm-collection->list)))
|
||||
|
||||
(defn set-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.new-message :refer [chat-message-new]]
|
||||
[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.components.animation :as anim]
|
||||
[reagent.core :as r]
|
||||
|
@ -101,7 +102,7 @@
|
|||
|
||||
(defn toolbar-content []
|
||||
(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]])]
|
||||
(fn []
|
||||
[view (st/chat-name-view @show-actions)
|
||||
|
@ -123,20 +124,20 @@
|
|||
(online-text @contact @chat-id)])])))
|
||||
|
||||
(defn toolbar-action []
|
||||
(let [show-actions (subscribe [:show-actions])]
|
||||
(let [show-actions (subscribe [:chat-ui-props :show-actions?])]
|
||||
(fn []
|
||||
(if @show-actions
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions false])}
|
||||
{:on-press #(dispatch [:set-chat-ui-props :show-actions? false])}
|
||||
[view st/action
|
||||
[icon :up st/up-icon]]]
|
||||
[touchable-highlight
|
||||
{:on-press #(dispatch [:set-show-actions true])}
|
||||
{:on-press #(dispatch [:set-chat-ui-props :show-actions? true])}
|
||||
[view st/action
|
||||
[chat-icon]]]))))
|
||||
|
||||
(defview chat-toolbar []
|
||||
[show-actions [:show-actions]]
|
||||
[show-actions [:chat-ui-props :show-actions?]]
|
||||
[view
|
||||
[status-bar]
|
||||
[toolbar {:hide-nav? show-actions
|
||||
|
@ -182,7 +183,8 @@
|
|||
|
||||
(defn 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?])
|
||||
layout-height (subscribe [:get :layout-height])]
|
||||
(r/create-class
|
||||
|
@ -200,6 +202,10 @@
|
|||
;; todo uncomment this
|
||||
#_(when @group-chat [typing-all])
|
||||
[response-view]
|
||||
(when-not @command? [suggestion-container])
|
||||
(when-not @command?
|
||||
[suggestion-container])
|
||||
[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
|
||||
{:message-id "intro-status"
|
||||
:content (label :t/intro-status)
|
||||
:delivery-status "seen"
|
||||
:from "console"
|
||||
:chat-id "console"
|
||||
:content-type content-type-status
|
||||
|
|
|
@ -2,13 +2,15 @@
|
|||
(:require [status-im.components.styles :refer [font
|
||||
title-font
|
||||
color-white
|
||||
color-black
|
||||
chat-background
|
||||
online-color
|
||||
selected-message-color
|
||||
separator-color
|
||||
text1-color
|
||||
text2-color
|
||||
toolbar-background1]]))
|
||||
toolbar-background1]]
|
||||
[status-im.utils.logging :as log]))
|
||||
|
||||
(def chat-view
|
||||
{:flex 1
|
||||
|
@ -114,6 +116,13 @@
|
|||
:color text2-color
|
||||
:font-size 12})
|
||||
|
||||
(def actions-overlay
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def typing-all
|
||||
{:marginBottom 20})
|
||||
|
||||
|
@ -137,12 +146,51 @@
|
|||
:fontFamily font
|
||||
:color text2-color})
|
||||
|
||||
(def actions-overlay
|
||||
{:position :absolute
|
||||
:top 0
|
||||
:bottom 0
|
||||
:left 0
|
||||
:right 0})
|
||||
|
||||
(def overlay-highlight
|
||||
{: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]]
|
||||
[status-im.utils.platform :refer [ios?]]
|
||||
[status-im.models.commands :as commands]
|
||||
[status-im.models.chats :as chats]
|
||||
[status-im.constants :refer [response-suggesstion-resize-duration]]
|
||||
[status-im.chat.constants :as c]
|
||||
[status-im.handlers.content-suggestions :refer [get-content-suggestions]]
|
||||
|
@ -19,9 +20,9 @@
|
|||
(into {}))))
|
||||
|
||||
(register-sub
|
||||
:show-actions
|
||||
(fn [db _]
|
||||
(reaction (:show-actions @db))))
|
||||
:chat-ui-props
|
||||
(fn [db [_ ui-element]]
|
||||
(reaction (get-in @db [:chat-ui-props ui-element]))))
|
||||
|
||||
(register-sub :chat
|
||||
(fn [db [_ k]]
|
||||
|
@ -48,6 +49,10 @@
|
|||
(fn [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
|
||||
(fn [db _]
|
||||
(let [current-chat (@db :current-chat-id)]
|
||||
|
|
|
@ -105,7 +105,7 @@
|
|||
subtitle]
|
||||
icon-name :icon}]
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(dispatch [:set-show-actions false])
|
||||
(dispatch [:set-chat-ui-props :show-actions? false])
|
||||
(when handler
|
||||
(handler)))}
|
||||
[view st/action-icon-row
|
||||
|
@ -138,5 +138,5 @@
|
|||
^{:key action} [action-view action]))]])))
|
||||
|
||||
(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]])
|
|
@ -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.chat.views.request-message :refer [message-content-command-request]]
|
||||
[status-im.chat.styles.message :as st]
|
||||
[status-im.models.chats :refer [chat-by-id]]
|
||||
[status-im.models.commands :refer [parse-command-message-content
|
||||
parse-command-request]]
|
||||
[status-im.resources :as res]
|
||||
|
@ -20,7 +21,10 @@
|
|||
content-type-status
|
||||
content-type-command
|
||||
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]
|
||||
[view {}
|
||||
|
@ -131,18 +135,64 @@
|
|||
[message-content-audio {:content content
|
||||
:content-type content-type}]]])
|
||||
|
||||
(defview message-delivery-status [{:keys [delivery-status chat-id message-id] :as message}]
|
||||
[status [:get-in [:message-status chat-id message-id]]]
|
||||
[view st/delivery-view
|
||||
[image {:source (case (or status delivery-status)
|
||||
:seen {:uri :icon_ok_small}
|
||||
:seen-by-everyone {:uri :icon_ok_small}
|
||||
:failed res/delivery-failed-icon
|
||||
nil)
|
||||
:style st/delivery-image}]
|
||||
[text {:style st/delivery-text
|
||||
:font :default}
|
||||
(message-status-label (or status delivery-status))]])
|
||||
(defview group-message-delivery-status [{:keys [message-id group-id message-status user-statuses] :as msg}]
|
||||
[app-db-message-user-statuses [:get-in [:message-user-statuses message-id]]
|
||||
app-db-message-status-value [:get-in [:message-statuses message-id :status]]
|
||||
chat [:get-chat-by-id group-id]
|
||||
contacts [:get-contacts]]
|
||||
(let [status (or message-status app-db-message-status-value :sending)
|
||||
user-statuses (merge user-statuses app-db-message-user-statuses)
|
||||
participants (:contacts chat)
|
||||
seen-by-everyone? (and (= (count user-statuses) (count participants))
|
||||
(every? (fn [[_ {:keys [status]}]]
|
||||
(= (keyword status) :seen)) user-statuses))]
|
||||
(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]
|
||||
[photo-path [:photo-path from]]
|
||||
|
@ -167,14 +217,16 @@
|
|||
content
|
||||
;; TODO show for last or selected
|
||||
(when (and selected delivery-status)
|
||||
[message-delivery-status {:delivery-status delivery-status}])]]]))
|
||||
[message-delivery-status message])]]]))
|
||||
|
||||
(defn message-body
|
||||
[{:keys [outgoing] :as message} content]
|
||||
[{:keys [outgoing message-type] :as message} content]
|
||||
[view (st/message-body message)
|
||||
content
|
||||
(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]}]
|
||||
(fn [_]
|
||||
|
@ -210,19 +262,18 @@
|
|||
children)])}))
|
||||
(into [view] children)))
|
||||
|
||||
(defn chat-message [{:keys [outgoing delivery-status timestamp new-day group-chat message-id chat-id]
|
||||
:as message}]
|
||||
(let [status (subscribe [:get-in [:message-status chat-id message-id]])]
|
||||
(defn chat-message [{:keys [outgoing message-id chat-id user-statuses]}]
|
||||
(let [my-identity (api/my-identity)
|
||||
status (subscribe [:get-in [:message-user-statuses message-id my-identity]])]
|
||||
(r/create-class
|
||||
{:component-did-mount
|
||||
(fn []
|
||||
(when (and (not outgoing)
|
||||
(not= :seen delivery-status)
|
||||
(not= :seen @status))
|
||||
(not= :seen (keyword @status))
|
||||
(not= :seen (keyword (get-in user-statuses [my-identity :status]))))
|
||||
(dispatch [:send-seen! chat-id message-id])))
|
||||
:reagent-render
|
||||
(fn [{:keys [outgoing delivery-status timestamp new-day group-chat]
|
||||
:as message}]
|
||||
(fn [{:keys [outgoing timestamp new-day group-chat] :as message}]
|
||||
[message-container message
|
||||
;; TODO there is no new-day info in message
|
||||
(when new-day
|
||||
|
@ -233,5 +284,4 @@
|
|||
(if incoming-group
|
||||
incoming-group-message-body
|
||||
message-body)
|
||||
(merge message {:delivery-status (keyword delivery-status)
|
||||
:incoming-group incoming-group})])]])})))
|
||||
(merge message {:incoming-group incoming-group})])]])})))
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
image
|
||||
touchable-highlight]]
|
||||
[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.components.action-button :refer [action-button
|
||||
action-button-item]]
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
(ns status-im.components.status-bar
|
||||
(:require [status-im.components.react :as ui]
|
||||
[status-im.components.styles :as cst]
|
||||
[status-im.utils.platform :refer [platform-specific]]))
|
||||
|
||||
(defn status-bar [{type :type
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
(register-sub :get-contacts
|
||||
(fn [db _]
|
||||
(let [contacts (reaction (:contacts @db))]
|
||||
(reaction (vals @contacts)))))
|
||||
(reaction @contacts))))
|
||||
|
||||
(defn sort-contacts [contacts]
|
||||
(sort-by :name #(compare (clojure.string/lower-case %1)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(.isAddress js/Web3.prototype s))
|
||||
|
||||
(defn unique-identity? [identity]
|
||||
(not (realm/exists? :account :contact :whisper-identity identity)))
|
||||
(not (realm/exists? :account :contact {:whisper-identity identity})))
|
||||
|
||||
(defn valid-length? [identity]
|
||||
(let [length (count identity)]
|
||||
|
|
|
@ -35,7 +35,8 @@
|
|||
:contacts-ids #{}
|
||||
:selected-contacts #{}
|
||||
:chats-updated-signal 0
|
||||
:show-actions false
|
||||
:chat-ui-props {:show-actions? false
|
||||
:show-bottom-info? false}
|
||||
:selected-participants #{}
|
||||
:signed-up false
|
||||
:view-id default-view
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
(defn discovery-list []
|
||||
(->> (-> (r/get-all :account :discovery)
|
||||
(r/sorted :priority :desc)
|
||||
(r/collection->map))
|
||||
(r/realm-collection->list))
|
||||
(mapv #(update % :tags vals))))
|
||||
|
||||
(defn- add-discoveries [discoveries]
|
||||
|
@ -65,5 +65,5 @@
|
|||
(defn all-tags []
|
||||
(-> (r/get-all :account :tag)
|
||||
(r/sorted :count :desc)
|
||||
r/collection->map))
|
||||
r/realm-collection->list))
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
(defn get-accounts []
|
||||
(-> (r/get-all :base :account)
|
||||
r/collection->map))
|
||||
r/realm-collection->list))
|
||||
|
||||
(defn save-account [update?]
|
||||
#(r/create :base :account % update?))
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
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]
|
||||
;; TODO Get real status
|
||||
|
@ -39,29 +39,6 @@
|
|||
:content-type content-type-status
|
||||
: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]
|
||||
(-> (r/get-by-field :account :chat :chat-id chat-id)
|
||||
(r/single)
|
||||
|
@ -93,7 +70,7 @@
|
|||
(defn chats-list []
|
||||
(-> (r/get-all :account :chat)
|
||||
(r/sorted :timestamp :desc)
|
||||
r/collection->map
|
||||
r/realm-collection->list
|
||||
normalize-contacts))
|
||||
|
||||
(defn chat-by-id [chat-id]
|
||||
|
@ -101,6 +78,37 @@
|
|||
(r/single-cljs)
|
||||
(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]
|
||||
(r/write :account
|
||||
(fn []
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
(defn get-contacts []
|
||||
(-> (r/get-all :account :contact)
|
||||
(r/sorted :name :asc)
|
||||
r/collection->map))
|
||||
r/realm-collection->list))
|
||||
|
||||
(defn get-contact [id]
|
||||
(r/get-one-by-field :account :contact :whisper-identity id))
|
||||
|
|
|
@ -17,6 +17,13 @@
|
|||
[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
|
||||
{:outgoing false
|
||||
:to nil
|
||||
|
@ -26,10 +33,9 @@
|
|||
|
||||
(defn save-message
|
||||
;; todo remove chat-id parameter
|
||||
[chat-id {:keys [delivery-status message-id content]
|
||||
:or {delivery-status :sending}
|
||||
[chat-id {:keys [message-id content]
|
||||
: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
|
||||
(fn []
|
||||
(let [content' (if (string? content)
|
||||
|
@ -39,7 +45,6 @@
|
|||
message
|
||||
{:chat-id chat-id
|
||||
:content content'
|
||||
:delivery-status delivery-status
|
||||
:timestamp (timestamp)})]
|
||||
(r/create :account :message message' true))))))
|
||||
|
||||
|
@ -54,26 +59,29 @@
|
|||
(->> (-> (r/get-by-field :account :message :chat-id chat-id)
|
||||
(r/sorted :timestamp :desc)
|
||||
(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 '())
|
||||
reverse
|
||||
(keep (fn [{:keys [content-type preview] :as message}]
|
||||
(if (command-type? content-type)
|
||||
(-> message
|
||||
(update :content str-to-map)
|
||||
(assoc :rendered-preview
|
||||
(when preview
|
||||
(generate-hiccup (read-string preview)))))
|
||||
message))))))
|
||||
(if (command-type? content-type)
|
||||
(-> message
|
||||
(update :content str-to-map)
|
||||
(assoc :rendered-preview
|
||||
(when preview
|
||||
(generate-hiccup (read-string preview)))))
|
||||
message))))))
|
||||
|
||||
(defn update-message! [{:keys [message-id] :as message}]
|
||||
(r/write :account
|
||||
(fn []
|
||||
(when (r/exists? :account :message :message-id message-id)
|
||||
(r/create :account :message message true)))))
|
||||
(when (r/exists? :account :message {:message-id message-id})
|
||||
(let [message (update message :user-statuses vals)]
|
||||
(r/create :account :message message true))))))
|
||||
|
||||
(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]
|
||||
(-> (r/get-by-field :account :message :chat-id chat-id)
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
[:status :sent]
|
||||
[:status :failed]])
|
||||
(r/sorted :timestamp :desc)
|
||||
(r/collection->map))]
|
||||
(r/realm-collection->list))]
|
||||
(->> collection
|
||||
(map (fn [{:keys [message-id] :as message}]
|
||||
(let [message (-> message
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
(defn get-requests []
|
||||
(-> (r/get-all :account :request)
|
||||
r/collection->map))
|
||||
r/realm-collection->list))
|
||||
|
||||
(defn create-request [request]
|
||||
(r/create :account :request request true))
|
||||
|
|
|
@ -168,8 +168,8 @@
|
|||
(defn delete [schema obj]
|
||||
(.delete (realm schema) obj))
|
||||
|
||||
(defn exists? [schema schema-name field value]
|
||||
(pos? (.-length (get-by-field schema schema-name field value))))
|
||||
(defn exists? [schema schema-name fields]
|
||||
(pos? (.-length (get-by-fields schema schema-name :and fields))))
|
||||
|
||||
(defn get-count [objs]
|
||||
(.-length objs))
|
||||
|
@ -177,7 +177,7 @@
|
|||
(defn get-list [schema schema-name]
|
||||
(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))
|
||||
(js->clj :keywordize-keys true)))
|
||||
|
||||
|
|
|
@ -52,30 +52,38 @@
|
|||
:primaryKey :key
|
||||
:properties {:key "string"
|
||||
:value "string"}}
|
||||
{:name :user-status
|
||||
:primaryKey :id
|
||||
:properties {:id "string"
|
||||
:whisper-identity {:type "string"
|
||||
:default ""}
|
||||
:status "string"}}
|
||||
{:name :message
|
||||
:primaryKey :message-id
|
||||
:properties {:message-id "string"
|
||||
:from "string"
|
||||
:to {:type "string"
|
||||
:optional true}
|
||||
:group-id {:type "string"
|
||||
:optional true}
|
||||
:content "string" ;; TODO make it ArrayBuffer
|
||||
:content-type "string"
|
||||
:timestamp "int"
|
||||
:chat-id {:type "string"
|
||||
:indexed true}
|
||||
:outgoing "bool"
|
||||
:delivery-status {:type "string"
|
||||
:optional true}
|
||||
:retry-count {:type :int
|
||||
:default 0}
|
||||
:same-author "bool"
|
||||
:same-direction "bool"
|
||||
:preview {:type :string
|
||||
:optional true}
|
||||
:message-type {:type :string
|
||||
:optional true}}}
|
||||
:properties {:message-id "string"
|
||||
:from "string"
|
||||
:to {:type "string"
|
||||
:optional true}
|
||||
:group-id {:type "string"
|
||||
:optional true}
|
||||
:content "string" ;; TODO make it ArrayBuffer
|
||||
:content-type "string"
|
||||
:timestamp "int"
|
||||
:chat-id {:type "string"
|
||||
:indexed true}
|
||||
:outgoing "bool"
|
||||
:retry-count {:type :int
|
||||
:default 0}
|
||||
:same-author "bool"
|
||||
:same-direction "bool"
|
||||
:preview {:type :string
|
||||
:optional true}
|
||||
:message-type {:type :string
|
||||
:optional true}
|
||||
:message-status {:type :string
|
||||
:optional true}
|
||||
:user-statuses {:type :list
|
||||
:objectType "user-status"}}}
|
||||
{:name :pending-message
|
||||
:primaryKey :message-id
|
||||
:properties {:message-id "string"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
(r/single-cljs)
|
||||
(r/decode-value)))
|
||||
(contains-key? [_ key]
|
||||
(r/exists? schema :kv-store :key key))
|
||||
(r/exists? schema :kv-store {:key key}))
|
||||
(delete [_ key]
|
||||
(r/write schema
|
||||
(fn []
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
[status-im.models.protocol :refer [update-identity
|
||||
set-initialized]]
|
||||
[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
|
||||
(u/side-effect!
|
||||
|
@ -104,49 +105,54 @@
|
|||
(log/debug action message-id from group-id identity)
|
||||
(participant-invited-to-group-message group-id identity from message-id))))
|
||||
|
||||
(defn update-message! [status]
|
||||
(fn [_ [_ _ message-id]]
|
||||
(messages/update-message! {:message-id message-id
|
||||
:delivery-status status})))
|
||||
(defn save-message-status! [status]
|
||||
(fn [_ [_ {:keys [message-id whisper-identity]}]]
|
||||
(when-let [message (messages/get-message message-id)]
|
||||
(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]
|
||||
(fn [db [_ chat-id message-id]]
|
||||
(let [current-status (get-in db [:message-status chat-id message-id])]
|
||||
(fn [db [_ {:keys [message-id whisper-identity]}]]
|
||||
(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)
|
||||
(assoc-in db [:message-status chat-id message-id] status)
|
||||
(assoc-in db db-key {:whisper-identity whisper-identity
|
||||
:status status})
|
||||
db))))
|
||||
|
||||
(register-handler :message-delivered
|
||||
(after (update-message! :delivered))
|
||||
(update-message-status :delivered))
|
||||
|
||||
(register-handler :message-failed
|
||||
(after (update-message! :failed))
|
||||
(after (save-message-status! :failed))
|
||||
(update-message-status :failed))
|
||||
|
||||
(register-handler :message-sent
|
||||
(after (update-message! :sent))
|
||||
(after (save-message-status! :sent))
|
||||
(update-message-status :sent))
|
||||
|
||||
(register-handler :message-delivered
|
||||
(after (save-message-status! :delivered))
|
||||
(update-message-status :delivered))
|
||||
|
||||
(register-handler :message-seen
|
||||
[(after (update-message! :seen))
|
||||
(after (fn [_ [_ chat-id]]
|
||||
[(after (save-message-status! :seen))
|
||||
(after (fn [_ [_ {:keys [chat-id]}]]
|
||||
(dispatch [:remove-unviewed-messages chat-id])))]
|
||||
(update-message-status :seen))
|
||||
|
||||
(register-handler :pending-message-upsert
|
||||
(after
|
||||
(fn [_ [_ {:keys [message-id status] :as 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)))
|
||||
(u/side-effect!
|
||||
(fn [_ [_ pending-message]]
|
||||
(pending-messages/upsert-pending-message! pending-message))))
|
||||
|
||||
(register-handler :pending-message-remove
|
||||
(u/side-effect!
|
||||
|
|
|
@ -23,14 +23,18 @@
|
|||
:to to)]))
|
||||
:contact-request (let [{:keys [from payload]} event]
|
||||
(dispatch [:contact-request-received (assoc payload :from from)]))
|
||||
:message-delivered (let [{:keys [message-id from]} event]
|
||||
(dispatch [:message-delivered from message-id]))
|
||||
:message-seen (let [{:keys [message-id from]} event]
|
||||
(dispatch [:message-seen from message-id]))
|
||||
:message-failed (let [{:keys [message-id chat-id] :as event} event]
|
||||
(dispatch [:message-failed chat-id message-id]))
|
||||
:message-sent (let [{:keys [message-id chat-id]} event]
|
||||
(dispatch [:message-sent chat-id message-id]))
|
||||
:message-delivered (let [{:keys [from message-id]} event]
|
||||
(dispatch [:message-delivered {:whisper-identity from
|
||||
:message-id message-id}]))
|
||||
:message-seen (let [{:keys [from message-id]} event]
|
||||
(dispatch [:message-seen {:whisper-identity from
|
||||
:message-id message-id}]))
|
||||
:message-failed (let [{:keys [chat-id message-id]} event]
|
||||
(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]
|
||||
(dispatch [:contact-keypair-received from]))
|
||||
:pending-message-upsert (let [{message :message} event]
|
||||
|
|
Loading…
Reference in New Issue