Update suggestions after config changes #831

This commit is contained in:
Koitharu
2024-03-30 08:47:08 +02:00
parent 41f64b2e36
commit a15197f69d
7 changed files with 43 additions and 24 deletions

View File

@@ -20,7 +20,7 @@ class CaptchaNotifier(
) : EventListener { ) : EventListener {
fun notify(exception: CloudFlareProtectedException) { fun notify(exception: CloudFlareProtectedException) {
if (!context.checkNotificationPermission()) { if (!context.checkNotificationPermission(CHANNEL_ID)) {
return return
} }
val manager = NotificationManagerCompat.from(context) val manager = NotificationManagerCompat.from(context)

View File

@@ -14,7 +14,7 @@ import android.content.ContextWrapper
import android.content.OperationApplicationException import android.content.OperationApplicationException
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.SyncResult import android.content.SyncResult
import android.content.pm.PackageManager import android.content.pm.PackageManager.PERMISSION_GRANTED
import android.content.pm.ResolveInfo import android.content.pm.ResolveInfo
import android.database.SQLException import android.database.SQLException
import android.graphics.Bitmap import android.graphics.Bitmap
@@ -216,10 +216,19 @@ fun Context.findActivity(): Activity? = when (this) {
else -> null else -> null
} }
fun Context.checkNotificationPermission(): Boolean = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { fun Context.checkNotificationPermission(channelId: String?): Boolean {
ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED val hasPermission = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
} else { ContextCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PERMISSION_GRANTED
NotificationManagerCompat.from(this).areNotificationsEnabled() } else {
NotificationManagerCompat.from(this).areNotificationsEnabled()
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPermission && channelId != null) {
val channel = NotificationManagerCompat.from(this).getNotificationChannel(channelId)
if (channel != null && channel.importance == NotificationManagerCompat.IMPORTANCE_NONE) {
return false
}
}
return hasPermission
} }
@WorkerThread @WorkerThread

View File

@@ -50,7 +50,7 @@ class ImportWorker @AssistedInject constructor(
val result = runCatchingCancellable { val result = runCatchingCancellable {
importer.import(uri).manga importer.import(uri).manga
} }
if (applicationContext.checkNotificationPermission()) { if (applicationContext.checkNotificationPermission(CHANNEL_ID)) {
val notification = buildNotification(result) val notification = buildNotification(result)
notificationManager.notify(uri.hashCode(), notification) notificationManager.notify(uri.hashCode(), notification)
} }

View File

@@ -4,6 +4,7 @@ import android.content.SharedPreferences
import android.os.Bundle import android.os.Bundle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
@@ -15,8 +16,7 @@ import org.koitharu.kotatsu.suggestions.ui.SuggestionsWorker
import javax.inject.Inject import javax.inject.Inject
@AndroidEntryPoint @AndroidEntryPoint
class SuggestionsSettingsFragment : class SuggestionsSettingsFragment : BasePreferenceFragment(R.string.suggestions),
BasePreferenceFragment(R.string.suggestions),
SharedPreferences.OnSharedPreferenceChangeListener { SharedPreferences.OnSharedPreferenceChangeListener {
@Inject @Inject
@@ -48,16 +48,17 @@ class SuggestionsSettingsFragment :
} }
override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) {
if (key == AppSettings.KEY_SUGGESTIONS && settings.isSuggestionsEnabled) { if (settings.isSuggestionsEnabled && (key == AppSettings.KEY_SUGGESTIONS
onSuggestionsEnabled() || key == AppSettings.KEY_SUGGESTIONS_EXCLUDE_TAGS
|| key == AppSettings.KEY_SUGGESTIONS_EXCLUDE_NSFW)
) {
updateSuggestions()
} }
} }
private fun onSuggestionsEnabled() { private fun updateSuggestions() {
lifecycleScope.launch { lifecycleScope.launch(Dispatchers.Default) {
if (repository.isEmpty()) { suggestionsScheduler.startNow()
suggestionsScheduler.startNow()
}
} }
} }
} }

View File

@@ -64,6 +64,8 @@ class SuggestionsViewModel @Inject constructor(
override fun onRetry() = Unit override fun onRetry() = Unit
fun updateSuggestions() { fun updateSuggestions() {
suggestionsScheduler.startNow() launchJob(Dispatchers.Default) {
suggestionsScheduler.startNow()
}
} }
} }

View File

