♻️ Extract interface for list notification filter
[Sone.git] / src / main / kotlin / net / pterodactylus / sone / notify / DefaultListNotificationFilter.kt
1 /*
2  * Sone - DefaultListNotificationFilter.kt - Copyright © 2010–2020 David Roden
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 package net.pterodactylus.sone.notify
18
19 import net.pterodactylus.sone.data.Post
20 import net.pterodactylus.sone.data.PostReply
21 import net.pterodactylus.sone.data.Sone
22 import net.pterodactylus.sone.utils.ifTrue
23 import net.pterodactylus.util.notify.Notification
24 import javax.inject.Inject
25 import javax.inject.Singleton
26
27 /**
28  * Filter for [ListNotification]s.
29  */
30 @Singleton
31 class DefaultListNotificationFilter @Inject constructor(private val postVisibilityFilter: PostVisibilityFilter, private val replyVisibilityFilter: ReplyVisibilityFilter) : ListNotificationFilter {
32
33         /**
34          * Filters new-post and new-reply notifications in the given list of
35          * notifications. If `currentSone` is `null`, new-post and
36          * new-reply notifications are removed completely. If `currentSone` is
37          * not `null`, only posts that are posted by a friend Sone or the Sone
38          * itself, and replies that are replies to posts of friend Sones or the Sone
39          * itself will be retained in the notifications.
40          *
41          * @param notifications
42          * The notifications to filter
43          * @param currentSone
44          * The current Sone, or `null` if not logged in
45          * @return The filtered notifications
46          */
47         override fun filterNotifications(notifications: Collection<Notification>, currentSone: Sone?) =
48                         notifications.mapNotNull { it.filtered(currentSone) }
49
50         @Suppress("UNCHECKED_CAST")
51         private fun Notification.filtered(currentSone: Sone?): Notification? = when {
52                 isNewSoneNotification -> {
53                         takeIf { currentSone == null || currentSone.options.isShowNewSoneNotifications }
54                 }
55                 isNewPostNotification -> {
56                         (currentSone != null && currentSone.options.isShowNewPostNotifications).ifTrue {
57                                 (this as ListNotification<Post>).filterNotification { postVisibilityFilter.isPostVisible(currentSone, it) }
58                         }
59                 }
60                 isNewReplyNotification -> {
61                         (currentSone != null && currentSone.options.isShowNewReplyNotifications).ifTrue {
62                                 (this as ListNotification<PostReply>).filterNotification { replyVisibilityFilter.isReplyVisible(currentSone, it) }
63                         }
64                 }
65                 isMentionNotification -> {
66                         (this as ListNotification<Post>).filterNotification { postVisibilityFilter.isPostVisible(currentSone, it) }
67                 }
68                 else -> this
69         }
70
71 }
72
73 /**
74  * Filters the elements of this list notification.
75  *
76  * @param filter The filter for the notification’s elements
77  * @return A list notification containing the filtered elements, or `null`
78  * if the notification does not have any elements after filtering
79  */
80 private fun <T> ListNotification<T>.filterNotification(filter: (T) -> Boolean) =
81                 elements.filter(filter).let { filteredElements ->
82                         when (filteredElements.size) {
83                                 0 -> null
84                                 elements.size -> this
85                                 else -> ListNotification(this).apply {
86                                         setElements(filteredElements)
87                                         setLastUpdateTime(lastUpdatedTime)
88                                 }
89                         }
90                 }