♻️ Use handler for local-reply notifications
authorDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 8 Feb 2020 12:09:17 +0000 (13:09 +0100)
committerDavid ‘Bombe’ Roden <bombe@pterodactylus.net>
Sat, 8 Feb 2020 12:09:17 +0000 (13:09 +0100)
src/main/java/net/pterodactylus/sone/web/WebInterface.java
src/main/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandler.kt [new file with mode: 0644]
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandler.kt
src/main/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModule.kt
src/test/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandlerTest.kt [new file with mode: 0644]
src/test/kotlin/net/pterodactylus/sone/web/notification/NotificationHandlerModuleTest.kt

index c757599..027fb7f 100644 (file)
@@ -170,7 +170,8 @@ public class WebInterface implements SessionProvider {
                        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) {
+                       @Named("localPost") ListNotification<Post> localPostNotification,
+                       @Named("localReply") ListNotification<PostReply> localReplyNotification) {
                this.sonePlugin = sonePlugin;
                this.loaders = loaders;
                this.listNotificationFilter = listNotificationFilter;
@@ -190,15 +191,12 @@ public class WebInterface implements SessionProvider {
                this.newPostNotification = newPostNotification;
                this.newReplyNotification = newReplyNotification;
                this.localPostNotification = localPostNotification;
+               this.localReplyNotification = localReplyNotification;
                formPassword = sonePlugin.pluginRespirator().getToadletContainer().getFormPassword();
 
                this.templateContextFactory = templateContextFactory;
                templateContextFactory.addTemplateObject("webInterface", this);
                templateContextFactory.addTemplateObject("formPassword", formPassword);
-
-               /* create notifications. */
-               Template localReplyNotificationTemplate = loaders.loadTemplate("/templates/notify/newReplyNotification.html");
-               localReplyNotification = new ListNotification<>("local-reply-notification", "replies", localReplyNotificationTemplate, false);
        }
 
        //
@@ -514,35 +512,12 @@ public class WebInterface implements SessionProvider {
        // EVENT HANDLERS
        //
 
-       /**
-        * Notifies the web interface that a new {@link PostReply} was found.
-        *
-        * @param newPostReplyFoundEvent
-        *            The event
-        */
-       @Subscribe
-       public void newReplyFound(NewPostReplyFoundEvent newPostReplyFoundEvent) {
-               PostReply reply = newPostReplyFoundEvent.getPostReply();
-               boolean isLocal = reply.getSone().isLocal();
-               if (isLocal) {
-                       localReplyNotification.add(reply);
-                       if (!hasFirstStartNotification()) {
-                               notificationManager.addNotification(localReplyNotification);
-                       }
-               }
-       }
-
        @Subscribe
        public void markPostKnown(MarkPostKnownEvent markPostKnownEvent) {
                removePost(markPostKnownEvent.getPost());
        }
 
        @Subscribe
-       public void markReplyKnown(MarkPostReplyKnownEvent markPostReplyKnownEvent) {
-               removeReply(markPostReplyKnownEvent.getPostReply());
-       }
-
-       @Subscribe
        public void postRemoved(PostRemovedEvent postRemovedEvent) {
                removePost(postRemovedEvent.getPost());
        }
@@ -551,15 +526,6 @@ public class WebInterface implements SessionProvider {
                newPostNotification.remove(post);
        }
 
-       @Subscribe
-       public void replyRemoved(PostReplyRemovedEvent postReplyRemovedEvent) {
-               removeReply(postReplyRemovedEvent.getPostReply());
-       }
-
-       private void removeReply(PostReply reply) {
-               localReplyNotification.remove(reply);
-       }
-
        /**
         * Notifies the web interface that a {@link Sone} is being inserted.
         *
diff --git a/src/main/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandler.kt b/src/main/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandler.kt
new file mode 100644 (file)
index 0000000..424295e
--- /dev/null
@@ -0,0 +1,54 @@
+/**
+ * Sone - LocalReplyHandler.kt - Copyright © 2019 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.util.notify.*
+import javax.inject.*
+
+/**
+ * Handler for local replies.
+ */
+class LocalReplyHandler @Inject constructor(private val notificationManager: NotificationManager, @Named("localReply") private val notification: ListNotification<PostReply>) {
+
+       @Subscribe
+       fun newReplyFound(event: NewPostReplyFoundEvent) =
+                       event.postReply.onLocal {
+                               notification.add(it)
+                               if (!notificationManager.hasFirstStartNotification()) {
+                                       notificationManager.addNotification(notification)
+                               }
+                       }
+
+       @Subscribe
+       fun replyRemoved(event: PostReplyRemovedEvent) {
+               notification.remove(event.postReply)
+       }
+
+       @Subscribe
+       fun replyMarkedAsKnown(event: MarkPostReplyKnownEvent) {
+               notification.remove(event.postReply)
+       }
+
+}
+
+private fun PostReply.onLocal(action: (PostReply) -> Unit) =
+               if (sone.isLocal) action(this) else Unit
index 6e1d216..c55308e 100644 (file)
@@ -35,6 +35,7 @@ class NotificationHandler @Inject constructor(
                soneLockedOnStartupHandler: SoneLockedOnStartupHandler,
                soneLockedHandler: SoneLockedHandler,
                localPostHandler: LocalPostHandler,
+               localReplyHandler: LocalReplyHandler,
                newVersionHandler: NewVersionHandler,
                imageInsertHandler: ImageInsertHandler,
                firstStartHandler: FirstStartHandler,
index 4a91fc7..bb37e09 100644 (file)
@@ -47,6 +47,7 @@ class NotificationHandlerModule : AbstractModule() {
                bind<RemotePostReplyHandler>().asSingleton()
                bind<SoneLockedHandler>().asSingleton()
                bind<LocalPostHandler>().asSingleton()
+               bind<LocalReplyHandler>().asSingleton()
                bind<NewVersionHandler>().asSingleton()
                bind<ImageInsertHandler>().asSingleton()
                bind<FirstStartHandler>().asSingleton()
@@ -100,6 +101,12 @@ class NotificationHandlerModule : AbstractModule() {
 
        @Provides
        @Singleton
+       @Named("localReply")
+       fun getLocalReplyNotification(loaders: Loaders) =
+                       ListNotification<PostReply>("local-reply-notification", "replies", loaders.loadTemplate("/templates/notify/newReplyNotification.html"), dismissable = false)
+
+       @Provides
+       @Singleton
        @Named("newVersion")
        fun getNewVersionNotification(loaders: Loaders) =
                        TemplateNotification("new-version-notification", loaders.loadTemplate("/templates/notify/newVersionNotification.html"))
diff --git a/src/test/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandlerTest.kt b/src/test/kotlin/net/pterodactylus/sone/web/notification/LocalReplyHandlerTest.kt
new file mode 100644 (file)
index 0000000..750d083
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ * Sone - LocalReplyHandlerTest.kt - Copyright © 2019 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.template.*
+import org.hamcrest.MatcherAssert.*
+import org.hamcrest.Matchers.*
+import kotlin.test.*
+
+/**
+ * Unit test for [LocalReplyHandler].
+ */
+class LocalReplyHandlerTest {
+
+       private val notification = ListNotification<PostReply>("", "", Template())
+       private val localReplyHandlerTester = NotificationHandlerTester { LocalReplyHandler(it, notification) }
+
+       @Test
+       fun `handler does not add reply to notification`() {
+               localReplyHandlerTester.sendEvent(NewPostReplyFoundEvent(remoteReply))
+               assertThat(notification.elements, emptyIterable())
+       }
+
+       @Test
+       fun `handler does add local reply to notification`() {
+               localReplyHandlerTester.sendEvent(NewPostReplyFoundEvent(localReply))
+               assertThat(notification.elements, contains(localReply))
+       }
+
+       @Test
+       fun `handler adds notification to manager`() {
+               localReplyHandlerTester.sendEvent(NewPostReplyFoundEvent(localReply))
+               assertThat(localReplyHandlerTester.notifications, hasItem(notification))
+       }
+
+       @Test
+       fun `handler does not add notification to manager for remote reply`() {
+               localReplyHandlerTester.sendEvent(NewPostReplyFoundEvent(remoteReply))
+               assertThat(localReplyHandlerTester.notifications, not(hasItem(notification)))
+       }
+
+       @Test
+       fun `handler does not add notification to manager during first start`() {
+               localReplyHandlerTester.firstStart()
+               localReplyHandlerTester.sendEvent(NewPostReplyFoundEvent(localReply))
+               assertThat(localReplyHandlerTester.notifications, not(hasItem(notification)))
+       }
+
+       @Test
+       fun `handler removes reply from notification if reply is removed`() {
+               notification.add(localReply)
+               localReplyHandlerTester.sendEvent(PostReplyRemovedEvent(localReply))
+               assertThat(notification.elements, not(hasItem(localReply)))
+       }
+
+       @Test
+       fun `handler removes reply from notification if reply is marked as known`() {
+               notification.add(localReply)
+               localReplyHandlerTester.sendEvent(MarkPostReplyKnownEvent(localReply))
+               assertThat(notification.elements, not(hasItem(localReply)))
+       }
+
+}
+
+private val localReply = emptyPostReply(sone = localSone1)
+private val remoteReply = emptyPostReply()
index 138a41e..27f396f 100644 (file)
@@ -269,6 +269,35 @@ class NotificationHandlerModuleTest {
        }
 
        @Test
+       fun `local-reply notification is not dismissable`() {
+               assertThat(injector.getInstance<ListNotification<PostReply>>(named("localReply")).isDismissable, equalTo(false))
+       }
+
+       @Test
+       fun `local-reply notification has correct ID`() {
+               assertThat(injector.getInstance<ListNotification<PostReply>>(named("localReply")).id, equalTo("local-reply-notification"))
+       }
+
+       @Test
+       fun `local-reply notification has correct key and template`() {
+               loaders.templates += "/templates/notify/newReplyNotification.html" to "<% replies>".asTemplate()
+               val notification = injector.getInstance<ListNotification<PostReply>>(named("localReply"))
+               val replies = listOf(emptyPostReply("reply1"), emptyPostReply("reply2"))
+               replies.forEach(notification::add)
+               assertThat(notification.render(), equalTo(replies.toString()))
+       }
+
+       @Test
+       fun `local-reply notification is created as singleton`() {
+               injector.verifySingletonInstance<ListNotification<PostReply>>(named("localReply"))
+       }
+
+       @Test
+       fun `local-reply handler is created as singleton`() {
+               injector.verifySingletonInstance<LocalReplyHandler>()
+       }
+
+       @Test
        fun `new-version notification is created as singleton`() {
                injector.verifySingletonInstance<TemplateNotification>(named("newVersion"))
        }