feat: subscriptions in notifications

This commit is contained in:
rebelonion 2024-05-17 10:11:42 -05:00
parent 6c1176a182
commit df2867c7db
9 changed files with 105 additions and 19 deletions

View file

@ -26,7 +26,8 @@ enum class NotificationType(val value: String) {
//custom //custom
COMMENT_REPLY("COMMENT_REPLY"), COMMENT_REPLY("COMMENT_REPLY"),
COMMENT_WARNING("COMMENT_WARNING"), COMMENT_WARNING("COMMENT_WARNING"),
DANTOTSU_UPDATE("DANTOTSU_UPDATE"); DANTOTSU_UPDATE("DANTOTSU_UPDATE"),
SUBSCRIPTION("SUBSCRIPTION");
fun toFormattedString(): String { fun toFormattedString(): String {
return this.value.replace("_", " ").lowercase(Locale.ROOT) return this.value.replace("_", " ").lowercase(Locale.ROOT)

View file

@ -188,7 +188,7 @@ class CommentNotificationTask : Task {
null null
) ?: listOf() ) ?: listOf()
val newStore = notificationStore.toMutableList() val newStore = notificationStore.toMutableList()
if (newStore.size > 10) { if (newStore.size > 30) {
newStore.remove(newStore.minByOrNull { it.time }) newStore.remove(newStore.minByOrNull { it.time })
} }
if (newStore.any { it.content == notification.content }) { if (newStore.any { it.content == notification.content }) {

View file

@ -13,8 +13,6 @@ data class CommentStore(
val time: Long = System.currentTimeMillis(), val time: Long = System.currentTimeMillis(),
) : java.io.Serializable { ) : java.io.Serializable {
companion object { companion object {
@Suppress("INAPPROPRIATE_CONST_NAME")
private const val serialVersionUID = 2L private const val serialVersionUID = 2L
} }
} }

View file

@ -118,6 +118,15 @@ class SubscriptionNotificationTask : Task {
if (ep != null) ep.number + " " + context.getString(R.string.just_released) to null if (ep != null) ep.number + " " + context.getString(R.string.just_released) to null
else null else null
} ?: return@map } ?: return@map
addSubscriptionToStore(
SubscriptionStore(
media.name,
text.first,
media.id
)
)
PrefManager.setVal(PrefName.UnreadCommentNotifications,
PrefManager.getVal<Int>(PrefName.UnreadCommentNotifications) + 1)
val notification = createNotification( val notification = createNotification(
context.applicationContext, context.applicationContext,
media, media,
@ -219,4 +228,17 @@ class SubscriptionNotificationTask : Task {
} }
) )
} }
private fun addSubscriptionToStore(notification: SubscriptionStore) {
val notificationStore = PrefManager.getNullableVal<List<SubscriptionStore>>(
PrefName.SubscriptionNotificationStore,
null
) ?: listOf()
val newStore = notificationStore.toMutableList()
if (newStore.size >= 100) {
newStore.remove(newStore.minByOrNull { it.time })
}
newStore.add(notification)
PrefManager.setVal(PrefName.SubscriptionNotificationStore, newStore)
}
} }

View file

@ -0,0 +1,16 @@
package ani.dantotsu.notifications.subscription
import kotlinx.serialization.Serializable
@Serializable
data class SubscriptionStore(
val title: String,
val content: String,
val mediaId: Int,
val type: String = "SUBSCRIPTION",
val time: Long = System.currentTimeMillis(),
) : java.io.Serializable {
companion object {
private const val serialVersionUID = 1L
}
}

View file

@ -92,6 +92,10 @@ class ActivityItemBuilder {
NotificationType.DANTOTSU_UPDATE -> { NotificationType.DANTOTSU_UPDATE -> {
notification.context ?: "You should not see this" notification.context ?: "You should not see this"
} }
NotificationType.SUBSCRIPTION -> {
notification.context ?: "You should not see this"
}
} }
} }

View file

