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.MultiDex
|
||||||
import androidx.multidex.MultiDexApplication
|
import androidx.multidex.MultiDexApplication
|
||||||
import androidx.work.Constraints
|
import androidx.work.Constraints
|
||||||
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.PeriodicWorkRequest
|
import androidx.work.PeriodicWorkRequest
|
||||||
import ani.dantotsu.aniyomi.anime.custom.AppModule
|
import ani.dantotsu.aniyomi.anime.custom.AppModule
|
||||||
import ani.dantotsu.aniyomi.anime.custom.PreferenceModule
|
import ani.dantotsu.aniyomi.anime.custom.PreferenceModule
|
||||||
import ani.dantotsu.connections.comments.CommentsAPI
|
import ani.dantotsu.connections.comments.CommentsAPI
|
||||||
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
|
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.others.DisabledReports
|
||||||
import ani.dantotsu.parsers.AnimeSources
|
import ani.dantotsu.parsers.AnimeSources
|
||||||
import ani.dantotsu.parsers.MangaSources
|
import ani.dantotsu.parsers.MangaSources
|
||||||
|
@ -34,7 +36,6 @@ import kotlinx.coroutines.launch
|
||||||
import logcat.AndroidLogcatLogger
|
import logcat.AndroidLogcatLogger
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import logcat.LogcatLogger
|
import logcat.LogcatLogger
|
||||||
import tachiyomi.core.util.system.logcat
|
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
|
||||||
|
@ -122,18 +123,51 @@ class App : MultiDexApplication() {
|
||||||
CommentsAPI.fetchAuthToken()
|
CommentsAPI.fetchAuthToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
startWorkers()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun startWorkers() {
|
||||||
val constraints = Constraints.Builder()
|
val constraints = Constraints.Builder()
|
||||||
.setRequiredNetworkType(androidx.work.NetworkType.CONNECTED)
|
.setRequiredNetworkType(androidx.work.NetworkType.CONNECTED)
|
||||||
.build()
|
.build()
|
||||||
val recurringWork = PeriodicWorkRequest.Builder(NotificationWorker::class.java,
|
|
||||||
15, java.util.concurrent.TimeUnit.MINUTES)
|
// CommentNotificationWorker
|
||||||
.setConstraints(constraints)
|
val commentInterval = CommentNotificationWorker.checkIntervals[PrefManager.getVal(PrefName.CommentNotificationInterval)]
|
||||||
.build()
|
if (commentInterval.toInt() != 0) {
|
||||||
androidx.work.WorkManager.getInstance(this).enqueueUniquePeriodicWork(
|
val recurringWork = PeriodicWorkRequest.Builder(CommentNotificationWorker::class.java,
|
||||||
NotificationWorker.WORK_NAME,
|
commentInterval, java.util.concurrent.TimeUnit.MINUTES)
|
||||||
androidx.work.ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
|
.setConstraints(constraints)
|
||||||
recurringWork
|
.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 } } } }"""
|
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>(
|
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
|
force = true
|
||||||
)
|
)
|
||||||
if (res != null) {
|
if (res != null) {
|
||||||
|
@ -1354,10 +1355,9 @@ Page(page:$page,perPage:50) {
|
||||||
val filter = if (userId != null) "userId:$userId,"
|
val filter = if (userId != null) "userId:$userId,"
|
||||||
else if (global) "isFollowing:false,type:TEXT,"
|
else if (global) "isFollowing:false,type:TEXT,"
|
||||||
else "isFollowing:true,type_not:MESSAGE,"
|
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}}}}}}"""
|
"""{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 {
|
companion object {
|
||||||
|
|
|
@ -699,7 +699,7 @@ class Query {
|
||||||
// // Activity reply query
|
// // Activity reply query
|
||||||
// val ActivityReply: ActivityReply?,
|
// val ActivityReply: ActivityReply?,
|
||||||
|
|
||||||
// // Comment query
|
// // CommentNotificationWorker query
|
||||||
// val ThreadComment: List<ThreadComment>?,
|
// val ThreadComment: List<ThreadComment>?,
|
||||||
|
|
||||||
// // Notification query
|
// // Notification query
|
||||||
|
|
|
@ -129,12 +129,12 @@ class CommentItem(val comment: Comment,
|
||||||
viewBinding.modBadge.visibility = if (comment.isMod == true) View.VISIBLE else View.GONE
|
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.adminBadge.visibility = if (comment.isAdmin == true) View.VISIBLE else View.GONE
|
||||||
viewBinding.commentDelete.setOnClickListener {
|
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())
|
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val success = CommentsAPI.deleteComment(comment.commentId)
|
val success = CommentsAPI.deleteComment(comment.commentId)
|
||||||
if (success) {
|
if (success) {
|
||||||
snackString("Comment Deleted")
|
snackString("CommentNotificationWorker Deleted")
|
||||||
parentSection.remove(this@CommentItem)
|
parentSection.remove(this@CommentItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,12 +152,12 @@ class CommentItem(val comment: Comment,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
viewBinding.commentReport.setOnClickListener {
|
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())
|
val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val success = CommentsAPI.reportComment(comment.commentId, comment.username, commentsFragment.mediaName, comment.userId)
|
val success = CommentsAPI.reportComment(comment.commentId, comment.username, commentsFragment.mediaName, comment.userId)
|
||||||
if (success) {
|
if (success) {
|
||||||
snackString("Comment Reported")
|
snackString("CommentNotificationWorker Reported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ class CommentsFragment : Fragment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
//adds additional comments to the section
|
//adds additional comments to the section
|
||||||
private suspend fun updateUIWithComment(comment: Comment) {
|
private suspend fun updateUIWithComment(comment: CommentNotificationWorker) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
section.add(
|
section.add(
|
||||||
CommentItem(
|
CommentItem(
|
||||||
|
@ -297,7 +297,7 @@ class CommentsFragment : Fragment() {
|
||||||
override fun afterTextChanged(s: android.text.Editable?) {
|
override fun afterTextChanged(s: android.text.Editable?) {
|
||||||
if (binding.commentInput.text.length > 300) {
|
if (binding.commentInput.text.length > 300) {
|
||||||
binding.commentInput.text.delete(300, binding.commentInput.text.length)
|
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() {
|
private fun processComment() {
|
||||||
val commentText = binding.commentInput.text.toString()
|
val commentText = binding.commentInput.text.toString()
|
||||||
if (commentText.isEmpty()) {
|
if (commentText.isEmpty()) {
|
||||||
snackString("Comment cannot be empty")
|
snackString("CommentNotificationWorker cannot be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,7 +662,7 @@ class CommentsFragment : Fragment() {
|
||||||
groups.forEach { item ->
|
groups.forEach { item ->
|
||||||
if (item is CommentItem && item.comment.commentId == commentWithInteraction?.comment?.commentId) {
|
if (item is CommentItem && item.comment.commentId == commentWithInteraction?.comment?.commentId) {
|
||||||
updateCommentItem(item, commentText)
|
updateCommentItem(item, commentText)
|
||||||
snackString("Comment edited")
|
snackString("CommentNotificationWorker edited")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,10 +24,9 @@ import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import java.util.Locale
|
|
||||||
|
|
||||||
|
|
||||||
class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
class CommentNotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||||
Worker(appContext, workerParams) {
|
Worker(appContext, workerParams) {
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
val scope = CoroutineScope(Dispatchers.IO)
|
val scope = CoroutineScope(Dispatchers.IO)
|
||||||
|
@ -62,7 +61,7 @@ class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||||
""
|
""
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
val title = "New Comment Reply"
|
val title = "New CommentNotificationWorker Reply"
|
||||||
val mediaName = names[it.mediaId]?.title ?: "Unknown"
|
val mediaName = names[it.mediaId]?.title ?: "Unknown"
|
||||||
val message = "${it.username} replied to your comment in $mediaName"
|
val message = "${it.username} replied to your comment in $mediaName"
|
||||||
createNotification(
|
createNotification(
|
||||||
|
@ -187,6 +186,7 @@ class NotificationWorker(appContext: Context, workerParams: WorkerParameters) :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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.animation.AnimationUtils
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
import android.widget.ArrayAdapter
|
import android.widget.ArrayAdapter
|
||||||
import android.widget.ImageView
|
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
@ -34,6 +33,7 @@ import ani.dantotsu.BuildConfig
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.Refresh
|
import ani.dantotsu.Refresh
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
|
import ani.dantotsu.connections.anilist.api.NotificationType
|
||||||
import ani.dantotsu.connections.discord.Discord
|
import ani.dantotsu.connections.discord.Discord
|
||||||
import ani.dantotsu.connections.mal.MAL
|
import ani.dantotsu.connections.mal.MAL
|
||||||
import ani.dantotsu.copyToClipboard
|
import ani.dantotsu.copyToClipboard
|
||||||
|
@ -47,6 +47,8 @@ import ani.dantotsu.initActivity
|
||||||
import ani.dantotsu.loadImage
|
import ani.dantotsu.loadImage
|
||||||
import ani.dantotsu.util.Logger
|
import ani.dantotsu.util.Logger
|
||||||
import ani.dantotsu.navBarHeight
|
import ani.dantotsu.navBarHeight
|
||||||
|
import ani.dantotsu.notifications.CommentNotificationWorker
|
||||||
|
import ani.dantotsu.notifications.anilist.AnilistNotificationWorker
|
||||||
import ani.dantotsu.openLinkInBrowser
|
import ani.dantotsu.openLinkInBrowser
|
||||||
import ani.dantotsu.others.AppUpdater
|
import ani.dantotsu.others.AppUpdater
|
||||||
import ani.dantotsu.others.CustomBottomDialog
|
import ani.dantotsu.others.CustomBottomDialog
|
||||||
|
@ -673,6 +675,75 @@ class SettingsActivity : AppCompatActivity(), SimpleDialog.OnDialogResultListene
|
||||||
true
|
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 =
|
binding.settingsNotificationsCheckingSubscriptions.isChecked =
|
||||||
PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
|
PrefManager.getVal(PrefName.SubscriptionCheckingNotifications)
|
||||||
binding.settingsNotificationsCheckingSubscriptions.setOnCheckedChangeListener { _, isChecked ->
|
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>())),
|
MangaSourcesOrder(Pref(Location.General, List::class, listOf<String>())),
|
||||||
MangaSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
MangaSearchHistory(Pref(Location.General, Set::class, setOf<String>())),
|
||||||
NovelSourcesOrder(Pref(Location.General, List::class, listOf<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
|
//User Interface
|
||||||
UseOLED(Pref(Location.UI, Boolean::class, false)),
|
UseOLED(Pref(Location.UI, Boolean::class, false)),
|
||||||
|
|
|
@ -53,6 +53,13 @@ object Notifications {
|
||||||
const val CHANNEL_COMMENT_WARING = "comment_warning_channel"
|
const val CHANNEL_COMMENT_WARING = "comment_warning_channel"
|
||||||
const val ID_COMMENT_REPLY = -801
|
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.
|
* Notification channel and ids used for app and extension updates.
|
||||||
|
@ -105,6 +112,9 @@ object Notifications {
|
||||||
buildNotificationChannelGroup(GROUP_COMMENTS) {
|
buildNotificationChannelGroup(GROUP_COMMENTS) {
|
||||||
setName("Comments")
|
setName("Comments")
|
||||||
},
|
},
|
||||||
|
buildNotificationChannelGroup(GROUP_ANILIST) {
|
||||||
|
setName("Anilist")
|
||||||
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -134,9 +144,13 @@ object Notifications {
|
||||||
setGroup(GROUP_COMMENTS)
|
setGroup(GROUP_COMMENTS)
|
||||||
},
|
},
|
||||||
buildNotificationChannel(CHANNEL_COMMENT_WARING, IMPORTANCE_HIGH) {
|
buildNotificationChannel(CHANNEL_COMMENT_WARING, IMPORTANCE_HIGH) {
|
||||||
setName("Comment Warnings")
|
setName("CommentNotificationWorker Warnings")
|
||||||
setGroup(GROUP_COMMENTS)
|
setGroup(GROUP_COMMENTS)
|
||||||
},
|
},
|
||||||
|
buildNotificationChannel(CHANNEL_ANILIST, IMPORTANCE_DEFAULT) {
|
||||||
|
setName("Anilist")
|
||||||
|
setGroup(GROUP_ANILIST)
|
||||||
|
},
|
||||||
buildNotificationChannel(CHANNEL_APP_UPDATE, IMPORTANCE_DEFAULT) {
|
buildNotificationChannel(CHANNEL_APP_UPDATE, IMPORTANCE_DEFAULT) {
|
||||||
setGroup(GROUP_APK_UPDATES)
|
setGroup(GROUP_APK_UPDATES)
|
||||||
setName("App Updates")
|
setName("App Updates")
|
||||||
|
|
|
@ -971,70 +971,6 @@
|
||||||
app:showText="false"
|
app:showText="false"
|
||||||
app:thumbTint="@color/button_switch_track" />
|
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>
|
||||||
|
|
||||||
<ani.dantotsu.others.Xpandable
|
<ani.dantotsu.others.Xpandable
|
||||||
|
@ -1440,6 +1376,81 @@
|
||||||
android:text="@string/subscriptions_info"
|
android:text="@string/subscriptions_info"
|
||||||
android:textSize="14sp" />
|
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
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
android:id="@+id/settingsNotificationsCheckingSubscriptions"
|
android:id="@+id/settingsNotificationsCheckingSubscriptions"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -1517,6 +1528,67 @@
|
||||||
app:drawableTint="?attr/colorPrimary"
|
app:drawableTint="?attr/colorPrimary"
|
||||||
app:showText="false"
|
app:showText="false"
|
||||||
app:thumbTint="@color/button_switch_track" />
|
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
|
<Button
|
||||||
android:id="@+id/settingsDev"
|
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="blur">Blur</string>
|
||||||
<string name="hide_scroll_bar">Hide Scroll Bar</string>
|
<string name="hide_scroll_bar">Hide Scroll Bar</string>
|
||||||
<string name="view_on_anilist">View on AniList</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>
|
</resources>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue