🚧 Use handler for new-reply notifications
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 9 Jan 2020 22:01:20 +0000 (23:01 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Thu, 9 Jan 2020 22:01:20 +0000 (23:01 +0100)
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandler.kt
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModule.kt
src/main/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandler.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModuleTest.kt
src/test/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandlerTest.kt [new file with mode: 0644]

index ea357d2..c757599 100644 (file)
@@ -169,6 +169,7 @@ public class WebInterface implements SessionProvider {
                        LinkedElementRenderFilter linkedElementRenderFilter,
                        PageToadletRegistry pageToadletRegistry, MetricRegistry metricRegistry, Translation translation, L10nFilter l10nFilter,
                        NotificationManager notificationManager, @Named("newRemotePost") ListNotification<Post> newPostNotification,
+                       @Named("newRemotePostReply") ListNotification<PostReply> newReplyNotification,
                        @Named("localPost") ListNotification<Post> localPostNotification) {
                this.sonePlugin = sonePlugin;
                this.loaders = loaders;
@@ -187,6 +188,7 @@ public class WebInterface implements SessionProvider {
                this.translation = translation;
                this.notificationManager = notificationManager;
                this.newPostNotification = newPostNotification;
+               this.newReplyNotification = newReplyNotification;
                this.localPostNotification = localPostNotification;
                formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword();
 
@@ -195,9 +197,6 @@ public class WebInterface implements SessionProvider {
                templateContextFactory.addTemplateObject("formPassword", formPassword);
 
                /* create notifications. */
-               Template newReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
-               newReplyNotification = new ListNotification<>("new-reply-notification", "replies", newReplyNotificationTemplate, false);
-
                Template localReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
                localReplyNotification = new ListNotification<>("local-reply-notification", "replies", localReplyNotificationTemplate, false);
        }
@@ -527,11 +526,9 @@ public class WebInterface implements SessionProvider {
                boolean isLocal = reply.getSone().isLocal();
                if (isLocal) {
                        localReplyNotification.add(reply);
-               } else {
-                       newReplyNotification.add(reply);
-               }
-               if (!hasFirstStartNotification()) {
-                       notificationManager.addNotification(isLocal ? localReplyNotification : newReplyNotification);
+                       if (!hasFirstStartNotification()) {
+                               notificationManager.addNotification(localReplyNotification);
+                       }
                }
        }
 
@@ -560,7 +557,6 @@ public class WebInterface implements SessionProvider {
        }
 
        private void removeReply(PostReply reply) {
-               newReplyNotification.remove(reply);
                localReplyNotification.remove(reply);
        }
 
index d0e8bf2..f7c0743 100644 (file)
@@ -31,6 +31,7 @@ class NotificationHandler @Inject constructor(
                markPostReplyKnownDuringFirstStartHandler: MarkPostReplyKnownDuringFirstStartHandler,
                newSoneHandler: NewSoneHandler,
                newRemotePostHandler: NewRemotePostHandler,
+               remotePostReplyHandler: RemotePostReplyHandler,
                soneLockedOnStartupHandler: SoneLockedOnStartupHandler,
                soneLockedHandler: SoneLockedHandler,
                newVersionHandler: NewVersionHandler,
index 2b147fc..4a91fc7 100644 (file)
@@ -44,6 +44,7 @@ class NotificationHandlerModule : AbstractModule() {
                bind<SoneLockedOnStartupHandler>().asSingleton()
                bind<NewSoneHandler>().asSingleton()
                bind<NewRemotePostHandler>().asSingleton()
+               bind<RemotePostReplyHandler>().asSingleton()
                bind<SoneLockedHandler>().asSingleton()
                bind<LocalPostHandler>().asSingleton()
                bind<NewVersionHandler>().asSingleton()
@@ -81,6 +82,12 @@ class NotificationHandlerModule : AbstractModule() {
 
        @Provides
        @Singleton
+       @Named("newRemotePostReply")
+       fun getNewRemotePostReplyNotification(loaders: Loaders) =
+                       ListNotification<PostReply>("new-reply-notification", "replies", loaders.loadTemplate("/templates/notify/newReplyNotification.html"), dismissable = false)
+
+       @Provides
+       @Singleton
        @Named("soneLocked")
        fun getSoneLockedNotification(loaders: Loaders) =
                        ListNotification<Sone>("sones-locked-notification", "sones", loaders.loadTemplate("/templates/notify/lockedSonesNotification.html"), dismissable = true)
diff --git a/src/main/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandler.kt b/src/main/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandler.kt
new file mode 100644 (file)
index 0000000..7dec7c9
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * Sone - RemotePostReplyHandler.kt - Copyright © 2020 David ‘Bombe’ Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.web.notification
+
+import com.google.common.eventbus.*
+import net.pterodactylus.sone.core.event.*
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.notify.*
+import net.pterodactylus.sone.utils.*
+import net.pterodactylus.util.notify.*
+import javax.inject.*
+
+/**
+ * Handler for remote replies.
+ */
+class RemotePostReplyHandler @Inject constructor(private val notificationManager: NotificationManager, @Named("newRemotePostReply") private val notification: ListNotification<PostReply>) {
+
+       @Subscribe
+       fun newPostReplyFound(event: NewPostReplyFoundEvent) {
+               event.postReply.let { postReply ->
+                       postReply.sone.isLocal.onFalse {
+                               if (!notificationManager.hasFirstStartNotification()) {
+                                       notification.add(event.postReply)
+                                       notificationManager.addNotification(notification)
+                               }
+                       }
+               }
+       }
+
+       @Subscribe
+       fun postReplyRemoved(event: PostReplyRemovedEvent) {
+               notification.remove(event.postReply)
+       }
+
+       @Subscribe
+       fun postReplyMarkedAsKnown(event: MarkPostReplyKnownEvent) {
+               notification.remove(event.postReply)
+       }
+
+}
index a4ed7af..138a41e 100644 (file)
@@ -182,6 +182,35 @@ class NotificationHandlerModuleTest {
        }
 
        @Test
+       fun `remote-post handler is created as singleton`() {
+               injector.verifySingletonInstance<RemotePostReplyHandler>()
+       }
+
+       @Test
+       fun `new-remote-post-reply notification is created as singleton`() {
+               injector.verifySingletonInstance<ListNotification<PostReply>>(named("newRemotePostReply"))
+       }
+
+       @Test
+       fun `new-remote-post-reply notification has correct ID`() {
+               assertThat(injector.getInstance<ListNotification<PostReply>>(named("newRemotePostReply")).id, equalTo("new-reply-notification"))
+       }
+
+       @Test
+       fun `new-remote-post-reply notification is not dismissable`() {
+               assertThat(injector.getInstance<ListNotification<PostReply>>(named("newRemotePostReply")).isDismissable, equalTo(false))
+       }
+
+       @Test
+       fun `new-remote-post-reply notification has correct key and template`() {
+               loaders.templates += "/templates/notify/newReplyNotification.html" to "<% replies>".asTemplate()
+               val notification = injector.getInstance<ListNotification<PostReply>>(named("newRemotePostReply"))
+               val postReplies = listOf(emptyPostReply(), emptyPostReply())
+               postReplies.forEach(notification::add)
+               assertThat(notification.render(), equalTo(postReplies.toString()))
+       }
+
+       @Test
        fun `sone-locked notification is created as singleton`() {
                injector.verifySingletonInstance<ListNotification<Sone>>(named("soneLocked"))
        }
diff --git a/src/test/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandlerTest.kt b/src/test/kotlin/net/pterodactylus/sone/web/notification/RemotePostReplyHandlerTest.kt
new file mode 100644 (file)
index 0000000..9c5361c
--- /dev/null
@@ -0,0 +1,93 @@
+/**
+ * Sone - RemotePostReplyHandler.kt - Copyright © 2020 David ‘Bombe’ Roden
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package net.pterodactylus.sone.web.notification
+
+import net.pterodactylus.sone.core.event.*
+import net.pterodactylus.sone.data.*
+import net.pterodactylus.sone.notify.*
+import net.pterodactylus.sone.test.*
+import net.pterodactylus.util.notify.*
+import net.pterodactylus.util.template.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import kotlin.test.*
+
+/**
+ * Unit test for [RemotePostReplyHandler].
+ */
+class RemotePostReplyHandlerTest {
+
+       private val notification = ListNotification<PostReply>("", "", Template())
+       private val notificationHandlerTester = NotificationHandlerTester { RemotePostReplyHandler(it, notification) }
+       private val postReply = emptyPostReply()
+
+       @Test
+       fun `reply is added to notification on new reply`() {
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notification.elements, hasItem<PostReply>(postReply))
+       }
+
+       @Test
+       fun `notification is added to manager on new reply`() {
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notificationHandlerTester.notifications, hasItem<Notification>(notification))
+       }
+
+       @Test
+       fun `reply is not added to notification on new reply during first start`() {
+               notificationHandlerTester.firstStart()
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notification.elements, not(hasItem<PostReply>(postReply)))
+       }
+
+       @Test
+       fun `notification is not added to manager on new reply during first start`() {
+               notificationHandlerTester.firstStart()
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notificationHandlerTester.notifications, not(hasItem<Notification>(notification)))
+       }
+
+       @Test
+       fun `reply is not added to notification on new local reply`() {
+               val postReply = emptyPostReply(sone = localSone1)
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notification.elements, not(hasItem<PostReply>(postReply)))
+       }
+
+       @Test
+       fun `notification is not added to manager on new local reply`() {
+               val postReply = emptyPostReply(sone = localSone1)
+               notificationHandlerTester.sendEvent(NewPostReplyFoundEvent(postReply))
+               assertThat(notificationHandlerTester.notifications, not(hasItem<Notification>(notification)))
+       }
+
+       @Test
+       fun `reply is removed from notification when removed`() {
+               notification.add(postReply)
+               notificationHandlerTester.sendEvent(PostReplyRemovedEvent(postReply))
+               assertThat(notification.elements, not(hasItem<PostReply>(postReply)))
+       }
+
+       @Test
+       fun `reply is removed from notification when marked as known`() {
+               notification.add(postReply)
+               notificationHandlerTester.sendEvent(MarkPostReplyKnownEvent(postReply))
+               assertThat(notification.elements, not(hasItem<PostReply>(postReply)))
+       }
+
+}