@@ -1,11 +1,12 @@
package org.koitharu.kotatsu.suggestions.ui package org.koitharu.kotatsu.suggestions.ui
import android.annotation.SuppressLint import android.Manifest
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import android.content.pm.ServiceInfo import android.content.pm.ServiceInfo
import android.os.Build import android.os.Build
import androidx.annotation.FloatRange import androidx.annotation.FloatRange
import androidx.annotation.RequiresPermission
import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
@@ -50,6 +51,7 @@ import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.core.util.ext.almostEquals import org.koitharu.kotatsu.core.util.ext.almostEquals
import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.core.util.ext.asArrayList
import org.koitharu.kotatsu.core.util.ext.awaitUniqueWorkInfoByName import org.koitharu.kotatsu.core.util.ext.awaitUniqueWorkInfoByName
import org.koitharu.kotatsu.core.util.ext.awaitWorkInfosByTag
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
import org.koitharu.kotatsu.core.util.ext.flatten import org.koitharu.kotatsu.core.util.ext.flatten
import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug import org.koitharu.kotatsu.core.util.ext.printStackTraceDebug
@@ -189,7 +191,9 @@ class SuggestionsWorker @AssistedInject constructor(
.sortedBy { it.relevance } .sortedBy { it.relevance }
.take(MAX_RESULTS) .take(MAX_RESULTS)
suggestionRepository.replace(suggestions) suggestionRepository.replace(suggestions)
if (appSettings.isSuggestionsNotificationAvailable && applicationContext.checkNotificationPermission()) { if (appSettings.isSuggestionsNotificationAvailable
&& applicationContext.checkNotificationPermission(MANGA_CHANNEL_ID)
) {
for (i in 0..3) { for (i in 0..3) {
try { try {
val manga = suggestions[Random.nextInt(0, suggestions.size / 3)] val manga = suggestions[Random.nextInt(0, suggestions.size / 3)]
@@ -252,7 +256,7 @@ class SuggestionsWorker @AssistedInject constructor(
e.printStackTraceDebug() e.printStackTraceDebug()
}.getOrDefault(emptyList()) }.getOrDefault(emptyList())
@SuppressLint("MissingPermission") @RequiresPermission(Manifest.permission.POST_NOTIFICATIONS)
private suspend fun showNotification(manga: Manga) { private suspend fun showNotification(manga: Manga) {
val channel = NotificationChannelCompat.Builder(MANGA_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_DEFAULT) val channel = NotificationChannelCompat.Builder(MANGA_CHANNEL_ID, NotificationManagerCompat.IMPORTANCE_DEFAULT)
.setName(applicationContext.getString(R.string.suggestions)) .setName(applicationContext.getString(R.string.suggestions))
@@ -393,7 +397,10 @@ class SuggestionsWorker @AssistedInject constructor(
.any { !it.state.isFinished } .any { !it.state.isFinished }
} }
fun startNow() { suspend fun startNow() {
if (workManager.awaitWorkInfosByTag(TAG_ONESHOT).any { !it.state.isFinished }) {
return
}
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
.build() .build()
@@ -402,7 +409,7 @@ class SuggestionsWorker @AssistedInject constructor(
.addTag(TAG_ONESHOT) .addTag(TAG_ONESHOT)
.setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST)
.build() .build()
workManager.enqueue(request) workManager.enqueue(request).await()
} }
private fun createConstraints() = Constraints.Builder() private fun createConstraints() = Constraints.Builder()

View File

@@ -168,7 +168,7 @@ class TrackWorker @AssistedInject constructor(
} }
} }
}.onEachIndexed { index, it -> }.onEachIndexed { index, it ->
if (applicationContext.checkNotificationPermission()) { if (applicationContext.checkNotificationPermission(WORKER_CHANNEL_ID)) {
notificationManager.notify(WORKER_NOTIFICATION_ID, createWorkerNotification(tracks.size, index + 1)) notificationManager.notify(WORKER_NOTIFICATION_ID, createWorkerNotification(tracks.size, index + 1))
} }
when (it) { when (it) {
@@ -197,7 +197,7 @@ class TrackWorker @AssistedInject constructor(
channelId: String?, channelId: String?,
newChapters: List<MangaChapter>, newChapters: List<MangaChapter>,
) { ) {
if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission()) { if (newChapters.isEmpty() || channelId == null || !applicationContext.checkNotificationPermission(channelId)) {
return return
} }
val id = manga.url.hashCode() val id = manga.url.hashCode()