feat: notification filtering

This commit is contained in:
rebelonion 2024-05-09 06:02:17 -05:00
parent be97229618
commit e1a865c973
10 changed files with 151 additions and 10 deletions

View file

@ -2,6 +2,7 @@ package ani.dantotsu.connections.anilist.api
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.util.Locale
enum class NotificationType(val value: String) {
ACTIVITY_MESSAGE("ACTIVITY_MESSAGE"),
@ -24,6 +25,19 @@ enum class NotificationType(val value: String) {
//custom
COMMENT_REPLY("COMMENT_REPLY"),
COMMENT_WARNING("COMMENT_WARNING"),
DANTOTSU_UPDATE("DANTOTSU_UPDATE");
fun toFormattedString(): String {
return this.value.replace("_", " ").lowercase(Locale.ROOT)
.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.ROOT) else it.toString() }
}
companion object {
fun String.fromFormattedString(): String {
return this.replace(" ", "_").uppercase(Locale.ROOT)
}
}
}
@Serializable

View file

@ -64,7 +64,7 @@ class CommentNotificationTask : Task {
val type: CommentNotificationWorker.NotificationType = when (it.type) {
1 -> CommentNotificationWorker.NotificationType.COMMENT_REPLY
2 -> CommentNotificationWorker.NotificationType.COMMENT_WARNING
3 -> CommentNotificationWorker.NotificationType.APP_GLOBAL
3 -> CommentNotificationWorker.NotificationType.DANTOTSU_UPDATE
420 -> CommentNotificationWorker.NotificationType.NO_NOTIFICATION
else -> CommentNotificationWorker.NotificationType.UNKNOWN
}
@ -76,6 +76,7 @@ class CommentNotificationTask : Task {
val commentStore = CommentStore(
title,
message,
CommentNotificationWorker.NotificationType.COMMENT_WARNING,
it.mediaId,
it.commentId
)
@ -101,6 +102,7 @@ class CommentNotificationTask : Task {
val commentStore = CommentStore(
title,
message,
CommentNotificationWorker.NotificationType.COMMENT_REPLY,
it.mediaId,
it.commentId
)
@ -118,13 +120,14 @@ class CommentNotificationTask : Task {
)
}
CommentNotificationWorker.NotificationType.APP_GLOBAL -> {
CommentNotificationWorker.NotificationType.DANTOTSU_UPDATE -> {
val title = "Update from Dantotsu"
val message = it.content ?: "New feature available"
val commentStore = CommentStore(
title,
message,
CommentNotificationWorker.NotificationType.DANTOTSU_UPDATE,
null,
null
)
@ -132,7 +135,7 @@ class CommentNotificationTask : Task {
createNotification(
context,
CommentNotificationWorker.NotificationType.APP_GLOBAL,
CommentNotificationWorker.NotificationType.DANTOTSU_UPDATE,
message,
title,
0,
@ -265,7 +268,7 @@ class CommentNotificationTask : Task {
builder.build()
}
CommentNotificationWorker.NotificationType.APP_GLOBAL -> {
CommentNotificationWorker.NotificationType.DANTOTSU_UPDATE -> {
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}

View file

@ -27,7 +27,7 @@ class CommentNotificationWorker(appContext: Context, workerParams: WorkerParamet
enum class NotificationType(val id: String) {
COMMENT_REPLY(Notifications.CHANNEL_COMMENTS),
COMMENT_WARNING(Notifications.CHANNEL_COMMENT_WARING),
APP_GLOBAL(Notifications.CHANNEL_APP_GLOBAL),
DANTOTSU_UPDATE(Notifications.CHANNEL_APP_GLOBAL),
NO_NOTIFICATION("no_notification"),
UNKNOWN("unknown")
}

View file

@ -3,11 +3,11 @@ package ani.dantotsu.notifications.comment
import kotlinx.serialization.Serializable
@Suppress("INAPPROPRIATE_CONST_NAME")
@Serializable
data class CommentStore(
val title: String,
val content: String,
val type: CommentNotificationWorker.NotificationType,
val mediaId: Int? = null,
val commentId: Int? = null,
val time: Long = System.currentTimeMillis(),
@ -15,6 +15,6 @@ data class CommentStore(
companion object {
@Suppress("INAPPROPRIATE_CONST_NAME")
private const val serialVersionUID = 1L
private const val serialVersionUID = 2L
}
}

View file

@ -43,6 +43,7 @@ class FollowActivity : AppCompatActivity() {
setContentView(binding.root)
val layoutType = PrefManager.getVal<Int>(PrefName.FollowerLayout)
selected = getSelected(layoutType)
binding.followFilterButton.visibility = View.GONE
binding.followerGrid.alpha = 0.33f
binding.followerList.alpha = 0.33f
selected(selected)

View file

@ -84,6 +84,14 @@ class ActivityItemBuilder {
NotificationType.COMMENT_REPLY -> {
notification.context ?: "You should not see this"
}
NotificationType.COMMENT_WARNING -> {
notification.context ?: "You should not see this"
}
NotificationType.DANTOTSU_UPDATE -> {
notification.context ?: "You should not see this"
}
}
}

View file

@ -3,8 +3,13 @@ package ani.dantotsu.profile.activity
import android.annotation.SuppressLint
import android.content.Intent
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MotionEvent
import android.view.ViewGroup
import android.widget.CheckBox
import android.widget.ImageButton
import android.widget.LinearLayout
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
@ -14,6 +19,9 @@ import androidx.recyclerview.widget.LinearLayoutManager
import ani.dantotsu.R
import ani.dantotsu.connections.anilist.Anilist
import ani.dantotsu.connections.anilist.api.Notification
import ani.dantotsu.connections.anilist.api.NotificationType
import ani.dantotsu.connections.anilist.api.NotificationType.Companion.fromFormattedString
import ani.dantotsu.currContext
import ani.dantotsu.databinding.ActivityFollowBinding
import ani.dantotsu.initActivity
import ani.dantotsu.media.MediaDetailsActivity
@ -34,6 +42,7 @@ class NotificationActivity : AppCompatActivity() {
private lateinit var binding: ActivityFollowBinding
private var adapter: GroupieAdapter = GroupieAdapter()
private var notificationList: List<Notification> = emptyList()
val filters = ArrayList<String>()
private var currentPage: Int = 1
private var hasNextPage: Boolean = true
@ -60,6 +69,75 @@ class NotificationActivity : AppCompatActivity() {
onBackPressedDispatcher.onBackPressed()
}
binding.listProgressBar.visibility = ViewGroup.VISIBLE
binding.followFilterButton.setOnClickListener {
val dialogView = LayoutInflater.from(currContext()).inflate(R.layout.custom_dialog_layout, null)
val checkboxContainer = dialogView.findViewById<LinearLayout>(R.id.checkboxContainer)
val tickAllButton = dialogView.findViewById<ImageButton>(R.id.toggleButton)
fun getToggleImageResource(container: ViewGroup): Int {
var allChecked = true
var allUnchecked = true
for (i in 0 until container.childCount) {
val checkBox = container.getChildAt(i) as CheckBox
if (!checkBox.isChecked) {
allChecked = false
} else {
allUnchecked = false
}
}
return when {
allChecked -> R.drawable.untick_all_boxes
allUnchecked -> R.drawable.tick_all_boxes
else -> R.drawable.invert_all_boxes
}
}
NotificationType.entries.forEach { notificationType ->
val checkBox = CheckBox(currContext())
checkBox.text = notificationType.toFormattedString()
checkBox.isChecked = !filters.contains(notificationType.value.fromFormattedString())
checkBox.setOnCheckedChangeListener { _, isChecked ->
if (isChecked) {
filters.remove(notificationType.value.fromFormattedString())
} else {
filters.add(notificationType.value.fromFormattedString())
}
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
}
checkboxContainer.addView(checkBox)
}
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
tickAllButton.setOnClickListener {
for (i in 0 until checkboxContainer.childCount) {
val checkBox = checkboxContainer.getChildAt(i) as CheckBox
checkBox.isChecked = !checkBox.isChecked
}
tickAllButton.setImageResource(getToggleImageResource(checkboxContainer))
}
val alertD = AlertDialog.Builder(this, R.style.MyPopup)
alertD.setTitle("Filter")
alertD.setView(dialogView)
alertD.setPositiveButton("OK") { _, _ ->
currentPage = 1
hasNextPage = true
adapter.clear()
adapter.addAll(notificationList.filter { notification ->
!filters.contains(notification.notificationType)
}.map {
NotificationItem(
it,
::onNotificationClick
)
})
loadPage(-1) {
binding.followRefresh.visibility = ViewGroup.GONE
}
}
alertD.setNegativeButton("Cancel") { _, _ -> }
val dialog = alertD.show()
dialog.window?.setDimAmount(0.8f)
}
val activityId = intent.getIntExtra("activityId", -1)
lifecycleScope.launch {
loadPage(activityId) {
@ -119,10 +197,10 @@ class NotificationActivity : AppCompatActivity() {
) ?: listOf()
commentStore.forEach {
val notification = Notification(
"COMMENT_REPLY",
it.type.toString(),
System.currentTimeMillis().toInt(),
commentId = it.commentId,
notificationType = "COMMENT_REPLY",
notificationType = it.type.toString(),
mediaId = it.mediaId,
context = it.title + "\n" + it.content,
createdAt = (it.time / 1000L).toInt(),
@ -133,7 +211,9 @@ class NotificationActivity : AppCompatActivity() {
}
notificationList += newNotifications
adapter.addAll(newNotifications.map {
adapter.addAll(newNotifications.filter { notification ->
!filters.contains(notification.notificationType)
}.map {
NotificationItem(
it,
::onNotificationClick

View file

@ -315,6 +315,23 @@ class NotificationItem(
}
}
}
NotificationType.COMMENT_WARNING -> {
image(user = true, commentNotification = true)
if (notification.commentId != null && notification.mediaId != null) {
binding.notificationBannerImage.setOnClickListener {
clickCallback(
notification.mediaId,
notification.commentId,
NotificationClickType.COMMENT
)
}
}
}
NotificationType.DANTOTSU_UPDATE -> {
image(user = true)
}
}
}

View file

@ -397,6 +397,14 @@ object PrefManager {
} else {
default
}
} catch (e: java.io.InvalidClassException) {
try {
getPrefLocation(location).edit().remove(key).apply()
default
} catch (e: Exception) {
Logger.log(e)
default
}
} catch (e: Exception) {
Logger.log(e)
default

View file

@ -50,6 +50,16 @@
android:textSize="18sp"
tools:text="Follow" />
<ImageView
android:id="@+id/followFilterButton"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_marginEnd="8dp"
android:layout_gravity="end|center_vertical"
android:contentDescription="@string/menu"
android:src="@drawable/ic_round_filter_alt_24"
app:tint="?attr/colorOnBackground" />
<androidx.cardview.widget.CardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"