@ -28,6 +28,7 @@ import ani.dantotsu.initActivity
import ani.dantotsu.media.MediaDetailsActivity import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.navBarHeight import ani.dantotsu.navBarHeight
import ani.dantotsu.notifications.comment.CommentStore import ani.dantotsu.notifications.comment.CommentStore
import ani.dantotsu.notifications.subscription.SubscriptionStore
import ani.dantotsu.profile.ProfileActivity import ani.dantotsu.profile.ProfileActivity
import ani.dantotsu.settings.saving.PrefManager import ani.dantotsu.settings.saving.PrefManager
import ani.dantotsu.settings.saving.PrefName import ani.dantotsu.settings.saving.PrefName
@ -41,6 +42,8 @@ import kotlinx.coroutines.withContext
class NotificationActivity : AppCompatActivity() { class NotificationActivity : AppCompatActivity() {
private lateinit var binding: ActivityFollowBinding private lateinit var binding: ActivityFollowBinding
private lateinit var commentStore: List<CommentStore>
private lateinit var subscriptionStore: List<SubscriptionStore>
private var adapter: GroupieAdapter = GroupieAdapter() private var adapter: GroupieAdapter = GroupieAdapter()
private var notificationList: List<Notification> = emptyList() private var notificationList: List<Notification> = emptyList()
val filters = ArrayList<String>() val filters = ArrayList<String>()
@ -70,6 +73,15 @@ class NotificationActivity : AppCompatActivity() {
onBackPressedDispatcher.onBackPressed() onBackPressedDispatcher.onBackPressed()
} }
binding.listProgressBar.visibility = ViewGroup.VISIBLE binding.listProgressBar.visibility = ViewGroup.VISIBLE
commentStore = PrefManager.getNullableVal<List<CommentStore>>(
PrefName.CommentNotificationStore,
null
) ?: listOf()
subscriptionStore = PrefManager.getNullableVal<List<SubscriptionStore>>(
PrefName.SubscriptionNotificationStore,
null
) ?: listOf()
binding.followFilterButton.setOnClickListener { binding.followFilterButton.setOnClickListener {
val dialogView = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null) val dialogView = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
val checkboxContainer = dialogView.findViewById<LinearLayout>(R.id.checkboxContainer) val checkboxContainer = dialogView.findViewById<LinearLayout>(R.id.checkboxContainer)
@ -193,12 +205,12 @@ class NotificationActivity : AppCompatActivity() {
notifications notifications
}.toMutableList() }.toMutableList()
} }
if (activityId == -1 && currentPage == 1) { if (activityId == -1) {
val commentStore = PrefManager.getNullableVal<List<CommentStore>>( val furthestTime = newNotifications.minOfOrNull { it.createdAt } ?: 0
PrefName.CommentNotificationStore,
null
) ?: listOf()
commentStore.forEach { commentStore.forEach {
if ((it.time > furthestTime * 1000L || !hasNextPage) && notificationList.none { notification ->
notification.commentId == it.commentId && notification.createdAt == (it.time / 1000L).toInt()
}) {
val notification = Notification( val notification = Notification(
it.type.toString(), it.type.toString(),
System.currentTimeMillis().toInt(), System.currentTimeMillis().toInt(),
@ -210,6 +222,23 @@ class NotificationActivity : AppCompatActivity() {
) )
newNotifications += notification newNotifications += notification
} }
}
subscriptionStore.forEach {
if ((it.time > furthestTime * 1000L || !hasNextPage) && notificationList.none { notification ->
notification.mediaId == it.mediaId && notification.createdAt == (it.time / 1000L).toInt()
}) {
val notification = Notification(
it.type,
System.currentTimeMillis().toInt(),
commentId = it.mediaId,
mediaId = it.mediaId,
notificationType = it.type,
context = it.content,
createdAt = (it.time / 1000L).toInt(),
)
newNotifications += notification
}
}
newNotifications.sortByDescending { it.createdAt } newNotifications.sortByDescending { it.createdAt }
} }

View file

@ -332,6 +332,20 @@ class NotificationItem(
NotificationType.DANTOTSU_UPDATE -> { NotificationType.DANTOTSU_UPDATE -> {
image(user = true) image(user = true)
} }
NotificationType.SUBSCRIPTION -> {
image(user = true, commentNotification = true)
binding.notificationCoverUser.setOnClickListener {
clickCallback(
notification.mediaId ?: 0, null, NotificationClickType.MEDIA
)
}
binding.notificationBannerImage.setOnClickListener {
clickCallback(
notification.mediaId ?: 0, null, NotificationClickType.MEDIA
)
}
}
} }
} }

View file

@ -4,6 +4,7 @@ import android.graphics.Color
import ani.dantotsu.connections.comments.AuthResponse import ani.dantotsu.connections.comments.AuthResponse
import ani.dantotsu.connections.mal.MAL import ani.dantotsu.connections.mal.MAL
import ani.dantotsu.notifications.comment.CommentStore import ani.dantotsu.notifications.comment.CommentStore
import ani.dantotsu.notifications.subscription.SubscriptionStore
import ani.dantotsu.settings.saving.internal.Location import ani.dantotsu.settings.saving.internal.Location
import ani.dantotsu.settings.saving.internal.Pref import ani.dantotsu.settings.saving.internal.Pref
@ -185,6 +186,7 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
LogToFile(Pref(Location.Irrelevant, Boolean::class, false)), LogToFile(Pref(Location.Irrelevant, Boolean::class, false)),
RecentGlobalNotification(Pref(Location.Irrelevant, Int::class, 0)), RecentGlobalNotification(Pref(Location.Irrelevant, Int::class, 0)),
CommentNotificationStore(Pref(Location.Irrelevant, List::class, listOf<CommentStore>())), CommentNotificationStore(Pref(Location.Irrelevant, List::class, listOf<CommentStore>())),
SubscriptionNotificationStore(Pref(Location.Irrelevant, List::class, listOf<SubscriptionStore>())),
UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)), UnreadCommentNotifications(Pref(Location.Irrelevant, Int::class, 0)),
DownloadsDir(Pref(Location.Irrelevant, String::class, "")), DownloadsDir(Pref(Location.Irrelevant, String::class, "")),
RefreshStatus(Pref(Location.Irrelevant, Boolean::class, false)), RefreshStatus(Pref(Location.Irrelevant, Boolean::class, false)),