diff --git a/src/syng_im/chat/handlers.cljs b/src/syng_im/chat/handlers.cljs index 73f2a2ece6..e6371a55d5 100644 --- a/src/syng_im/chat/handlers.cljs +++ b/src/syng_im/chat/handlers.cljs @@ -11,7 +11,8 @@ [syng-im.chat.sign-up :as sign-up-service] [syng-im.models.chats :as chats] [syng-im.navigation.handlers :as nav] - [syng-im.utils.handlers :as u])) + [syng-im.utils.handlers :as u] + [syng-im.persistence.realm :as r])) (register-handler :set-show-actions (fn [db [_ show-actions]] @@ -325,3 +326,45 @@ (register-handler :switch-command-suggestions (fn [db [_]] (suggestions/switch-command-suggestions db))) + +(defn remove-chat + [{:keys [current-chat-id] :as db} _] + (update db :chats dissoc current-chat-id)) + +(defn notify-about-leaving! + [{:keys [current-chat-id]} _] + (api/leave-group-chat current-chat-id)) + +; todo do we really need this message? +(defn leaving-message! + [{:keys [current-chat-id]} _] + (messages/save-message + current-chat-id + {:from "system" + :msg-id (random/id) + :content "You left this chat" + :content-type text-content-type})) + +(defn delete-messages! + [{:keys [current-chat-id]} _] + (r/write + (fn [] + (r/delete (r/get-by-field :msgs :chat-id current-chat-id))))) + +(defn delete-chat! + [{:keys [current-chat-id]} _] + (r/write + (fn [] + (-> (r/get-by-field :chats :chat-id current-chat-id) + (r/single) + (r/delete))))) + +(register-handler :leave-group-chat + ;; todo oreder of operations tbd + (after (fn [_ _] (dispatch [:navigation-replace :chat-list]))) + (-> remove-chat + ;; todo uncomment + ;((after notify-about-leaving!)) + ;((after leaving-message!)) + ((after delete-messages!)) + ((after delete-chat!)))) diff --git a/src/syng_im/db.cljs b/src/syng_im/db.cljs index fa814e08a2..edab7d93b6 100644 --- a/src/syng_im/db.cljs +++ b/src/syng_im/db.cljs @@ -18,7 +18,7 @@ :chats {} :chats-updated-signal 0 :show-actions false - :new-participants #{} + :selected-participants #{} :signed-up true :view-id default-view :navigation-stack (list default-view) diff --git a/src/syng_im/group_settings/handlers.cljs b/src/syng_im/group_settings/handlers.cljs index 71247222ec..d2d64d62d6 100644 --- a/src/syng_im/group_settings/handlers.cljs +++ b/src/syng_im/group_settings/handlers.cljs @@ -1,7 +1,20 @@ (ns syng-im.group-settings.handlers - (:require [re-frame.core :refer [register-handler debug dispatch after]] + (:require [re-frame.core :refer [register-handler debug dispatch after + enrich]] [syng-im.persistence.realm :as r] - [syng-im.models.messages :refer [clear-history]])) + [syng-im.chat.handlers :refer [delete-messages!]] + [syng-im.protocol.api :as api] + [syng-im.utils.random :as random] + [syng-im.models.contacts :as contacts] + [syng-im.models.messages :as messages] + [syng-im.models.chats :as chats] + [syng-im.constants :refer [text-content-type]] + [syng-im.utils.handlers :as u] + [syng-im.navigation.handlers :as nav])) + +(defmethod nav/preload-data! :group-settings + [db _] + (assoc db :selected-participants #{})) (defn save-chat-property! [db-name property-name] @@ -18,15 +31,6 @@ (let [property (db-name db)] (assoc-in db [:chats current-chat-id property-name] property)))) -(defn delete-chat [chat-id] - (r/write - (fn [] - (-> (r/get-by-field :chats :chat-id chat-id) - (r/single) - (r/delete)))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats])) - (defn prepare-chat-settings [{:keys [current-chat-id] :as db} _] (let [{:keys [name color]} (-> db @@ -49,10 +53,92 @@ (after (save-chat-property! :new-chat-color :color)) (update-chat-property :new-chat-color :color)) +(defn clear-messages + [{:keys [current-chat-id] :as db} _] + (assoc-in db [:chats current-chat-id :messages] '())) + (register-handler :clear-history - (fn [db _] - (clear-history (:current-chat-id db)))) + (after delete-messages!) + clear-messages) (register-handler :group-settings (fn [db [_ k v]] (assoc-in db [:group-settings k] v))) + +(defn remove-identities [collection identities] + (remove #(identities (:identity %)) collection)) + +(defn remove-members + [{:keys [current-chat-id selected-participants] :as db} _] + (update-in db [:chats current-chat-id :contacts] + remove-identities selected-participants)) + +(defn remove-members-from-realm! + [{:keys [current-chat-id selected-participants] :as db} _] + (let [chat (get-in db [:chats current-chat-id])] + (r/write + (fn [] + (r/create + :chats + (update chat :contacts remove-identities selected-participants) + true))))) + +(defn notify-about-removing! + [{:keys [current-chat-id selected-participants]} _] + (doseq [participant selected-participants] + (api/group-remove-participant current-chat-id participant))) + +(defn system-message [msg-id content] + {:from "system" + :msg-id msg-id + :content content + :content-type text-content-type}) + +(defn removed-participant-msg [chat-id identity] + (let [contact-name (:name (contacts/contact-by-identity identity))] + (->> (str "You've removed " (or contact-name identity)) + (system-message (random/id)) + (messages/save-message chat-id)))) + +(defn create-removing-messages! + [{:keys [current-chat-id selected-participants]} _] + (doseq [participant selected-participants] + (removed-participant-msg current-chat-id participant))) + +(defn deselect-members [db _] + (assoc db :selected-participants #{})) + +(register-handler :remove-participants + ;; todo check if user have rights to add/remove participants + ;; todo order of operations tbd + (-> remove-members + ;; todo shouldn't this be done only after receiving of the "ack message" + ;; about the api call that removes participants from the group? + ((after remove-members-from-realm!)) + ;; todo uncomment + ;((after notify-about-removing!)) + ((after create-removing-messages!)) + ((enrich deselect-members)) + debug)) + +(defn add-memebers + [{:keys [current-chat-id selected-participants] :as db} _] + (let [new-identities (map #(hash-map :identity %) selected-participants)] + (update db [:chats current-chat-id :contacts] concat new-identities))) + +(defn add-members-to-realm! + [{:keys [current-chat-id selected-participants]} _] + (chats/chat-add-participants current-chat-id selected-participants)) + +(defn notify-about-new-members! + [{:keys [current-chat-id selected-participants]} _] + (doseq [identity selected-participants] + (api/group-add-participant current-chat-id identity))) + +(register-handler :add-new-participants + ;; todo order of operations tbd + (-> add-memebers + ((after add-members-to-realm!)) + ;; todo uncomment + ;((after notify-about-new-members!)) + ((enrich deselect-members)))) diff --git a/src/syng_im/group_settings/screen.cljs b/src/syng_im/group_settings/screen.cljs index 3debc05c29..d89022c7b4 100644 --- a/src/syng_im/group_settings/screen.cljs +++ b/src/syng_im/group_settings/screen.cljs @@ -16,25 +16,25 @@ [syng-im.group-settings.views.member :refer [member-view]] [clojure.string :as s])) -(defn remove-member [{:keys [whisper-identity]}] - (dispatch [:chat-remove-member whisper-identity])) +(defn remove-member [] + (dispatch [:remove-participants])) (defn close-member-menu [] - (dispatch [:set :group-settings-selected-member nil])) + (dispatch [:set :selected-participants #{}])) (defview member-menu [] - [member [:group-settings-selected-member]] - [modal {:animated false - :transparent false - :onRequestClose close-member-menu} - [touchable-highlight {:style st/modal-container - :on-press close-member-menu} - [view st/modal-inner-container - [text {:style st/modal-member-name} - (:name member)] - [touchable-highlight {:on-press #(remove-member member)} - [text {:style st/modal-remove-text} - "Remove"]]]]]) + [{:keys [name] :as participant} [:selected-participant]] + (when participant + [modal {:animated false + :transparent false + :onRequestClose close-member-menu} + [touchable-highlight {:style st/modal-container + :on-press close-member-menu} + [view st/modal-inner-container + [text {:style st/modal-member-name} name] + [touchable-highlight {:on-press remove-member} + [text {:style st/modal-remove-text} + "Remove"]]]]])) (defview chat-members [] [members [:current-chat-contacts]] @@ -42,9 +42,6 @@ (for [member members] ^{:key member} [member-view member])]) -(defn show-chat-name-edit [] - (dispatch [:navigate-to :chat-name-edit])) - (defn setting-view [{:keys [icon-style custom-icon handler title subtitle] icon-name :icon}] [touchable-highlight {:on-press handler} @@ -161,8 +158,7 @@ [text {:style st/chat-name-btn-edit-text} "Edit"]])]]) (defview group-settings [] - [selected-member [:group-settings-selected-member] - show-color-picker [:group-settings :show-color-picker]] + [show-color-picker [:group-settings :show-color-picker]] [view st/group-settings [new-group-toolbar] [scroll-view st/body @@ -179,5 +175,4 @@ [settings-view]] (when show-color-picker [chat-color-picker]) - (when selected-member - [member-menu])]) + [member-menu]]) diff --git a/src/syng_im/group_settings/subs.cljs b/src/syng_im/group_settings/subs.cljs index 844a7088af..816c5b0954 100644 --- a/src/syng_im/group_settings/subs.cljs +++ b/src/syng_im/group_settings/subs.cljs @@ -2,10 +2,10 @@ (:require-macros [reagent.ratom :refer [reaction]]) (:require [re-frame.core :refer [register-sub]])) -(register-sub :group-settings-selected-member +(register-sub :selected-participant (fn [db [_]] (reaction - (let [identity (get @db :group-settings-selected-member)] + (let [identity (first (get @db :selected-participants))] (get-in @db [:contacts identity]))))) (register-sub :group-settings diff --git a/src/syng_im/group_settings/views/member.cljs b/src/syng_im/group_settings/views/member.cljs index 593a8c7eab..79f0bc6e4c 100644 --- a/src/syng_im/group_settings/views/member.cljs +++ b/src/syng_im/group_settings/views/member.cljs @@ -38,6 +38,6 @@ [text {:style st/role-text} role])] [touchable-highlight - {:on-press #(dispatch [:set :group-settings-selected-member whisper-identity])} + {:on-press #(dispatch [:set :selected-participants #{whisper-identity}])} [view st/more-btn [icon :more-vertical st/more-btn-icon]]]]) diff --git a/src/syng_im/handlers.cljs b/src/syng_im/handlers.cljs index 327e336144..da547db56c 100644 --- a/src/syng_im/handlers.cljs +++ b/src/syng_im/handlers.cljs @@ -1,47 +1,23 @@ (ns syng-im.handlers (:require - [re-frame.core :refer [register-handler after dispatch debug enrich]] + [re-frame.core :refer [register-handler after dispatch debug]] [schema.core :as s :include-macros true] - [syng-im.persistence.realm :as r] [syng-im.db :refer [app-db schema]] [syng-im.persistence.simple-kv-store :as kv] [syng-im.protocol.state.storage :as storage] - [syng-im.db :as db :refer [app-db schema]] - [syng-im.protocol.api :refer [init-protocol]] - [syng-im.protocol.protocol-handler :refer [make-handler]] - [syng-im.models.protocol :refer [update-identity - set-initialized]] - [syng-im.models.contacts :as contacts] - [syng-im.models.messages :refer [save-message - update-message! - clear-history]] [syng-im.models.commands :refer [set-commands]] - [syng-im.handlers.server :as server] [syng-im.chat.suggestions :refer [load-commands]] - [syng-im.models.chats :refer [chat-exists? - create-chat - chat-add-participants - chat-remove-participants - set-chat-active - re-join-group-chat - chat-by-id2]] [syng-im.utils.logging :as log] - [syng-im.protocol.api :as api] - [syng-im.constants :refer [text-content-type - content-type-command]] - [syng-im.navigation :refer [nav-push - nav-replace - nav-pop]] [syng-im.utils.crypt :refer [gen-random-bytes]] - [syng-im.utils.random :as random] [syng-im.utils.handlers :as u] syng-im.chat.handlers - [syng-im.group-settings.handlers :refer [delete-chat]] + syng-im.group-settings.handlers syng-im.navigation.handlers syng-im.contacts.handlers syng-im.discovery.handlers syng-im.new-group.handlers - syng-im.participants.handlers)) + syng-im.participants.handlers + syng-im.protocol.handlers)) ;; -- Middleware ------------------------------------------------------------ ;; @@ -106,193 +82,8 @@ (log/debug action commands) (set-commands db commands))) -;; -- Protocol -------------------------------------------------------------- - -(register-handler :initialize-protocol - (u/side-effect! - (fn [db [_]] - (init-protocol (make-handler db))))) - -(register-handler :protocol-initialized - (fn [db [_ identity]] - (-> db - (update-identity identity) - (set-initialized true)))) - -(defn system-message [msg-id content] - {:from "system" - :msg-id msg-id - :content content - :content-type text-content-type}) - -(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 (str msg-id "_" from) - :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 (if (= identity (api/my-identity)) - "You" - (: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))] - (->> (str (or remover-name from) " removed " (or removed-name identity)) - (system-message msg-id) - (save-message chat-id)))) - -(defn you-removed-from-group-msg [chat-id from msg-id] - (let [remover-name (:name (contacts/contact-by-identity from))] - (->> (str (or remover-name from) " removed you from group chat") - (system-message msg-id) - (save-message chat-id)))) - -(defn participant-left-group-msg [chat-id from msg-id] - (let [left-name (:name (contacts/contact-by-identity from))] - (->> (str (or left-name from) " left") - (system-message msg-id) - (save-message chat-id)))) - -(defn removed-participant-msg [chat-id identity] - (let [contact-name (:name (contacts/contact-by-identity identity))] - (->> (str "You've removed " (or contact-name identity)) - (system-message (random/id)) - (save-message chat-id)))) - -(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 - (u/side-effect! - (fn [_ [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)))) - -(register-handler :participant-removed-from-group - (u/side-effect! - (fn [_ [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)))) - -(register-handler :you-removed-from-group - (u/side-effect! - (fn [_ [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)))) - -(register-handler :participant-left-group - (u/side-effect! - (fn [_ [action from group-id msg-id]] - (log/debug action msg-id from group-id) - (when-not (= (api/my-identity) from) - (participant-left-group-msg group-id from msg-id))))) - -(register-handler :participant-invited-to-group - (u/side-effect! - (fn [_ [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)))) - -(register-handler :acked-msg - (u/side-effect! - (fn [_ [action from msg-id]] - (log/debug action from msg-id) - (update-message! {:msg-id msg-id - :delivery-status :delivered})))) - -(register-handler :msg-delivery-failed - (u/side-effect! - (fn [_ [action msg-id]] - (log/debug action msg-id) - (update-message! {:msg-id msg-id - :delivery-status :failed})))) - -(register-handler :leave-group-chat - (u/side-effect! - (fn [db [action]] - (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) - (delete-chat chat-id) - (dispatch [:navigate-back]))))) - ;; -- User data -------------------------------------------------------------- (register-handler :load-user-phone-number (fn [db [_]] ;; todo fetch phone number from db (assoc db :user-phone-number "123"))) - -;; -- Chats -------------------------------------------------------------- -(defn update-new-participants-selection [db identity add?] - (update db :new-participants (fn [new-participants] - (if add? - (conj new-participants identity) - (disj new-participants identity))))) - -(register-handler :select-new-participant - (fn [db [action identity add?]] - (log/debug action identity add?) - (update-new-participants-selection db identity add?))) - -(register-handler :remove-selected-participants - (fn [db [action]] - (log/debug action) - (let [identities (vec (:new-participants db)) - chat-id (:current-chat-id db)] - (chat-remove-participants chat-id identities) - (dispatch [:navigate-back]) - (doseq [ident identities] - (api/group-remove-participant chat-id ident) - (removed-participant-msg chat-id ident))))) - -(register-handler :add-new-participants - (fn [db [action navigator]] - (log/debug action) - (let [identities (vec (:new-participants db)) - chat-id (:current-chat-id db)] - (chat-add-participants chat-id identities) - (dispatch [:navigate-back]) - (doseq [ident identities] - (api/group-add-participant chat-id ident)) - db))) - -(defn chat-remove-member [db] - (let [chat (get-in db [:chats (:current-chat-id db)]) - identity (:group-settings-selected-member db)] - (r/write - (fn [] - (r/create :chats - (update chat :contacts - (fn [members] - (filter #(not= (:identity %) identity) members))) - true))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats]) - db)) - - -(register-handler :chat-remove-member - (fn [db [action]] - (let [chat-id (:current-chat-id db) - identity (:group-settings-selected-member db) - db (chat-remove-member db)] - (dispatch [:set :group-settings-selected-member nil]) - ;; TODO fix and uncomment - (api/group-remove-participant chat-id identity) - (removed-participant-msg chat-id identity) - db))) diff --git a/src/syng_im/models/messages.cljs b/src/syng_im/models/messages.cljs index 2706cad94a..eeca56ce29 100644 --- a/src/syng_im/models/messages.cljs +++ b/src/syng_im/models/messages.cljs @@ -62,10 +62,3 @@ (fn [] (when (r/exists? :msgs :msg-id msg-id) (r/create :msgs msg true))))) - -(defn clear-history [chat-id] - (r/write - (fn [] - (r/delete (r/get-by-field :msgs :chat-id chat-id)))) - ;; TODO temp. Update chat in db atom - (dispatch [:initialize-chats])) diff --git a/src/syng_im/navigation.cljs b/src/syng_im/navigation.cljs deleted file mode 100644 index 9c95aa81b2..0000000000 --- a/src/syng_im/navigation.cljs +++ /dev/null @@ -1,17 +0,0 @@ -(ns syng-im.navigation) - -(def ^{:dynamic true :private true} *nav-render* - "Flag to suppress navigator re-renders from outside om when pushing/popping." - true) - -(defn nav-pop [nav] - (binding [*nav-render* true] - (.pop nav))) - -(defn nav-push [nav route] - (binding [*nav-render* true] - (.push nav (clj->js route)))) - -(defn nav-replace [nav route] - (binding [*nav-render* true] - (.replace nav (clj->js route)))) diff --git a/src/syng_im/navigation/handlers.cljs b/src/syng_im/navigation/handlers.cljs index f385485298..17f742254d 100644 --- a/src/syng_im/navigation/handlers.cljs +++ b/src/syng_im/navigation/handlers.cljs @@ -18,7 +18,9 @@ (update :navigation-stack replace-top-element view-id) (assoc :view-id view-id))) -(defmulti preload-data! (fn [_ [_ view-id]] view-id)) +(defmulti preload-data! + (fn [db [_ view-id]] (or view-id (:view-id db)))) + (defmethod preload-data! :default [db _] db) (register-handler :navigate-to @@ -32,6 +34,7 @@ (replace-view db view-id))) (register-handler :navigate-back + (enrich preload-data!) (fn [{:keys [navigation-stack] :as db} _] (if (>= 1 (count navigation-stack)) db diff --git a/src/syng_im/participants/handlers.cljs b/src/syng_im/participants/handlers.cljs index a2b71cf64d..06eb073190 100644 --- a/src/syng_im/participants/handlers.cljs +++ b/src/syng_im/participants/handlers.cljs @@ -4,20 +4,20 @@ (defmethod nav/preload-data! :add-participants [db _] - (assoc db :new-participants #{})) + (assoc db :selected-participants #{})) (defmethod nav/preload-data! :remove-participants [db _] - (assoc db :new-participants #{})) + (assoc db :selected-participants #{})) (defn deselect-participant [db [_ id]] - (update db :new-participants disj id)) + (update db :selected-participants disj id)) (register-handler :deselect-participant deselect-participant) (defn select-participant [db [_ id]] - (update db :new-participants conj id)) + (update db :selected-participants conj id)) (register-handler :select-participant (debug select-participant)) diff --git a/src/syng_im/participants/subs.cljs b/src/syng_im/participants/subs.cljs index c6e53a8af1..3d4a60bfa3 100644 --- a/src/syng_im/participants/subs.cljs +++ b/src/syng_im/participants/subs.cljs @@ -4,4 +4,4 @@ [syng-im.utils.subs :as u])) (register-sub :is-participant-selected? - (u/contains-sub :new-participants)) + (u/contains-sub :selected-participants)) diff --git a/src/syng_im/participants/views/add.cljs b/src/syng_im/participants/views/add.cljs index 826579fcd1..e336cbc4d2 100644 --- a/src/syng_im/participants/views/add.cljs +++ b/src/syng_im/participants/views/add.cljs @@ -11,10 +11,11 @@ (defn new-participants-toolbar [] [toolbar - {:title "Add Participants" - :action {:image {:source res/v ;; {:uri "icon_search"} - :style st/new-participant-image} - :handler #(dispatch [:add-new-participants])}}]) + {:title "Add Participants" + :action {:image {:source res/v ;; {:uri "icon_search"} + :style st/new-participant-image} + :handler #(do (dispatch [:add-new-participants]) + (dispatch [:navigate-back]))}}]) (defn new-participants-row [row _ _] diff --git a/src/syng_im/participants/views/remove.cljs b/src/syng_im/participants/views/remove.cljs index 32cbd1882e..d2ebd11cfd 100644 --- a/src/syng_im/participants/views/remove.cljs +++ b/src/syng_im/participants/views/remove.cljs @@ -14,10 +14,11 @@ (defn remove-participants-toolbar [] [toolbar - {:title "Remove Participants" - :action {:handler #(dispatch [:remove-selected-participants]) - :image {:source res/trash-icon ;; {:uri "icon_search"} - :style st/remove-participants-image}}}]) + {:title "Remove Participants" + :action {:handler #(do (dispatch [:remove-participants]) + (dispatch [:navigate-back])) + :image {:source res/trash-icon ;; {:uri "icon_search"} + :style st/remove-participants-image}}}]) (defn remove-participants-row [row _ _] diff --git a/src/syng_im/protocol/handlers.cljs b/src/syng_im/protocol/handlers.cljs new file mode 100644 index 0000000000..10bb1a4d2b --- /dev/null +++ b/src/syng_im/protocol/handlers.cljs @@ -0,0 +1,115 @@ +; todo everything inside this namespace must be revievew in common with future +; changes in protocol lib +(ns syng-im.protocol.handlers + (:require [syng-im.utils.handlers :as u] + [syng-im.utils.logging :as log] + [syng-im.protocol.api :as api] + [re-frame.core :refer [register-handler dispatch debug]] + [syng-im.models.contacts :as contacts] + [syng-im.protocol.api :refer [init-protocol]] + [syng-im.protocol.protocol-handler :refer [make-handler]] + [syng-im.models.protocol :refer [update-identity + set-initialized]] + [syng-im.constants :refer [text-content-type]] + [syng-im.models.messages :as messages] + [syng-im.models.chats :as chats])) + +(register-handler :initialize-protocol + (u/side-effect! + (fn [db [_]] + (init-protocol (make-handler db))))) + +(register-handler :protocol-initialized + (fn [db [_ identity]] + (-> db + (update-identity identity) + (set-initialized true)))) + +(defn system-message [msg-id content] + {:from "system" + :msg-id msg-id + :content content + :content-type text-content-type}) + +(defn joined-chat-msg [chat-id from msg-id] + (let [contact-name (:name (contacts/contact-by-identity from))] + (messages/save-message chat-id {:from "system" + :msg-id (str msg-id "_" from) + :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 (if (= identity (api/my-identity)) + "You" + (:name (contacts/contact-by-identity identity)))] + (messages/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))] + (->> (str (or remover-name from) " removed " (or removed-name identity)) + (system-message msg-id) + (messages/save-message chat-id)))) + +(defn you-removed-from-group-msg [chat-id from msg-id] + (let [remover-name (:name (contacts/contact-by-identity from))] + (->> (str (or remover-name from) " removed you from group chat") + (system-message msg-id) + (messages/save-message chat-id)))) + +(defn participant-left-group-msg [chat-id from msg-id] + (let [left-name (:name (contacts/contact-by-identity from))] + (->> (str (or left-name from) " left") + (system-message msg-id) + (messages/save-message chat-id)))) + +(register-handler :group-chat-invite-acked + (u/side-effect! + (fn [_ [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)))) + +(register-handler :participant-removed-from-group + (u/side-effect! + (fn [_ [action from group-id identity msg-id]] + (log/debug action msg-id from group-id identity) + (chats/chat-remove-participants group-id [identity]) + (participant-removed-from-group-msg group-id identity from msg-id)))) + +(register-handler :you-removed-from-group + (u/side-effect! + (fn [_ [action from group-id msg-id]] + (log/debug action msg-id from group-id) + (you-removed-from-group-msg group-id from msg-id) + (chats/set-chat-active group-id false)))) + +(register-handler :participant-left-group + (u/side-effect! + (fn [_ [action from group-id msg-id]] + (log/debug action msg-id from group-id) + (when-not (= (api/my-identity) from) + (participant-left-group-msg group-id from msg-id))))) + +(register-handler :participant-invited-to-group + (u/side-effect! + (fn [_ [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)))) + +(register-handler :acked-msg + (u/side-effect! + (fn [_ [action from msg-id]] + (log/debug action from msg-id) + (messages/update-message! {:msg-id msg-id + :delivery-status :delivered})))) + +(register-handler :msg-delivery-failed + (u/side-effect! + (fn [_ [action msg-id]] + (log/debug action msg-id) + (messages/update-message! {:msg-id msg-id + :delivery-status :failed}))))