Merge pull request #16 from syng-im/group-chat-2-rebased
group chat actions and events implementation
This commit is contained in:
commit
891ac48d09
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -13,6 +13,8 @@
|
|||
[syng-im.components.sign-up-confirm :refer [sign-up-confirm-view]]
|
||||
[syng-im.components.chats.chats-list :refer [chats-list]]
|
||||
[syng-im.components.chats.new-group :refer [new-group]]
|
||||
[syng-im.components.chat.new-participants :refer [new-participants]]
|
||||
[syng-im.components.chat.remove-participants :refer [remove-participants]]
|
||||
[syng-im.utils.logging :as log]
|
||||
[syng-im.navigation :as nav]
|
||||
[syng-im.utils.encryption]))
|
||||
|
@ -42,6 +44,8 @@
|
|||
view-id (keyword view-id)]
|
||||
(init-back-button-handler! nav)
|
||||
(case view-id
|
||||
:add-participants (r/as-element [new-participants {:navigator nav}])
|
||||
:remove-participants (r/as-element [remove-participants {:navigator nav}])
|
||||
:chat-list (r/as-element [chats-list {:navigator nav}])
|
||||
:new-group (r/as-element [new-group {:navigator nav}])
|
||||
:contact-list (r/as-element [contact-list {:navigator nav}])
|
||||
|
|
|
@ -25,9 +25,12 @@
|
|||
(into {})))
|
||||
|
||||
(defn add-msg-color [{:keys [from] :as msg} contact-by-identity]
|
||||
(let [{:keys [text-color background-color]} (get contact-by-identity from)]
|
||||
(assoc msg :text-color text-color
|
||||
:background-color background-color)))
|
||||
(if (= "system" from)
|
||||
(assoc msg :text-color "#4A5258"
|
||||
:background-color "#D3EEEF")
|
||||
(let [{:keys [text-color background-color]} (get contact-by-identity from)]
|
||||
(assoc msg :text-color text-color
|
||||
:background-color background-color))))
|
||||
|
||||
(defn chat [{:keys [navigator]}]
|
||||
(let [messages (subscribe [:get-chat-messages])
|
||||
|
@ -42,18 +45,34 @@
|
|||
:backgroundColor "#eef2f5"}}
|
||||
(when android?
|
||||
;; TODO add IOS version
|
||||
[toolbar-android {:logo res/logo-icon
|
||||
:title (or (@chat :name)
|
||||
"Chat name")
|
||||
:titleColor "#4A5258"
|
||||
:subtitle "Last seen just now"
|
||||
:subtitleColor "#AAB2B2"
|
||||
:navIcon res/nav-back-icon
|
||||
:style {:backgroundColor "white"
|
||||
:height 56
|
||||
:elevation 2}
|
||||
:onIconClicked (fn []
|
||||
(nav-pop navigator))}])
|
||||
[toolbar-android {:logo res/logo-icon
|
||||
:title (or (@chat :name)
|
||||
"Chat name")
|
||||
:titleColor "#4A5258"
|
||||
:subtitle "Last seen just now"
|
||||
:subtitleColor "#AAB2B2"
|
||||
:navIcon res/nav-back-icon
|
||||
:style {:backgroundColor "white"
|
||||
:height 56
|
||||
:elevation 2}
|
||||
:actions (when (and (:group-chat @chat)
|
||||
(:is-active @chat))
|
||||
[{:title "Add Contact to chat"
|
||||
:icon res/add-icon
|
||||
:showWithText true}
|
||||
{:title "Remove Contact from chat"
|
||||
:icon res/trash-icon
|
||||
:showWithText true}
|
||||
{:title "Leave Chat"
|
||||
:icon res/leave-icon
|
||||
:showWithText true}])
|
||||
:onActionSelected (fn [position]
|
||||
(case position
|
||||
0 (dispatch [:show-add-participants navigator])
|
||||
1 (dispatch [:show-remove-participants navigator])
|
||||
2 (dispatch [:leave-group-chat navigator])))
|
||||
:onIconClicked (fn []
|
||||
(nav-pop navigator))}])
|
||||
[list-view {:dataSource datasource
|
||||
:renderScrollComponent (fn [props]
|
||||
(invertible-scroll-view nil))
|
||||
|
@ -62,4 +81,5 @@
|
|||
(add-msg-color contact-by-identity))]
|
||||
(r/as-element [chat-message msg])))
|
||||
:style {:backgroundColor "white"}}]
|
||||
[chat-message-new]]))))
|
||||
(when (:is-active @chat)
|
||||
[chat-message-new])]))))
|
||||
|
|
|
@ -86,28 +86,27 @@
|
|||
content)]]))
|
||||
|
||||
(defn message-content [{:keys [content-type content outgoing text-color background-color]}]
|
||||
(let [_ (log/debug color)]
|
||||
[view {:style (merge {:borderRadius 6}
|
||||
(if (= content-type text-content-type)
|
||||
{:paddingVertical 12
|
||||
:paddingHorizontal 16}
|
||||
{:paddingVertical 14
|
||||
:paddingHorizontal 10})
|
||||
(if outgoing
|
||||
{:backgroundColor "#D3EEEF"}
|
||||
{:backgroundColor background-color}))}
|
||||
(cond
|
||||
(= content-type text-content-type)
|
||||
[text {:style (merge {:fontSize 14
|
||||
:fontFamily "Avenir-Roman"}
|
||||
(if outgoing
|
||||
{:color "#4A5258"}
|
||||
{:color text-color}))}
|
||||
content]
|
||||
(= content-type content-type-command)
|
||||
[message-content-command content]
|
||||
:else [message-content-audio {:content content
|
||||
:content-type content-type}])]))
|
||||
[view {:style (merge {:borderRadius 6}
|
||||
(if (= content-type text-content-type)
|
||||
{:paddingVertical 12
|
||||
:paddingHorizontal 16}
|
||||
{:paddingVertical 14
|
||||
:paddingHorizontal 10})
|
||||
(if outgoing
|
||||
{:backgroundColor "#D3EEEF"}
|
||||
{:backgroundColor background-color}))}
|
||||
(cond
|
||||
(= content-type text-content-type)
|
||||
[text {:style (merge {:fontSize 14
|
||||
:fontFamily "Avenir-Roman"}
|
||||
(if outgoing
|
||||
{:color "#4A5258"}
|
||||
{:color text-color}))}
|
||||
content]
|
||||
(= content-type content-type-command)
|
||||
[message-content-command content]
|
||||
:else [message-content-audio {:content content
|
||||
:content-type content-type}])])
|
||||
|
||||
(defn message-delivery-status [{:keys [delivery-status]}]
|
||||
[view {:style {:flexDirection "row"
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
(ns syng-im.components.chat.new-participants
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.resources :as res]
|
||||
[syng-im.components.react :refer [view toolbar-android android? text-input]]
|
||||
[syng-im.components.realm :refer [list-view]]
|
||||
[syng-im.utils.listview :refer [to-realm-datasource]]
|
||||
[syng-im.components.chats.new-participant-contact :refer [new-participant-contact]]
|
||||
[reagent.core :as r]
|
||||
[syng-im.navigation :refer [nav-pop]]))
|
||||
|
||||
(defn new-participants [{:keys [navigator]}]
|
||||
(let [contacts (subscribe [:all-new-contacts])]
|
||||
(fn []
|
||||
(let [contacts-ds (to-realm-datasource @contacts)]
|
||||
[view {:style {:flex 1
|
||||
:backgroundColor "white"}}
|
||||
(when android?
|
||||
;; TODO add IOS version
|
||||
[toolbar-android {:logo res/logo-icon
|
||||
:title "Add Participants"
|
||||
:titleColor "#4A5258"
|
||||
:style {:backgroundColor "white"
|
||||
:height 56
|
||||
:elevation 2}
|
||||
:actions [{:title "Add"
|
||||
:icon res/v
|
||||
:show "always"}]
|
||||
:onActionSelected (fn [position]
|
||||
(dispatch [:add-new-participants navigator]))
|
||||
:navIcon res/nav-back-icon
|
||||
:onIconClicked (fn []
|
||||
(nav-pop navigator))}])
|
||||
[list-view {:dataSource contacts-ds
|
||||
:renderRow (fn [row section-id row-id]
|
||||
(r/as-element [new-participant-contact (js->clj row :keywordize-keys true) navigator]))
|
||||
:style {:backgroundColor "white"}}]]))))
|
|
@ -0,0 +1,36 @@
|
|||
(ns syng-im.components.chat.remove-participants
|
||||
(:require [re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.resources :as res]
|
||||
[syng-im.components.react :refer [view toolbar-android android? text-input]]
|
||||
[syng-im.components.realm :refer [list-view]]
|
||||
[syng-im.utils.listview :refer [to-realm-datasource]]
|
||||
[syng-im.components.chats.new-participant-contact :refer [new-participant-contact]]
|
||||
[reagent.core :as r]
|
||||
[syng-im.navigation :refer [nav-pop]]))
|
||||
|
||||
(defn remove-participants [{:keys [navigator]}]
|
||||
(let [contacts (subscribe [:current-chat-contacts])]
|
||||
(fn []
|
||||
(let [contacts-ds (to-realm-datasource @contacts)]
|
||||
[view {:style {:flex 1
|
||||
:backgroundColor "white"}}
|
||||
(when android?
|
||||
;; TODO add IOS version
|
||||
[toolbar-android {:logo res/logo-icon
|
||||
:title "Remove Participants"
|
||||
:titleColor "#4A5258"
|
||||
:style {:backgroundColor "white"
|
||||
:height 56
|
||||
:elevation 2}
|
||||
:actions [{:title "Remove"
|
||||
:icon res/trash-icon
|
||||
:show "always"}]
|
||||
:onActionSelected (fn [position]
|
||||
(dispatch [:remove-selected-participants navigator]))
|
||||
:navIcon res/nav-back-icon
|
||||
:onIconClicked (fn []
|
||||
(nav-pop navigator))}])
|
||||
[list-view {:dataSource contacts-ds
|
||||
:renderRow (fn [row section-id row-id]
|
||||
(r/as-element [new-participant-contact (js->clj row :keywordize-keys true) navigator]))
|
||||
:style {:backgroundColor "white"}}]]))))
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
(defn chat-list-item [chat-obj navigator]
|
||||
[touchable-highlight {:on-press (fn []
|
||||
(dispatch [:show-chat (aget chat-obj "chat-id") navigator]))}
|
||||
(dispatch [:show-chat (aget chat-obj "chat-id") navigator :push]))}
|
||||
[view {:style {:flexDirection "row"
|
||||
:width 260
|
||||
:marginVertical 5}}
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
(ns syng-im.components.chats.new-participant-contact
|
||||
(:require [syng-im.resources :as res]
|
||||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.components.react :refer [view]]
|
||||
[syng-im.components.contact-list.contact-inner :refer [contact-inner-view]]
|
||||
[syng-im.components.item-checkbox :refer [item-checkbox]]
|
||||
[syng-im.utils.logging :as log]
|
||||
[reagent.core :as r]))
|
||||
|
||||
(defn new-participant-contact [{:keys [whisper-identity] :as contact} navigator]
|
||||
(let [checked (r/atom false)]
|
||||
(fn []
|
||||
[view {:style {:flexDirection "row"
|
||||
:marginTop 5
|
||||
:marginBottom 5
|
||||
:paddingLeft 15
|
||||
:paddingRight 15
|
||||
:height 75}}
|
||||
[item-checkbox {:onToggle (fn [checked?]
|
||||
(reset! checked checked?)
|
||||
(dispatch [:select-new-participant whisper-identity checked?]))
|
||||
:checked @checked
|
||||
:size 30}]
|
||||
[contact-inner-view contact]])))
|
|
@ -9,10 +9,11 @@
|
|||
:identity-password "replace-me-with-user-entered-password"
|
||||
:contacts []
|
||||
:chat {:current-chat-id "0x0479a5ed1f38cadfad1db6cd56c4b659b0ebe052bbe9efa950f6660058519fa4ca6be2dda66afa80de96ab00eb97a2605d5267a1e8f4c2a166ab551f6826608cdd"
|
||||
:command nil}
|
||||
:command nil}
|
||||
:chats {}
|
||||
:chats-updated-signal 0
|
||||
:new-group #{}})
|
||||
:new-group #{}
|
||||
:new-participants #{}})
|
||||
|
||||
|
||||
(def protocol-initialized-path [:protocol-initialized])
|
||||
|
@ -28,3 +29,4 @@
|
|||
(defn chat-command-content-path [chat-id]
|
||||
[:chats chat-id :command-input :content])
|
||||
(def new-group-path [:new-group])
|
||||
(def new-participants-path [:new-participants])
|
||||
|
|
|
@ -18,18 +18,28 @@
|
|||
set-chat-command-content]]
|
||||
[syng-im.handlers.sign-up :as sign-up-service]
|
||||
|
||||
[syng-im.models.chats :refer [create-chat]]
|
||||
[syng-im.models.chats :refer [create-chat
|
||||
chat-add-participants
|
||||
chat-remove-participants
|
||||
set-chat-active]]
|
||||
[syng-im.models.chat :refer [signal-chat-updated
|
||||
set-current-chat-id
|
||||
current-chat-id
|
||||
update-new-group-selection
|
||||
update-new-participants-selection
|
||||
clear-new-group
|
||||
clear-new-participants
|
||||
new-group-selection
|
||||
set-chat-input-text]]
|
||||
set-chat-input-text
|
||||
new-participants-selection]]
|
||||
[syng-im.utils.logging :as log]
|
||||
[syng-im.protocol.api :as api]
|
||||
[syng-im.constants :refer [text-content-type]]
|
||||
[syng-im.navigation :refer [nav-push]]
|
||||
[syng-im.utils.crypt :refer [gen-random-bytes]]))
|
||||
[syng-im.navigation :refer [nav-push
|
||||
nav-replace
|
||||
nav-pop]]
|
||||
[syng-im.utils.crypt :refer [gen-random-bytes]]
|
||||
[syng-im.utils.random :as random]))
|
||||
|
||||
;; -- Middleware ------------------------------------------------------------
|
||||
;;
|
||||
|
@ -77,9 +87,11 @@
|
|||
db))
|
||||
|
||||
(register-handler :navigate-to
|
||||
(fn [db [action navigator route]]
|
||||
(fn [db [action navigator route nav-type]]
|
||||
(log/debug action route)
|
||||
(nav-push navigator route)
|
||||
(case nav-type
|
||||
:push (nav-push navigator route)
|
||||
:replace (nav-replace navigator route))
|
||||
db))
|
||||
|
||||
;; -- Protocol --------------------------------------------------------------
|
||||
|
@ -110,14 +122,98 @@
|
|||
(save-message chat-id msg)
|
||||
(signal-chat-updated db chat-id)))
|
||||
|
||||
(defn joined-chat-msg [chat-id from msg-id]
|
||||
(let [contact-name (:name (contacts/contact-by-identity from))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id msg-id
|
||||
:content (str (or contact-name from) " received chat invitation")
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn participant-invited-to-group-msg [chat-id identity from msg-id]
|
||||
(let [inviter-name (:name (contacts/contact-by-identity from))
|
||||
invitee-name (:name (contacts/contact-by-identity identity))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id msg-id
|
||||
:content (str (or inviter-name from) " invited " (or invitee-name identity))
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn participant-removed-from-group-msg [chat-id identity from msg-id]
|
||||
(let [remover-name (:name (contacts/contact-by-identity from))
|
||||
removed-name (:name (contacts/contact-by-identity identity))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id msg-id
|
||||
:content (str (or remover-name from) " removed " (or removed-name identity))
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn you-removed-from-group-msg [chat-id from msg-id]
|
||||
(let [remover-name (:name (contacts/contact-by-identity from))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id msg-id
|
||||
:content (str (or remover-name from) " removed you from group chat")
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn participant-left-group-msg [chat-id from msg-id]
|
||||
(let [left-name (:name (contacts/contact-by-identity from))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id msg-id
|
||||
:content (str (or left-name from) " left")
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn removed-participant-msg [chat-id identity]
|
||||
(let [contact-name (:name (contacts/contact-by-identity identity))]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id (random/id)
|
||||
:content (str "You've removed " (or contact-name identity))
|
||||
:content-type text-content-type})))
|
||||
|
||||
(defn left-chat-msg [chat-id]
|
||||
(save-message chat-id {:from "system"
|
||||
:msg-id (random/id)
|
||||
:content "You left this chat"
|
||||
:content-type text-content-type}))
|
||||
|
||||
(register-handler :group-chat-invite-acked
|
||||
(fn [db [action from group-id ack-msg-id]]
|
||||
(log/debug action from group-id ack-msg-id)
|
||||
(joined-chat-msg group-id from ack-msg-id)
|
||||
(signal-chat-updated db group-id)))
|
||||
|
||||
(register-handler :participant-removed-from-group
|
||||
(fn [db [action from group-id identity msg-id]]
|
||||
(log/debug action msg-id from group-id identity)
|
||||
(chat-remove-participants group-id [identity])
|
||||
(participant-removed-from-group-msg group-id identity from msg-id)
|
||||
(signal-chat-updated db group-id)))
|
||||
|
||||
(register-handler :you-removed-from-group
|
||||
(fn [db [action from group-id msg-id]]
|
||||
(log/debug action msg-id from group-id)
|
||||
(you-removed-from-group-msg group-id from msg-id)
|
||||
(set-chat-active group-id false)
|
||||
(signal-chat-updated db group-id)))
|
||||
|
||||
(register-handler :participant-left-group
|
||||
(fn [db [action from group-id msg-id]]
|
||||
(log/debug action msg-id from group-id)
|
||||
(participant-left-group-msg group-id from msg-id)
|
||||
(signal-chat-updated db group-id)))
|
||||
|
||||
(register-handler :participant-invited-to-group
|
||||
(fn [db [action from group-id identity msg-id]]
|
||||
(log/debug action msg-id from group-id identity)
|
||||
(participant-invited-to-group-msg group-id identity from msg-id)
|
||||
(signal-chat-updated db group-id)))
|
||||
|
||||
(register-handler :acked-msg
|
||||
(fn [db [_ from msg-id]]
|
||||
(fn [db [action from msg-id]]
|
||||
(log/debug action from msg-id)
|
||||
(update-message! {:msg-id msg-id
|
||||
:delivery-status :delivered})
|
||||
(signal-chat-updated db from)))
|
||||
|
||||
(register-handler :msg-delivery-failed
|
||||
(fn [db [_ msg-id]]
|
||||
(fn [db [action msg-id]]
|
||||
(log/debug action msg-id)
|
||||
(update-message! {:msg-id msg-id
|
||||
:delivery-status :failed})
|
||||
(let [{:keys [chat-id]} (message-by-id msg-id)]
|
||||
|
@ -128,7 +224,7 @@
|
|||
(log/debug action "chat-id" chat-id "text" text)
|
||||
(let [msg (if (= chat-id "console")
|
||||
(sign-up-service/send-console-msg text)
|
||||
(let [{msg-id :msg-id
|
||||
(let [{msg-id :msg-id
|
||||
{from :from
|
||||
to :to} :msg} (api/send-user-msg {:to chat-id
|
||||
:content text})]
|
||||
|
@ -141,13 +237,22 @@
|
|||
(save-message chat-id msg)
|
||||
(signal-chat-updated db chat-id))))
|
||||
|
||||
(register-handler :leave-group-chat
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
(let [chat-id (current-chat-id db)]
|
||||
(api/leave-group-chat chat-id)
|
||||
(set-chat-active chat-id false)
|
||||
(left-chat-msg chat-id)
|
||||
(signal-chat-updated db chat-id))))
|
||||
|
||||
(register-handler :send-chat-command
|
||||
(fn [db [action chat-id command content]]
|
||||
(log/debug action "chat-id" chat-id "command" command "content" content)
|
||||
(let [msg (if (= chat-id "console")
|
||||
(sign-up-service/send-console-command command content)
|
||||
;; TODO handle command, now sends as plain message
|
||||
(let [{msg-id :msg-id
|
||||
(let [{msg-id :msg-id
|
||||
{from :from
|
||||
to :to} :msg} (api/send-user-msg {:to chat-id
|
||||
:content content})]
|
||||
|
@ -216,10 +321,10 @@
|
|||
;; -- Chats --------------------------------------------------------------
|
||||
|
||||
(register-handler :show-chat
|
||||
(fn [db [action chat-id navigator]]
|
||||
(fn [db [action chat-id navigator nav-type]]
|
||||
(log/debug action "chat-id" chat-id)
|
||||
(let [db (set-current-chat-id db chat-id)]
|
||||
(dispatch [:navigate-to navigator {:view-id :chat}])
|
||||
(dispatch [:navigate-to navigator {:view-id :chat} nav-type])
|
||||
db)))
|
||||
|
||||
(register-handler :set-sign-up-chat
|
||||
|
@ -248,6 +353,48 @@
|
|||
(nav-push navigator {:view-id :contact-list})
|
||||
db))
|
||||
|
||||
(register-handler :select-new-participant
|
||||
(fn [db [action identity add?]]
|
||||
(log/debug action identity add?)
|
||||
(update-new-participants-selection db identity add?)))
|
||||
|
||||
(register-handler :show-remove-participants
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
(nav-push navigator {:view-id :remove-participants})
|
||||
(clear-new-participants db)))
|
||||
|
||||
(register-handler :remove-selected-participants
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
(let [identities (-> (new-participants-selection db)
|
||||
(vec))
|
||||
chat-id (current-chat-id db)]
|
||||
(chat-remove-participants chat-id identities)
|
||||
(nav-pop navigator)
|
||||
(doseq [ident identities]
|
||||
(api/group-remove-participant chat-id ident)
|
||||
(removed-participant-msg chat-id ident))
|
||||
(signal-chat-updated db chat-id))))
|
||||
|
||||
(register-handler :show-add-participants
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
(nav-push navigator {:view-id :add-participants})
|
||||
(clear-new-participants db)))
|
||||
|
||||
(register-handler :add-new-participants
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
(let [identities (-> (new-participants-selection db)
|
||||
(vec))
|
||||
chat-id (current-chat-id db)]
|
||||
(chat-add-participants chat-id identities)
|
||||
(nav-pop navigator)
|
||||
(doseq [ident identities]
|
||||
(api/group-add-participant chat-id ident))
|
||||
db)))
|
||||
|
||||
(register-handler :show-group-new
|
||||
(fn [db [action navigator]]
|
||||
(log/debug action)
|
||||
|
@ -266,7 +413,7 @@
|
|||
(vec))
|
||||
group-id (api/start-group-chat identities group-name)
|
||||
db (create-chat db group-id identities true group-name)]
|
||||
(dispatch [:show-chat group-id navigator])
|
||||
(dispatch [:show-chat group-id navigator :replace])
|
||||
db)))
|
||||
|
||||
(register-handler :group-chat-invite-received
|
||||
|
|
|
@ -19,9 +19,15 @@
|
|||
|
||||
(defn update-new-group-selection [db identity add?]
|
||||
(update-in db db/new-group-path (fn [new-group]
|
||||
(if add?
|
||||
(conj new-group identity)
|
||||
(disj new-group identity)))))
|
||||
(if add?
|
||||
(conj new-group identity)
|
||||
(disj new-group identity)))))
|
||||
|
||||
(defn update-new-participants-selection [db identity add?]
|
||||
(update-in db db/new-participants-path (fn [new-participants]
|
||||
(if add?
|
||||
(conj new-participants identity)
|
||||
(disj new-participants identity)))))
|
||||
|
||||
(defn new-group-selection [db]
|
||||
(get-in db db/new-group-path))
|
||||
|
@ -29,6 +35,12 @@
|
|||
(defn clear-new-group [db]
|
||||
(assoc-in db db/new-group-path #{}))
|
||||
|
||||
(defn new-participants-selection [db]
|
||||
(get-in db db/new-participants-path))
|
||||
|
||||
(defn clear-new-participants [db]
|
||||
(assoc-in db db/new-participants-path #{}))
|
||||
|
||||
(defn set-chat-input-text [db text]
|
||||
(assoc-in db (db/chat-input-text-path (current-chat-id db)) text))
|
||||
|
||||
|
@ -37,5 +49,5 @@
|
|||
(swap! re-frame.db/app-db (fn [db]
|
||||
(signal-chat-updated db "0x0479a5ed1f38cadfad1db6cd56c4b659b0ebe052bbe9efa950f6660058519fa4ca6be2dda66afa80de96ab00eb97a2605d5267a1e8f4c2a166ab551f6826608cdd")))
|
||||
|
||||
(current-chat-id @re-frame.db/app-db)
|
||||
(current-chat-id @re-frame.db/app-db)
|
||||
)
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
[clojure.string :refer [join blank?]]
|
||||
[syng-im.db :as db]
|
||||
[syng-im.utils.logging :as log]
|
||||
[syng-im.constants :refer [group-chat-colors]]))
|
||||
[syng-im.constants :refer [group-chat-colors]]
|
||||
[syng-im.persistence.realm-queries :refer [include-query]]))
|
||||
|
||||
(defn signal-chats-updated [db]
|
||||
(update-in db db/updated-chats-signal-path (fn [current]
|
||||
|
@ -46,6 +47,7 @@
|
|||
:background-color background
|
||||
:text-color text}) identities group-chat-colors)]
|
||||
(r/create :chats {:chat-id chat-id
|
||||
:is-active true
|
||||
:name chat-name
|
||||
:group-chat group-chat?
|
||||
:timestamp (timestamp)
|
||||
|
@ -61,8 +63,52 @@
|
|||
(r/single-cljs)
|
||||
(r/list-to-array :contacts)))
|
||||
|
||||
(comment
|
||||
(defn chat-add-participants [chat-id identities]
|
||||
(r/write
|
||||
(fn []
|
||||
(let [contacts (-> (r/get-by-field :chats :chat-id chat-id)
|
||||
(r/single)
|
||||
(aget "contacts"))
|
||||
colors-in-use (->> (.map contacts (fn [object index collection]
|
||||
{:text-color (aget object "text-color")
|
||||
:background-color (aget object "background-color")}))
|
||||
(set))
|
||||
colors (->> group-chat-colors
|
||||
(filter (fn [color]
|
||||
(not (contains? colors-in-use color)))))
|
||||
new-contacts (mapv (fn [ident {:keys [background text]}]
|
||||
{:identity ident
|
||||
:background-color background
|
||||
:text-color text}) identities colors)]
|
||||
(doseq [contact new-contacts]
|
||||
(.push contacts (clj->js contact)))))))
|
||||
|
||||
(defn chat-remove-participants [chat-id identities]
|
||||
(r/write
|
||||
(fn []
|
||||
(let [query (include-query :identity identities)
|
||||
chat (-> (r/get-by-field :chats :chat-id chat-id)
|
||||
(r/single))]
|
||||
(-> (aget chat "contacts")
|
||||
(r/filtered query)
|
||||
(r/delete))))))
|
||||
|
||||
(defn active-group-chats []
|
||||
(let [results (-> (r/get-all :chats)
|
||||
(r/filtered "group-chat = true && is-active = true"))]
|
||||
(->> (.map results (fn [object index collection]
|
||||
(aget object "chat-id")))
|
||||
(js->clj))))
|
||||
|
||||
|
||||
(defn set-chat-active [chat-id active?]
|
||||
(r/write (fn []
|
||||
(-> (r/get-by-field :chats :chat-id chat-id)
|
||||
(r/single)
|
||||
(aset "is-active" active?)))))
|
||||
|
||||
(comment
|
||||
(active-group-chats)
|
||||
|
||||
|
||||
(-> (r/get-by-field :chats :chat-id "0x04ed4c3797026cddeb7d64a54ca58142e57ea03cda21072358d67455b506db90c56d95033e3d221992f70d01922c3d90bf0697c49e4be118443d03ae4a1cd3c15c")
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
[re-frame.core :refer [subscribe dispatch dispatch-sync]]
|
||||
[syng-im.utils.utils :refer [log toast]]
|
||||
[syng-im.persistence.realm :as realm]
|
||||
[syng-im.persistence.realm :as r]))
|
||||
[syng-im.persistence.realm :as r]
|
||||
[syng-im.persistence.realm-queries :refer [include-query
|
||||
exclude-query]]
|
||||
[clojure.string :as s]))
|
||||
|
||||
;; TODO see https://github.com/rt2zz/react-native-contacts/issues/45
|
||||
(def fake-phone-contacts? true)
|
||||
|
@ -91,18 +94,44 @@
|
|||
(-> (r/get-all :contacts)
|
||||
(r/sorted :name :asc)))
|
||||
|
||||
(defn contacts-list-exclude [exclude-idents]
|
||||
(let [query (exclude-query :whisper-identity exclude-idents)]
|
||||
(-> (r/get-all :contacts)
|
||||
(r/filtered query)
|
||||
(r/sorted :name :asc))))
|
||||
|
||||
(defn contacts-list-include [include-indents]
|
||||
(let [query (include-query :whisper-identity include-indents)]
|
||||
(-> (r/get-all :contacts)
|
||||
(r/filtered query)
|
||||
(r/sorted :name :asc))))
|
||||
|
||||
(defn contact-by-identity [identity]
|
||||
(-> (r/get-by-field :contacts :whisper-identity identity)
|
||||
(r/single-cljs)))
|
||||
|
||||
(comment
|
||||
|
||||
(r/write #(create-contact {:phone-number "0543072333"
|
||||
:whisper-identity "0x04ed4c3797026cddeb7d64a54ca58142e57ea03cda21072358d67455b506db90c56d95033e3d221992f70d01922c3d90bf0697c49e4be118443d03ae4a1cd3c15c"
|
||||
:whisper-identity "0x043e3a8344049fb48fef030084212a9d41577a5dea18aeb4c8f285c16f783aa84e43f84c32eb8601e22827b12d5f93f14e545f9023034a0521dc18484bbbc44704"
|
||||
:name "Mr. Bean"
|
||||
:photo-path ""}))
|
||||
|
||||
(r/write #(create-contact {:phone-number "0544828649"
|
||||
:whisper-identity "0x0498bcce41dbe05c6d4776ef50d12c2ef1a00d9d7f7144d174ece3dce85ca3428bf0900352abcccdc463bd2cfa4ec319cda46c2079152c4cb14d1cad9a00dd7571"
|
||||
:whisper-identity "0x04e9b01298dd12c4d8f0393d7890302b25762966d825158d1fdffe124703c0efcd7f23a6cf71c466ca50b2af3d54264ea5f224a19ba7775779c1ddbcb237258c5c"
|
||||
:name "Mr. Batman"
|
||||
:photo-path ""}))
|
||||
|
||||
(r/write #(create-contact {:phone-number "0522222222"
|
||||
:whisper-identity "0x0487954e7fa746d8cf787403c2c491aadad540b9bb1f0f7b8184792e91c33b6a394079295f5777ec6d4af9ad5ba24794b3ff1ec8be9ff6a708c85a163733192665"
|
||||
:name "Mr. Eagle"
|
||||
:photo-path ""}))
|
||||
|
||||
(r/write #(create-contact {:phone-number "0533333333"
|
||||
:whisper-identity "0x04e43e861a6dd99ad9eee7bd58af89dcaa430188ebec8698de7b7bad54573324fff4ac5cb9bb277af317efd7abfc917b91bf48cc41e40bf70062fd79400016a1f9"
|
||||
:name "Mr. PiggyBear"
|
||||
:photo-path ""}))
|
||||
|
||||
(contacts-list)
|
||||
|
||||
(:new-group @re-frame.db/app-db)
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
(defn save-message [chat-id {:keys [from to msg-id content content-type outgoing] :or {outgoing false
|
||||
to nil} :as msg}]
|
||||
(log/debug "save-message" chat-id msg)
|
||||
(when-not (r/exists? :msgs :msg-id msg-id)
|
||||
(r/write
|
||||
(fn []
|
||||
|
@ -28,10 +29,12 @@
|
|||
(-> (r/get-by-field :msgs :msg-id msg-id)
|
||||
(r/single-cljs)))
|
||||
|
||||
(defn update-message! [msg]
|
||||
(defn update-message! [{:keys [msg-id] :as msg}]
|
||||
(log/debug "update-message!" msg)
|
||||
(r/write
|
||||
(fn []
|
||||
(r/create :msgs msg true))))
|
||||
(when (r/exists? :msgs :msg-id msg-id)
|
||||
(r/create :msgs msg true)))))
|
||||
|
||||
(comment
|
||||
|
||||
|
|
|
@ -41,7 +41,9 @@
|
|||
:primaryKey :chat-id
|
||||
:properties {:chat-id "string"
|
||||
:name "string"
|
||||
:group-chat "bool"
|
||||
:group-chat {:type "bool"
|
||||
:indexed true}
|
||||
:is-active "bool"
|
||||
:timestamp "int"
|
||||
:contacts {:type "list"
|
||||
:objectType "chat-contact"}}}]})
|
||||
|
@ -92,6 +94,9 @@
|
|||
false
|
||||
true)))
|
||||
|
||||
(defn filtered [results filter-query]
|
||||
(.filtered results filter-query))
|
||||
|
||||
(defn page [results from to]
|
||||
(js/Array.prototype.slice.call results from to))
|
||||
|
||||
|
@ -111,8 +116,7 @@
|
|||
(read-string value))
|
||||
|
||||
(defn delete [obj]
|
||||
(write (fn []
|
||||
(.delete realm obj))))
|
||||
(.delete realm obj))
|
||||
|
||||
(defn exists? [schema-name field value]
|
||||
(> (.-length (get-by-field schema-name field value))
|
||||
|
@ -127,22 +131,4 @@
|
|||
|
||||
(comment
|
||||
|
||||
(write #(.create realm "msgs" (clj->js {:msg-id "12"
|
||||
:content "sdfd"
|
||||
:from "sdfsd"
|
||||
:chat-id "56"
|
||||
:content-type "fg"
|
||||
:timestamp 2
|
||||
:outgoing true
|
||||
:to "sfs"
|
||||
:delivery-status "seen"}) true))
|
||||
|
||||
(.addListener realm "change" (fn [& args]
|
||||
(log/debug args)))
|
||||
|
||||
;realm.addListener('change', () => {
|
||||
; // Update UI
|
||||
; ...
|
||||
; });
|
||||
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
(ns syng-im.persistence.realm-queries
|
||||
(:require [clojure.string :as s]
|
||||
[syng-im.utils.types :refer [to-string]]))
|
||||
|
||||
(defn include-query [field-name values]
|
||||
(->> values
|
||||
(map (fn [val]
|
||||
(str (to-string field-name) " == " (if (string? val)
|
||||
(str "'" val "'")
|
||||
val))))
|
||||
(s/join " || ")))
|
||||
|
||||
(defn exclude-query [field-name values]
|
||||
(->> values
|
||||
(map (fn [val]
|
||||
(str (to-string field-name) " != " (if (string? val)
|
||||
(str "'" val "'")
|
||||
val))))
|
||||
(s/join " && ")))
|
|
@ -17,8 +17,9 @@
|
|||
(contains-key? [_ key]
|
||||
(r/exists? :kv-store :key key))
|
||||
(delete [_ key]
|
||||
(-> (r/get-by-field :kv-store :key key)
|
||||
(r/single)
|
||||
(r/delete))))
|
||||
(r/write (fn []
|
||||
(-> (r/get-by-field :kv-store :key key)
|
||||
(r/single)
|
||||
(r/delete))))))
|
||||
|
||||
(def kv-store (->SimpleKvStore))
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
[syng-im.constants :refer [ethereum-rpc-url]]
|
||||
[re-frame.core :refer [dispatch]]
|
||||
[syng-im.models.protocol :refer [stored-identity]]
|
||||
[syng-im.persistence.simple-kv-store :as kv]))
|
||||
[syng-im.persistence.simple-kv-store :as kv]
|
||||
[syng-im.models.chats :refer [active-group-chats]]))
|
||||
|
||||
|
||||
(defn make-handler [db]
|
||||
{:ethereum-rpc-url ethereum-rpc-url
|
||||
:identity (stored-identity db)
|
||||
:active-group-ids (active-group-chats)
|
||||
:storage kv/kv-store
|
||||
:handler (fn [{:keys [event-type] :as event}]
|
||||
(log/info "Event:" (clj->js event))
|
||||
|
@ -28,18 +30,14 @@
|
|||
payload :payload} event]
|
||||
(dispatch [:group-received-msg (assoc payload :from from
|
||||
:group-id group-id)]))
|
||||
;:group-chat-invite-acked (let [{:keys [from group-id]} event]
|
||||
; (add-to-chat "group-chat" ":" (str "Received ACK for group chat invitation from " from " for group-id: " group-id)))
|
||||
;:group-new-participant (let [{:keys [group-id identity from]} event]
|
||||
; (add-to-chat "group-chat" ":" (str (shorten from) " added " (shorten identity) " to group chat"))
|
||||
; (add-identity-to-group-list identity))
|
||||
;:group-removed-participant (let [{:keys [group-id identity from]} event]
|
||||
; (add-to-chat "group-chat" ":" (str (shorten from) " removed " (shorten identity) " from group chat"))
|
||||
; (remove-identity-from-group-list identity))
|
||||
;:removed-from-group (let [{:keys [group-id from]} event]
|
||||
; (add-to-chat "group-chat" ":" (str (shorten from) " removed you from group chat")))
|
||||
;:participant-left-group (let [{:keys [group-id from]} event]
|
||||
; (add-to-chat "group-chat" ":" (str (shorten from) " left group chat")))
|
||||
;(add-to-chat "chat" ":" (str "Don't know how to handle " event-type))
|
||||
(log/info "Don't know how to handle" event-type)
|
||||
))})
|
||||
:group-chat-invite-acked (let [{:keys [from group-id ack-msg-id]} event]
|
||||
(dispatch [:group-chat-invite-acked from group-id ack-msg-id]))
|
||||
:group-new-participant (let [{:keys [group-id identity from msg-id]} event]
|
||||
(dispatch [:participant-invited-to-group from group-id identity msg-id]))
|
||||
:group-removed-participant (let [{:keys [group-id identity from msg-id]} event]
|
||||
(dispatch [:participant-removed-from-group from group-id identity msg-id]))
|
||||
:removed-from-group (let [{:keys [group-id from msg-id]} event]
|
||||
(dispatch [:you-removed-from-group from group-id msg-id]))
|
||||
:participant-left-group (let [{:keys [group-id from msg-id]} event]
|
||||
(dispatch [:participant-left-group from group-id msg-id]))
|
||||
(log/info "Don't know how to handle" event-type)))})
|
||||
|
|
|
@ -13,3 +13,6 @@
|
|||
(def smile (js/require "./images/smile.png"))
|
||||
(def att (js/require "./images/att.png"))
|
||||
(def v (js/require "./images/v.png"))
|
||||
(def add-icon (js/require "./images/add.png"))
|
||||
(def trash-icon (js/require "./images/trash.png"))
|
||||
(def leave-icon (js/require "./images/leave.png"))
|
||||
|
|
|
@ -8,7 +8,9 @@
|
|||
chats-updated?
|
||||
chat-by-id]]
|
||||
[syng-im.models.messages :refer [get-messages]]
|
||||
[syng-im.models.contacts :refer [contacts-list]]
|
||||
[syng-im.models.contacts :refer [contacts-list
|
||||
contacts-list-exclude
|
||||
contacts-list-include]]
|
||||
[syng-im.handlers.suggestions :refer [get-suggestions]]))
|
||||
|
||||
;; -- Chat --------------------------------------------------------------
|
||||
|
@ -58,10 +60,13 @@
|
|||
(register-sub :get-current-chat
|
||||
(fn [db _]
|
||||
(let [current-chat-id (-> (current-chat-id @db)
|
||||
(reaction))
|
||||
chat-updated (-> (chat-updated? @db @current-chat-id)
|
||||
(reaction))]
|
||||
(-> (when-let [chat-id @current-chat-id]
|
||||
(chat-by-id chat-id))
|
||||
(reaction)))))
|
||||
(reaction
|
||||
(let [_ @chat-updated]
|
||||
(when-let [chat-id @current-chat-id]
|
||||
(chat-by-id chat-id)))))))
|
||||
|
||||
;; -- User data --------------------------------------------------------------
|
||||
|
||||
|
@ -99,3 +104,31 @@
|
|||
(fn [db _]
|
||||
(reaction
|
||||
(contacts-list))))
|
||||
|
||||
(register-sub :all-new-contacts
|
||||
(fn [db _]
|
||||
(let [current-chat-id (-> (current-chat-id @db)
|
||||
(reaction))
|
||||
chat (-> (when-let [chat-id @current-chat-id]
|
||||
(chat-by-id chat-id))
|
||||
(reaction))]
|
||||
(reaction
|
||||
(when @chat
|
||||
(let [current-participants (->> @chat
|
||||
:contacts
|
||||
(map :identity))]
|
||||
(contacts-list-exclude current-participants)))))))
|
||||
|
||||
(register-sub :current-chat-contacts
|
||||
(fn [db _]
|
||||
(let [current-chat-id (-> (current-chat-id @db)
|
||||
(reaction))
|
||||
chat (-> (when-let [chat-id @current-chat-id]
|
||||
(chat-by-id chat-id))
|
||||
(reaction))]
|
||||
(reaction
|
||||
(when @chat
|
||||
(let [current-participants (->> @chat
|
||||
:contacts
|
||||
(map :identity))]
|
||||
(contacts-list-include current-participants)))))))
|
||||
|
|
Loading…
Reference in New Issue