From 737d44931f5a23c83fe1f3a552988db300d557bc Mon Sep 17 00:00:00 2001 From: Dmitry Novotochinov Date: Fri, 19 Oct 2018 23:15:01 +0300 Subject: [PATCH] [#4433] update mac os dock badge label on new messages Signed-off-by: Dmitry Novotochinov --- .../desktop/desktopnotification.cpp | 4 ++ .../desktop/desktopnotification.h | 1 + src/status_im/chat/models.cljs | 32 +++++++++++++++- src/status_im/chat/models/message.cljs | 38 +++++++++++-------- src/status_im/init/core.cljs | 7 +++- test/cljs/status_im/test/chat/models.cljs | 26 +++++++++++++ 6 files changed, 89 insertions(+), 19 deletions(-) diff --git a/modules/react-native-desktop-notification/desktop/desktopnotification.cpp b/modules/react-native-desktop-notification/desktop/desktopnotification.cpp index baef34213c..76c83db460 100644 --- a/modules/react-native-desktop-notification/desktop/desktopnotification.cpp +++ b/modules/react-native-desktop-notification/desktop/desktopnotification.cpp @@ -115,3 +115,7 @@ void DesktopNotification::sendNotification(QString text) { text, Snore::Icon::defaultIcon()); Snore::SnoreCore::instance().broadcastNotification(notification); } + +void DesktopNotification::setDockBadgeLabel(const QString label) { + Snore::SnoreCore::instance().setDockBadgeLabel(label); +} diff --git a/modules/react-native-desktop-notification/desktop/desktopnotification.h b/modules/react-native-desktop-notification/desktop/desktopnotification.h index 8911afc1a9..55fdf34a9f 100644 --- a/modules/react-native-desktop-notification/desktop/desktopnotification.h +++ b/modules/react-native-desktop-notification/desktop/desktopnotification.h @@ -36,6 +36,7 @@ public: QVariantMap constantsToExport() override; Q_INVOKABLE void sendNotification(QString text); + Q_INVOKABLE void setDockBadgeLabel(const QString label); private: QScopedPointer d_ptr; bool m_appHasFocus = false; diff --git a/src/status_im/chat/models.cljs b/src/status_im/chat/models.cljs index 0c354d85ec..78e0371311 100644 --- a/src/status_im/chat/models.cljs +++ b/src/status_im/chat/models.cljs @@ -14,6 +14,8 @@ [status-im.utils.fx :as fx] [status-im.utils.gfycat.core :as gfycat] [status-im.utils.utils :as utils] + [status-im.ui.components.colors :as colors] + [status-im.ui.components.react :as react] [status-im.utils.platform :as platform])) (defn multi-user-chat? [cofx chat-id] @@ -130,6 +132,23 @@ (when (not (get-in db [:chats chat-id :group-chat])) (protocol/send (protocol/map->MessagesSeen {:message-ids message-ids}) chat-id cofx))) +(defn- unread-messages-number [chats] + (apply + (map (comp count :unviewed-messages) chats))) + +(fx/defn update-dock-badge-label + [cofx] + (let [chats (get-in cofx [:db :chats]) + active-chats (filter :is-active (vals chats)) + private-chats (filter (complement :public?) active-chats) + public-chats (filter :public? active-chats) + private-chats-unread-count (unread-messages-number private-chats) + public-chats-unread-count (unread-messages-number public-chats) + label (cond + (pos? private-chats-unread-count) private-chats-unread-count + (pos? public-chats-unread-count) "•" + :else nil)] + {:set-dock-badge-label label})) + ;; TODO (janherich) - ressurect `constants/system` messages for group chats in the future (fx/defn mark-messages-seen "Marks all unviewed loaded messages as seen in particular chat" @@ -154,7 +173,9 @@ (update-in [:chats chat-id :unviewed-messages] #(apply disj % loaded-unviewed-ids))) :data-store/tx [(user-statuses-store/save-statuses-tx updated-statuses)]} - (send-messages-seen chat-id loaded-unviewed-ids)))))) + (send-messages-seen chat-id loaded-unviewed-ids) + (when platform/desktop? + (update-dock-badge-label))))))) (fx/defn preload-chat-data "Takes chat-id and coeffects map, returns effects necessary when navigating to chat" @@ -217,3 +238,12 @@ (utils/show-popup nil (i18n/label :cooldown/warning-message) #()))) + +(defn set-dock-badge-label [label] + "Sets dock badge label (OSX only for now). + Label must be a string. Pass nil or empty string to clear the label." + (.setDockBadgeLabel react/desktop-notification label)) + +(re-frame/reg-fx + :set-dock-badge-label + set-dock-badge-label) diff --git a/src/status_im/chat/models/message.cljs b/src/status_im/chat/models/message.cljs index 4ff5a3ac72..67b9028185 100644 --- a/src/status_im/chat/models/message.cljs +++ b/src/status_im/chat/models/message.cljs @@ -98,21 +98,23 @@ (get-in db [:account/account :desktop-notifications?]) (< (time/seconds-ago (time/to-date timestamp)) constants/one-earth-day)) (.sendNotification react/desktop-notification (:text content))) - (let [fx {:db (cond-> - (-> db - (update-in [:chats chat-id :messages] assoc message-id prepared-message) - ;; this will increase last-clock-value twice when sending our own messages - (update-in [:chats chat-id :last-clock-value] (partial utils.clocks/receive clock-value))) - (and (not current-chat?) - (not= from (:current-public-key db))) - (update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id)) - :data-store/tx [(messages-store/save-message-tx prepared-message)]}] - (if batch? - fx - (fx/merge cofx - fx - (re-index-message-groups chat-id) - (chat-loading/group-chat-messages chat-id [message])))))) + (fx/merge cofx + {:db (cond-> + (-> db + (update-in [:chats chat-id :messages] assoc message-id prepared-message) + ;; this will increase last-clock-value twice when sending our own messages + (update-in [:chats chat-id :last-clock-value] (partial utils.clocks/receive clock-value))) + (and (not current-chat?) + (not= from (:current-public-key db))) + (update-in [:chats chat-id :unviewed-messages] (fnil conj #{}) message-id)) + :data-store/tx [(messages-store/save-message-tx prepared-message)]} + (when (and platform/desktop? + (not batch?)) + (chat-model/update-dock-badge-label)) + (when-not batch? + (re-index-message-groups chat-id)) + (when-not batch? + (chat-loading/group-chat-messages chat-id [message]))))) (fx/defn send-message-seen [cofx chat-id message-id send-seen?] @@ -217,7 +219,11 @@ chat-ids) messages-fx-fns (map #(add-received-message true %) deduped-messages) groups-fx-fns (map #(update-group-messages chat->message %) chat-ids)] - (apply fx/merge cofx (concat chats-fx-fns messages-fx-fns groups-fx-fns)))) + (apply fx/merge cofx (concat chats-fx-fns + messages-fx-fns + groups-fx-fns + (when platform/desktop? + [(chat-model/update-dock-badge-label)]))))) (defn system-message [{:keys [now] :as cofx} {:keys [clock-value chat-id content from]}] (let [{:keys [last-clock-value]} (get-in cofx [:db :chats chat-id]) diff --git a/src/status_im/init/core.cljs b/src/status_im/init/core.cljs index 2dc035d031..042f59b860 100644 --- a/src/status_im/init/core.cljs +++ b/src/status_im/init/core.cljs @@ -27,7 +27,8 @@ [status-im.utils.universal-links.core :as universal-links] [status-im.utils.utils :as utils] [taoensso.timbre :as log] - [status-im.utils.fx :as fx])) + [status-im.utils.fx :as fx] + [status-im.chat.models :as chat-model])) (defn init-store! "Try to decrypt the database, move on if successful otherwise go back to @@ -188,7 +189,9 @@ {:notifications/request-notifications-permissions nil} (navigation/navigate-to-cofx :home nil) (universal-links/process-stored-event) - (notifications/process-stored-event address))) + (notifications/process-stored-event address) + (when platform/desktop? + (chat-model/update-dock-badge-label)))) (defn dev-mode? [cofx] (get-in cofx [:db :account/account :dev-mode?])) diff --git a/test/cljs/status_im/test/chat/models.cljs b/test/cljs/status_im/test/chat/models.cljs index 8b29c93188..15a844ed73 100644 --- a/test/cljs/status_im/test/chat/models.cljs +++ b/test/cljs/status_im/test/chat/models.cljs @@ -253,3 +253,29 @@ (is (= #{"4" "5" "6"} (set (get-in (chat/mark-messages-seen {:db test-db} "1-1") [:shh/post 0 :message :payload :message-ids])))))) + +(deftest update-dock-badge-label + (testing "When user has unseen private messages" + (is (= {:set-dock-badge-label 3} + (chat/update-dock-badge-label {:db {:chats {"0x0" {:is-active true + :public? false + :unviewed-messages #{1 2 3}} + "status" {:is-active true + :public? true + :unviewed-messages #{1 2}}}}})))) + (testing "When user has unseen public messages and no unseen private messages" + (is (= {:set-dock-badge-label "•"} + (chat/update-dock-badge-label {:db {:chats {"0x0" {:is-active true + :public? false + :unviewed-messages #{}} + "status" {:is-active true + :public? true + :unviewed-messages #{1 2}}}}})))) + (testing "When user has no unseen messages" + (is (= {:set-dock-badge-label nil} + (chat/update-dock-badge-label {:db {:chats {"0x0" {:is-active true + :public? false + :unviewed-messages #{}} + "status" {:is-active true + :public? true + :unviewed-messages #{}}}}})))))