feat: anilist notifications (real)
This commit is contained in:
parent
19697f4f39
commit
4d2a08c258
12 changed files with 390 additions and 95 deletions
|
@ -7,12 +7,14 @@ import android.os.Bundle
|
|||
import androidx.multidex.MultiDex
|
||||
import androidx.multidex.MultiDexApplication
|
||||
import androidx.work.Constraints
|
||||
import androidx.work.OneTimeWorkRequest
|
||||
import androidx.work.PeriodicWorkRequest
|
||||
import ani.dantotsu.aniyomi.anime.custom.AppModule
|
||||
import ani.dantotsu.aniyomi.anime.custom.PreferenceModule
|
||||
import ani.dantotsu.connections.comments.CommentsAPI
|
||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
||||
import ani.dantotsu.notifications.NotificationWorker
|
||||
import ani.dantotsu.notifications.CommentNotificationWorker
|
||||
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
|
||||
import ani.dantotsu.others.DisabledReports
|
||||
import ani.dantotsu.parsers.AnimeSources
|
||||
import ani.dantotsu.parsers.MangaSources
|
||||
|
@ -34,7 +36,6 @@ import kotlinx.coroutines.launch
|
|||
import logcat.AndroidLogcatLogger
|
||||
import logcat.LogPriority
|
||||
import logcat.LogcatLogger
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
|
@ -122,18 +123,51 @@ class App : MultiDexApplication() {
|
|||
CommentsAPI.fetchAuthToken()
|
||||
}
|
||||
|
||||
startWorkers()
|
||||
}
|
||||
|
||||
private fun startWorkers() {
|
||||
val constraints = Constraints.Builder()
|
||||
.setRequiredNetworkType(androidx.work.NetworkType.CONNECTED)
|
||||
.build()
|
||||
val recurringWork = PeriodicWorkRequest.Builder(NotificationWorker::class.java,
|
||||
15, java.util.concurrent.TimeUnit.MINUTES)
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
androidx.work.WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
NotificationWorker.WORK_NAME,
|
||||
androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
recurringWork
|
||||
)
|
||||
|
||||
// CommentNotificationWorker
|
||||
val commentInterval = CommentNotificationWorker.checkIntervals[PrefManager.getVal(PrefName.CommentNotificationInterval)]
|
||||
if (commentInterval.toInt() != 0) {
|
||||
val recurringWork = PeriodicWorkRequest.Builder(CommentNotificationWorker::class.java,
|
||||
commentInterval, java.util.concurrent.TimeUnit.MINUTES)
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
androidx.work.WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
CommentNotificationWorker.WORK_NAME,
|
||||
androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
recurringWork
|
||||
)
|
||||
} else {
|
||||
androidx.work.WorkManager.getInstance(this).cancelUniqueWork(CommentNotificationWorker.WORK_NAME)
|
||||
//run once
|
||||
androidx.work.WorkManager.getInstance(this).enqueue(OneTimeWorkRequest.Companion.from(CommentNotificationWorker::class.java))
|
||||
}
|
||||
|
||||
// AnilistNotificationWorker
|
||||
val anilistInterval = AnilistNotificationWorker.checkIntervals[PrefManager.getVal(PrefName.AnilistNotificationInterval)]
|
||||
if (anilistInterval.toInt() != 0) {
|
||||
val recurringWork = PeriodicWorkRequest.Builder(
|
||||
AnilistNotificationWorker::class.java,
|
||||
anilistInterval, java.util.concurrent.TimeUnit.MINUTES)
|
||||
.setConstraints(constraints)
|
||||
.build()
|
||||
androidx.work.WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
||||
AnilistNotificationWorker.WORK_NAME,
|
||||
androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
||||
recurringWork
|
||||
)
|
||||
} else {
|
||||
androidx.work.WorkManager.getInstance(this).cancelUniqueWork(AnilistNotificationWorker.WORK_NAME)
|
||||
//run once
|
||||
androidx.work.WorkManager.getInstance(this).enqueue(OneTimeWorkRequest.Companion.from(AnilistNotificationWorker::class.java))
|
||||
}
|
||||
androidx.work.WorkManager.getInstance(this).cancelUniqueWork("ani.dantotsu.notifications.NotificationWorker")
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1339,9 +1339,10 @@ Page(page:$page,perPage:50) {
|
|||
return """MediaListCollection(userId: ${id}, type: $type, chunk:1,perChunk:25, sort: [SCORE_DESC,UPDATED_TIME_DESC]) { lists { entries{ media { id bannerImage } } } }"""
|
||||
}
|
||||
|
||||
suspend fun getNotifications(id: Int, page: Int = 1): NotificationResponse? {
|
||||
suspend fun getNotifications(id: Int, page: Int = 1, resetNotification: Boolean = true): NotificationResponse? {
|
||||
val reset = if (resetNotification) "true" else "false"
|
||||
val res = executeQuery<NotificationResponse>(
|
||||
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){notifications(resetNotificationCount:true){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""",
|
||||
"""{User(id:$id){unreadNotificationCount}Page(page:$page,perPage:$ITEMS_PER_PAGE){notifications(resetNotificationCount:$reset){__typename...on AiringNotification{id,type,animeId,episode,contexts,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}},}...on FollowingNotification{id,userId,type,context,createdAt,user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMessageNotification{id,userId,type,activityId,context,createdAt,message{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityMentionNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplySubscribedNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ActivityReplyLikeNotification{id,userId,type,activityId,context,createdAt,activity{__typename}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentMentionNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentReplyNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentSubscribedNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadCommentLikeNotification{id,userId,type,commentId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on ThreadLikeNotification{id,userId,type,threadId,context,createdAt,thread{id}comment{id}user{id,name,bannerImage,avatar{medium,large,}}}...on RelatedMediaAdditionNotification{id,type,context,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDataChangeNotification{id,type,mediaId,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaMergeNotification{id,type,mediaId,deletedMediaTitles,context,reason,createdAt,media{id,title{romaji,english,native,userPreferred}bannerImage,coverImage{medium,large}}}...on MediaDeletionNotification{id,type,deletedMediaTitle,context,reason,createdAt,}}}}""",
|
||||
force = true
|
||||
)
|
||||
if (res != null) {
|
||||
|
@ -1354,10 +1355,9 @@ Page(page:$page,perPage:50) {
|
|||
val filter = if (userId != null) "userId:$userId,"
|
||||
else if (global) "isFollowing:false,type:TEXT,"
|
||||
else "isFollowing:true,type_not:MESSAGE,"
|
||||
val res = executeQuery<FeedResponse>(
|
||||
return executeQuery<FeedResponse>(
|
||||
"""{Page(page:$page,perPage:$ITEMS_PER_PAGE){activities(${filter}sort:ID_DESC){__typename ... on TextActivity{id userId type replyCount text(asHtml:true)siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on ListActivity{id userId type replyCount status progress siteUrl isLocked isSubscribed likeCount isLiked isPinned createdAt user{id name bannerImage avatar{medium large}}media{id title{english romaji native userPreferred}bannerImage coverImage{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}... on MessageActivity{id recipientId messengerId type replyCount likeCount message(asHtml:true)isLocked isSubscribed isLiked isPrivate siteUrl createdAt recipient{id name bannerImage avatar{medium large}}messenger{id name bannerImage avatar{medium large}}replies{id userId activityId text(asHtml:true)likeCount isLiked createdAt user{id name bannerImage avatar{medium large}}likes{id name bannerImage avatar{medium large}}}likes{id name bannerImage avatar{medium large}}}}}}"""
|
||||
)
|
||||
return res
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
|
|
@ -699,7 +699,7 @@ class Query {
|
|||
// // Activity reply query
|
||||
// val ActivityReply: ActivityReply?,
|
||||
|
||||
// // Comment query
|
||||
// // CommentNotificationWorker query
|
||||
// val ThreadComment: List<ThreadComment>?,
|
||||
|
||||
// // Notification query
|
||||
|
|
|
@ -129,12 +129,12 @@ class CommentItem(val comment: Comment,
|
|||
viewBinding.modBadge.visibility = if (comment.isMod == true) View.VISIBLE else View.GONE
|
||||
viewBinding.adminBadge.visibility = if (comment.isAdmin == true) View.VISIBLE else View.GONE
|
||||
viewBinding.commentDelete.setOnClickListener {
|
||||
dialogBuilder("Delete Comment", "Are you sure you want to delete this comment?") {
|
||||
dialogBuilder("Delete CommentNotificationWorker", "Are you sure you want to delete this comment?") {
|
||||
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
scope.launch {
|
||||
val success = CommentsAPI.deleteComment(comment.commentId)
|
||||
if (success) {
|
||||
snackString("Comment Deleted")
|
||||
snackString("CommentNotificationWorker Deleted")
|
||||
parentSection.remove(this@CommentItem)
|
||||
}
|
||||
}
|
||||
|
@ -152,12 +152,12 @@ class CommentItem(val comment: Comment,
|
|||
}
|
||||
}
|
||||
viewBinding.commentReport.setOnClickListener {
|
||||
dialogBuilder("Report Comment", "Only report comments that violate the rules. Are you sure you want to report this comment?") {
|
||||
dialogBuilder("Report CommentNotificationWorker", "Only report comments that violate the rules. Are you sure you want to report this comment?") {
|
||||
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||
scope.launch {
|
||||
val success = CommentsAPI.reportComment(comment.commentId, comment.username, commentsFragment.mediaName, comment.userId)
|
||||
if (success) {
|
||||
snackString("Comment Reported")
|
||||
snackString("CommentNotificationWorker Reported")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -270,7 +270,7 @@ class CommentsFragment : Fragment() {
|
|||
}
|
||||
|
||||
//adds additional comments to the section
|
||||
private suspend fun updateUIWithComment(comment: Comment) {
|
||||
private suspend fun updateUIWithComment(comment: CommentNotificationWorker) {
|
||||
withContext(Dispatchers.Main) {
|
||||
section.add(
|
||||
CommentItem(
|
||||
|
@ -297,7 +297,7 @@ class CommentsFragment : Fragment() {
|
|||
override fun afterTextChanged(s: android.text.Editable?) {
|
||||
if (binding.commentInput.text.length > 300) {
|
||||
binding.commentInput.text.delete(300, binding.commentInput.text.length)
|
||||
snackString("Comment cannot be longer than 300 characters")
|
||||
snackString("CommentNotificationWorker cannot be longer than 300 characters")
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@ -626,7 +626,7 @@ class CommentsFragment : Fragment() {
|
|||
private fun processComment() {
|
||||
val commentText = binding.commentInput.text.toString()
|
||||
if (commentText.isEmpty()) {
|
||||
snackString("Comment cannot be empty")
|
||||
snackString("CommentNotificationWorker cannot be empty")
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -662,7 +662,7 @@ class CommentsFragment : Fragment() {
|
|||
groups.forEach { item ->
|
||||
if (item is CommentItem && item.comment.commentId == commentWithInteraction?.comment?.commentId) {
|
||||
updateCommentItem(item, commentText)
|
||||
snackString("Comment edited")
|
||||
snackString("CommentNotificationWorker edited")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,10 +24,9 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.OkHttpClient
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||
class CommentNotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||
Worker(appContext, workerParams) {
|
||||
override fun doWork(): Result {
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
|
@ -62,7 +61,7 @@ class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
|||
""
|
||||
)
|
||||
} else {
|
||||
val title = "New Comment Reply"
|
||||
val title = "New CommentNotificationWorker Reply"
|
||||
val mediaName = names[it.mediaId]?.title ?: "Unknown"
|
||||
val message = "${it.username} replied to your comment in $mediaName"
|
||||
createNotification(
|
||||
|
@ -187,6 +186,7 @@ class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
|||
}
|
||||
|
||||
companion object {
|
||||
const val WORK_NAME = "ani.dantotsu.notifications.NotificationWorker"
|
||||
val checkIntervals = arrayOf(0L, 720, 1440)
|
||||
const val WORK_NAME = "ani.dantotsu.notifications.CommentNotificationWorker"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package ani.dantotsu.notifications.anilist
|
||||
|
||||
import android.Manifest
|
||||
import android.app.PendingIntent
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.work.Worker
|
||||
import androidx.work.WorkerParameters
|
||||
import ani.dantotsu.R
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.profile.activity.ActivityItemBuilder
|
||||
import ani.dantotsu.profile.activity.FeedActivity
|
||||
import ani.dantotsu.settings.saving.PrefManager
|
||||
import ani.dantotsu.settings.saving.PrefName
|
||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class AnilistNotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||
Worker(appContext, workerParams) {
|
||||
|
||||
override fun doWork(): Result {
|
||||
val scope = CoroutineScope(Dispatchers.IO)
|
||||
scope.launch {
|
||||
PrefManager.init(applicationContext) //make sure prefs are initialized
|
||||
val userId = PrefManager.getVal<String>(PrefName.AnilistUserId)
|
||||
if (userId.isNotEmpty()) {
|
||||
Anilist.getSavedToken()
|
||||
val res = Anilist.query.getNotifications(userId.toInt(), resetNotification = false)
|
||||
val unreadNotificationCount = res?.data?.user?.unreadNotificationCount ?: 0
|
||||
if (unreadNotificationCount > 0) {
|
||||
val unreadNotifications = res?.data?.page?.notifications?.sortedBy { it.id }
|
||||
?.takeLast(unreadNotificationCount)
|
||||
val lastId = PrefManager.getVal<Int>(PrefName.LastAnilistNotificationId)
|
||||
val newNotifications = unreadNotifications?.filter { it.id > lastId }
|
||||
val filteredTypes =
|
||||
PrefManager.getVal<Set<String>>(PrefName.AnilistFilteredTypes)
|
||||
newNotifications?.forEach {
|
||||
if (!filteredTypes.contains(it.notificationType)) {
|
||||
val content = ActivityItemBuilder.getContent(it)
|
||||
val notification = createNotification(applicationContext, content)
|
||||
if (ActivityCompat.checkSelfPermission(
|
||||
applicationContext,
|
||||
Manifest.permission.POST_NOTIFICATIONS
|
||||
) == PackageManager.PERMISSION_GRANTED
|
||||
) {
|
||||
NotificationManagerCompat.from(applicationContext)
|
||||
.notify(
|
||||
Notifications.CHANNEL_ANILIST,
|
||||
System.currentTimeMillis().toInt(),
|
||||
notification
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (newNotifications?.isNotEmpty() == true) {
|
||||
PrefManager.setVal(PrefName.LastAnilistNotificationId, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Result.success()
|
||||
}
|
||||
|
||||
|
||||
private fun createNotification(
|
||||
context: Context,
|
||||
content: String
|
||||
): android.app.Notification {
|
||||
val title = "New Anilist Notification"
|
||||
val intent = Intent(applicationContext, FeedActivity::class.java)
|
||||
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||
val pendingIntent = PendingIntent.getActivity(
|
||||
applicationContext,
|
||||
0,
|
||||
intent,
|
||||
PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
return NotificationCompat.Builder(context, Notifications.CHANNEL_ANILIST)
|
||||
.setSmallIcon(R.drawable.notification_icon)
|
||||
.setContentTitle(title)
|
||||
.setContentText(content)
|
||||
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
|
||||
.setContentIntent(pendingIntent)
|
||||
.setAutoCancel(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
companion object {
|
||||
val checkIntervals = arrayOf(0L, 30, 60, 120, 240, 360, 720, 1440)
|
||||
const val WORK_NAME = "ani.dantotsu.notifications.anilist.AnilistNotificationWorker"
|
||||
}
|
||||
}
|
|
@ -17,7 +17,6 @@ import android.view.ViewGroup
|
|||
import android.view.animation.AnimationUtils
|
||||
import android.view.inputmethod.EditorInfo
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import android.widget.Toast
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
|
@ -34,6 +33,7 @@ import ani.dantotsu.BuildConfig
|
|||
import ani.dantotsu.R
|
||||
import ani.dantotsu.Refresh
|
||||
import ani.dantotsu.connections.anilist.Anilist
|
||||
import ani.dantotsu.connections.anilist.api.NotificationType
|
||||
import ani.dantotsu.connections.discord.Discord
|
||||
import ani.dantotsu.connections.mal.MAL
|
||||
import ani.dantotsu.copyToClipboard
|
||||
|
@ -47,6 +47,8 @@ import ani.dantotsu.initActivity
|
|||
import ani.dantotsu.loadImage
|
||||
import ani.dantotsu.util.Logger
|
||||
import ani.dantotsu.navBarHeight
|
||||
import ani.dantotsu.notifications.CommentNotificationWorker
|
||||
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
|
||||
import ani.dantotsu.openLinkInBrowser
|
||||
import ani.dantotsu.others.AppUpdater
|
||||
import ani.dantotsu.others.CustomBottomDialog
|
||||
|
@ -673,6 +675,75 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
|||
true
|
||||
}
|
||||
|
||||
val aTimeNames = AnilistNotificationWorker.checkIntervals.map { it.toInt() }
|
||||
val aItems = aTimeNames.map {
|
||||
val mins = it % 60
|
||||
val hours = it / 60
|
||||
if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
|
||||
else getString(R.string.do_not_update)
|
||||
}
|
||||
binding.settingsAnilistSubscriptionsTime.text =
|
||||
getString(R.string.anilist_notifications_checking_time, aItems[PrefManager.getVal(PrefName.AnilistNotificationInterval)])
|
||||
binding.settingsAnilistSubscriptionsTime.setOnClickListener {
|
||||
|
||||
val selected = PrefManager.getVal<Int>(PrefName.AnilistNotificationInterval)
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(R.string.subscriptions_checking_time)
|
||||
.setSingleChoiceItems(aItems.toTypedArray(), selected) { dialog, i ->
|
||||
PrefManager.setVal(PrefName.AnilistNotificationInterval, i)
|
||||
binding.settingsAnilistSubscriptionsTime.text =
|
||||
getString(R.string.anilist_notifications_checking_time, aItems[i])
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
binding.settingsAnilistNotifications.setOnClickListener {
|
||||
val types = NotificationType.entries.map { it.name }
|
||||
val filteredTypes = PrefManager.getVal<Set<String>>(PrefName.AnilistFilteredTypes).toMutableSet()
|
||||
val selected = types.map { filteredTypes.contains(it) }.toBooleanArray()
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(R.string.anilist_notification_filters)
|
||||
.setMultiChoiceItems(types.toTypedArray(), selected) { _, which, isChecked ->
|
||||
val type = types[which]
|
||||
if (isChecked) {
|
||||
filteredTypes.add(type)
|
||||
} else {
|
||||
filteredTypes.remove(type)
|
||||
}
|
||||
PrefManager.setVal(PrefName.AnilistFilteredTypes, filteredTypes)
|
||||
}
|
||||
.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
val cTimeNames = CommentNotificationWorker.checkIntervals.map { it.toInt() }
|
||||
val cItems = cTimeNames.map {
|
||||
val mins = it % 60
|
||||
val hours = it / 60
|
||||
if (it > 0) "${if (hours > 0) "$hours hrs " else ""}${if (mins > 0) "$mins mins" else ""}"
|
||||
else getString(R.string.do_not_update)
|
||||
}
|
||||
binding.settingsCommentSubscriptionsTime.text =
|
||||
getString(R.string.comment_notification_checking_time, cItems[PrefManager.getVal(PrefName.CommentNotificationInterval)])
|
||||
binding.settingsCommentSubscriptionsTime.setOnClickListener {
|
||||
val selected = PrefManager.getVal<Int>(PrefName.CommentNotificationInterval)
|
||||
val dialog = AlertDialog.Builder(this, R.style.MyPopup)
|
||||
.setTitle(R.string.subscriptions_checking_time)
|
||||
.setSingleChoiceItems(cItems.toTypedArray(), selected) { dialog, i ->
|
||||
PrefManager.setVal(PrefName.CommentNotificationInterval, i)
|
||||
binding.settingsCommentSubscriptionsTime.text =
|
||||
getString(R.string.comment_notification_checking_time, cItems[i])
|
||||
dialog.dismiss()
|
||||
}
|
||||
.create()
|
||||
dialog.window?.setDimAmount(0.8f)
|
||||
dialog.show()
|
||||
}
|
||||
|
||||
binding.settingsNotificationsCheckingSubscriptions.isChecked =
|
||||
PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
|
||||
binding.settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
|
||||
|
|
|
@ -33,7 +33,10 @@ enum class PrefName(val data: Pref) { //TODO: Split this into multiple files
|
|||
MangaSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
||||
MangaSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
||||
NovelSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
||||
NotificationInterval(Pref(Location.General, Int::class, 0)),
|
||||
CommentNotificationInterval(Pref(Location.General, Int::class, 0)),
|
||||
AnilistNotificationInterval(Pref(Location.General, Int::class, 3)),
|
||||
LastAnilistNotificationId(Pref(Location.General, Int::class, 0)),
|
||||
AnilistFilteredTypes(Pref(Location.General, Set::class, setOf<String>())),
|
||||
|
||||
//User Interface
|
||||
UseOLED(Pref(Location.UI, Boolean::class, false)),
|
||||
|
|
|
@ -53,6 +53,13 @@ object Notifications {
|
|||
const val CHANNEL_COMMENT_WARING = "comment_warning_channel"
|
||||
const val ID_COMMENT_REPLY = -801
|
||||
|
||||
/**
|
||||
* Notification channel and ids used for anilist updates.
|
||||
*/
|
||||
const val GROUP_ANILIST = "group_anilist"
|
||||
const val CHANNEL_ANILIST = "anilist_channel"
|
||||
const val ID_ANILIST = -901
|
||||
|
||||
|
||||
/**
|
||||
* Notification channel and ids used for app and extension updates.
|
||||
|
@ -105,6 +112,9 @@ object Notifications {
|
|||
buildNotificationChannelGroup(GROUP_COMMENTS) {
|
||||
setName("Comments")
|
||||
},
|
||||
buildNotificationChannelGroup(GROUP_ANILIST) {
|
||||
setName("Anilist")
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
|
@ -134,9 +144,13 @@ object Notifications {
|
|||
setGroup(GROUP_COMMENTS)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_COMMENT_WARING, IMPORTANCE_HIGH) {
|
||||
setName("Comment Warnings")
|
||||
setName("CommentNotificationWorker Warnings")
|
||||
setGroup(GROUP_COMMENTS)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_ANILIST, IMPORTANCE_DEFAULT) {
|
||||
setName("Anilist")
|
||||
setGroup(GROUP_ANILIST)
|
||||
},
|
||||
buildNotificationChannel(CHANNEL_APP_UPDATE, IMPORTANCE_DEFAULT) {
|
||||
setGroup(GROUP_APK_UPDATES)
|
||||
setName("App Updates")
|
||||
|
|
|
@ -971,70 +971,6 @@
|
|||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsShareUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_round_search_24"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/share_username_in_crash_reports"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsLogToFile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_round_edit_note_24"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/log_to_file"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:alpha="0.58"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/logging_warning" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/settingsShareLog"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_round_share_24"
|
||||
android:padding="16dp" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ani.dantotsu.others.Xpandable>
|
||||
|
||||
<ani.dantotsu.others.Xpandable
|
||||
|
@ -1440,6 +1376,81 @@
|
|||
android:text="@string/subscriptions_info"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginEnd="-16dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsAnilistNotifications"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-31dp"
|
||||
android:layout_marginEnd="-31dp"
|
||||
android:background="@drawable/ui_bg"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:paddingStart="31dp"
|
||||
android:paddingEnd="31dp"
|
||||
android:text="@string/anilist_notification_filters"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_anilist"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp"
|
||||
app:iconTint="?attr/colorPrimary" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsAnilistSubscriptionsTime"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-11dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:text="@string/anilist_notifications_checking_time"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_notifications_none_24"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsCommentSubscriptionsTime"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:layout_marginStart="-11dp"
|
||||
android:layout_marginTop="8dp"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:insetTop="0dp"
|
||||
android:insetBottom="0dp"
|
||||
android:text="@string/comment_notification_checking_time"
|
||||
android:textAlignment="viewStart"
|
||||
android:textAllCaps="false"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:icon="@drawable/ic_round_notifications_none_24"
|
||||
app:iconPadding="16dp"
|
||||
app:iconSize="24dp" />
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginStart="-16dp"
|
||||
android:layout_marginEnd="-16dp"
|
||||
android:background="?android:attr/listDivider" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsNotificationsCheckingSubscriptions"
|
||||
android:layout_width="match_parent"
|
||||
|
@ -1517,6 +1528,67 @@
|
|||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsShareUsername"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_round_search_24"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/share_username_in_crash_reports"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<com.google.android.material.materialswitch.MaterialSwitch
|
||||
android:id="@+id/settingsLogToFile"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:drawableStart="@drawable/ic_round_edit_note_24"
|
||||
android:drawablePadding="16dp"
|
||||
android:elegantTextHeight="true"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:minHeight="64dp"
|
||||
android:text="@string/log_to_file"
|
||||
android:textAlignment="viewStart"
|
||||
android:textColor="?attr/colorOnBackground"
|
||||
app:cornerRadius="0dp"
|
||||
app:drawableTint="?attr/colorPrimary"
|
||||
app:showText="false"
|
||||
app:thumbTint="@color/button_switch_track" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:alpha="0.58"
|
||||
android:fontFamily="@font/poppins_bold"
|
||||
android:text="@string/logging_warning" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/settingsShareLog"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:src="@drawable/ic_round_share_24"
|
||||
android:padding="16dp" />
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/settingsDev"
|
||||
|
|
|
@ -700,4 +700,7 @@ Non quae tempore quo provident laudantium qui illo dolor vel quia dolor et exerc
|
|||
<string name="blur">Blur</string>
|
||||
<string name="hide_scroll_bar">Hide Scroll Bar</string>
|
||||
<string name="view_on_anilist">View on AniList</string>
|
||||
<string name="anilist_notification_filters">Anilist Notification Filters</string>
|
||||
<string name="anilist_notifications_checking_time">Anilist notifications update frequency : %1$s</string>
|
||||
<string name="comment_notification_checking_time">Comment notifications update frequency : %1$s</string>
|
||||
</resources>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue