From 85cc7cc32bbb112b7e09a36ad40bbd234ffbcdfc Mon Sep 17 00:00:00 2001 From: ialokim <ialokim@mailbox.org> Date: Sat, 3 Dec 2022 00:30:20 +0100 Subject: [PATCH] send notifications on new forum posts --- .../notification/NotificationProvider.kt | 2 + .../notification/SoundNotificationProvider.kt | 5 ++- .../linux/LibnotifyNotificationProvider.kt | 20 ++++++--- .../briarproject/briar/desktop/ui/BriarUi.kt | 26 ++++++++--- .../briar/desktop/ui/MessageCounter.kt | 5 ++- .../briar/desktop/ui/MessageCounterImpl.kt | 45 +++++++++++++++---- .../resources/strings/BriarDesktop.properties | 2 + 7 files changed, 84 insertions(+), 21 deletions(-) diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/NotificationProvider.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/NotificationProvider.kt index 60449a37d8..ac9888246a 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/NotificationProvider.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/NotificationProvider.kt @@ -36,6 +36,7 @@ interface NotificationProvider { fun init() fun uninit() fun notifyPrivateMessages(num: Int, contacts: Int) + fun notifyForumPosts(num: Int, forums: Int) } interface VisualNotificationProvider : NotificationProvider @@ -50,4 +51,5 @@ object StubNotificationProvider : VisualNotificationProvider { override fun init() {} override fun uninit() {} override fun notifyPrivateMessages(num: Int, contacts: Int) {} + override fun notifyForumPosts(num: Int, forums: Int) {} } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/SoundNotificationProvider.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/SoundNotificationProvider.kt index 8611f17a78..ef5edba4e7 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/SoundNotificationProvider.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/SoundNotificationProvider.kt @@ -51,7 +51,10 @@ object SoundNotificationProvider : NotificationProvider { } } - override fun notifyPrivateMessages(num: Int, contacts: Int) { + private fun playSound() { if (available) sound.play() } + + override fun notifyPrivateMessages(num: Int, contacts: Int) = playSound() + override fun notifyForumPosts(num: Int, forums: Int) = playSound() } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt index 5527fa230c..0e91e5d8f0 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/notification/linux/LibnotifyNotificationProvider.kt @@ -82,7 +82,7 @@ object LibnotifyNotificationProvider : VisualNotificationProvider { } } - override fun notifyPrivateMessages(num: Int, contacts: Int) { + private fun sendNotification(text: String) { if (!available) return /** @@ -95,10 +95,6 @@ object LibnotifyNotificationProvider : VisualNotificationProvider { * The summary must be encoded using UTF-8. */ // todo: we could use body instead with markup (where supported) - val text = if (contacts == 1) - i18nP("notifications.message.private.one_chat", num) - else - i18nF("notifications.message.private.several_chats", num, contacts) val notification = libNotify.notify_notification_new(text, null, null) /** @@ -135,6 +131,20 @@ object LibnotifyNotificationProvider : VisualNotificationProvider { } } + override fun notifyPrivateMessages(num: Int, contacts: Int) = sendNotification( + if (contacts == 1) + i18nP("notifications.message.private.one_chat", num) + else + i18nF("notifications.message.private.several_chats", num, contacts) + ) + + override fun notifyForumPosts(num: Int, forums: Int) = sendNotification( + if (forums == 1) + i18nP("notifications.message.forum.one_forum", num) + else + i18nF("notifications.message.forum.several_forums", num, forums) + ) + /** * Functions as defined in the source code at * https://www.freedesktop.org/software/gstreamer-sdk/data/docs/latest/glib/glib-GVariant.html diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt index a2085c5f0a..8badde07f6 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt @@ -47,12 +47,15 @@ import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent import org.briarproject.briar.desktop.expiration.ExpirationBanner import org.briarproject.briar.desktop.login.ErrorScreen import org.briarproject.briar.desktop.login.StartupScreen +import org.briarproject.briar.desktop.notification.NotificationProvider import org.briarproject.briar.desktop.notification.SoundNotificationProvider import org.briarproject.briar.desktop.notification.VisualNotificationProvider import org.briarproject.briar.desktop.settings.Configuration import org.briarproject.briar.desktop.settings.UnencryptedSettings.Theme.AUTO import org.briarproject.briar.desktop.settings.UnencryptedSettings.Theme.DARK import org.briarproject.briar.desktop.theme.BriarTheme +import org.briarproject.briar.desktop.ui.MessageCounterDataType.Forum +import org.briarproject.briar.desktop.ui.MessageCounterDataType.PrivateMessage import org.briarproject.briar.desktop.ui.Screen.EXPIRED import org.briarproject.briar.desktop.ui.Screen.MAIN import org.briarproject.briar.desktop.ui.Screen.STARTUP @@ -136,7 +139,8 @@ constructor( DisposableEffect(Unit) { val notificationCoolDown = 5.seconds.inWholeMilliseconds - var lastNotification = 0L + var lastNotificationPrivateMessage = 0L + var lastNotificationForum = 0L val eventListener = EventListener { e -> when (e) { @@ -153,19 +157,29 @@ constructor( override fun windowLostFocus(e: WindowEvent?) { focusState.focused = false // reset notification cool-down - lastNotification = 0 + lastNotificationPrivateMessage = 0 + lastNotificationForum = 0 } } - val messageCounterListener: MessageCounterListener = { (total, contacts) -> + val messageCounterListener: MessageCounterListener = { (type, total, groups) -> if (total > 0 && !focusState.focused) { + val callback: NotificationProvider.() -> Unit = when (type) { + PrivateMessage -> { { notifyPrivateMessages(total, groups) } } + Forum -> { { notifyForumPosts(total, groups) } } + } + val (lastNotification, setLastNotification) = when (type) { + PrivateMessage -> lastNotificationPrivateMessage to { v: Long -> lastNotificationPrivateMessage = v } + Forum -> lastNotificationForum to { v: Long -> lastNotificationForum = v } + } + window.iconImage = iconBadge val currentTime = System.currentTimeMillis() if (currentTime - lastNotification > notificationCoolDown) { if (configuration.visualNotifications) - visualNotificationProvider.notifyPrivateMessages(total, contacts) + visualNotificationProvider.apply(callback) if (configuration.soundNotifications) - soundNotificationProvider.notifyPrivateMessages(total, contacts) - lastNotification = currentTime + soundNotificationProvider.apply(callback) + setLastNotification(currentTime) } } } diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounter.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounter.kt index f01ff09f0a..b5a07dfac7 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounter.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounter.kt @@ -25,9 +25,12 @@ interface MessageCounter { fun removeListener(listener: MessageCounterListener): Boolean } +enum class MessageCounterDataType { PrivateMessage, Forum } + data class MessageCounterData( + val type: MessageCounterDataType, val total: Int, - val contacts: Int, + val groups: Int, ) typealias MessageCounterListener = (MessageCounterData) -> Unit diff --git a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounterImpl.kt b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounterImpl.kt index 2234e68124..906a40ebfb 100644 --- a/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounterImpl.kt +++ b/briar-desktop/src/main/kotlin/org/briarproject/briar/desktop/ui/MessageCounterImpl.kt @@ -24,10 +24,16 @@ import org.briarproject.bramble.api.contact.ContactManager import org.briarproject.bramble.api.event.EventBus import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent +import org.briarproject.bramble.api.sync.GroupId import org.briarproject.briar.api.conversation.ConversationManager import org.briarproject.briar.api.conversation.event.ConversationMessageReceivedEvent +import org.briarproject.briar.api.forum.ForumManager +import org.briarproject.briar.api.forum.event.ForumPostReceivedEvent import org.briarproject.briar.desktop.conversation.ConversationMessagesReadEvent +import org.briarproject.briar.desktop.forums.ForumPostReadEvent import org.briarproject.briar.desktop.threading.BriarExecutors +import org.briarproject.briar.desktop.ui.MessageCounterDataType.Forum +import org.briarproject.briar.desktop.ui.MessageCounterDataType.PrivateMessage import javax.inject.Inject class MessageCounterImpl @@ -35,11 +41,13 @@ class MessageCounterImpl constructor( private val contactManager: ContactManager, private val conversationManager: ConversationManager, + private val forumManager: ForumManager, private val briarExecutors: BriarExecutors, eventBus: EventBus, ) : MessageCounter { - private val messageCount = Multiset<ContactId>() + private val countPrivateMessages = Multiset<ContactId>() + private val countForumPosts = Multiset<GroupId>() private val listeners = mutableListOf<MessageCounterListener>() @@ -52,19 +60,36 @@ constructor( val contacts = contactManager.getContacts(txn) for (c in contacts) { val unreadMessages = conversationManager.getGroupCount(txn, c.id).unreadCount - messageCount.addCount(c.id, unreadMessages) + countPrivateMessages.addCount(c.id, unreadMessages) + } + val forums = forumManager.getForums(txn) + for (f in forums) { + val unreadMessages = forumManager.getGroupCount(txn, f.id).unreadCount + countForumPosts.addCount(f.id, unreadMessages) + } + txn.attach { + informListeners(PrivateMessage) + informListeners(Forum) } - txn.attach { informListeners() } } } is ConversationMessageReceivedEvent<*> -> { - messageCount.add(e.contactId) - informListeners() + countPrivateMessages.add(e.contactId) + informListeners(PrivateMessage) } is ConversationMessagesReadEvent -> { - messageCount.removeCount(e.contactId, e.count) + countPrivateMessages.removeCount(e.contactId, e.count) + } + + is ForumPostReceivedEvent -> { + countForumPosts.add(e.groupId) + informListeners(Forum) + } + + is ForumPostReadEvent -> { + countForumPosts.removeCount(e.groupId, e.numMarkedRead) } } } @@ -74,8 +99,12 @@ constructor( override fun removeListener(listener: MessageCounterListener) = listeners.remove(listener) - private fun informListeners() = listeners.forEach { l -> - l.invoke(MessageCounterData(messageCount.total, messageCount.unique)) + private fun informListeners(type: MessageCounterDataType) = listeners.forEach { l -> + val groupCount = when (type) { + PrivateMessage -> countPrivateMessages + Forum -> countForumPosts + } + l.invoke(MessageCounterData(type, groupCount.total, groupCount.unique)) } private fun <T> Multiset<T>.removeCount(t: T, count: Int) = diff --git a/briar-desktop/src/main/resources/strings/BriarDesktop.properties b/briar-desktop/src/main/resources/strings/BriarDesktop.properties index 27063d7799..3b77ccf202 100644 --- a/briar-desktop/src/main/resources/strings/BriarDesktop.properties +++ b/briar-desktop/src/main/resources/strings/BriarDesktop.properties @@ -296,6 +296,8 @@ expiration.banner.part2=Please update to a newer version in time. # Notification notifications.message.private.one_chat={0, plural, one {New private message.} other {{0} new private messages.}} notifications.message.private.several_chats={0} new messages in {1} private chats. +notifications.message.forum.one_forum={0, plural, one {New forum post.} other {{0} new forum posts.}} +notifications.message.forum.several_forum={0} new posts in {1} forums. # Settings settings.title=Settings -- GitLab