Improve background works notifications
This commit is contained in:
@@ -11,8 +11,10 @@ import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onCompletion
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.transform
|
||||
import kotlinx.coroutines.flow.transformLatest
|
||||
import org.koitharu.kotatsu.R
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
fun <T> Flow<T>.onFirst(action: suspend (T) -> Unit): Flow<T> {
|
||||
var isFirstCall = true
|
||||
@@ -37,6 +39,14 @@ fun <T> Flow<T>.onEachWhile(action: suspend (T) -> Boolean): Flow<T> {
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> Flow<T>.onEachIndexed(action: suspend (index: Int, T) -> Unit): Flow<T> {
|
||||
val counter = AtomicInteger(0)
|
||||
return transform { value ->
|
||||
action(counter.getAndIncrement(), value)
|
||||
return@transform emit(value)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun <T, R> Flow<List<T>>.mapItems(crossinline transform: (T) -> R): Flow<List<R>> {
|
||||
return map { list -> list.map(transform) }
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.reader.ui.ReaderActivity.IntentBuilder
|
||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.settings.work.PeriodicWorkScheduler
|
||||
import org.koitharu.kotatsu.suggestions.domain.MangaSuggestion
|
||||
import org.koitharu.kotatsu.suggestions.domain.SuggestionRepository
|
||||
@@ -76,6 +77,7 @@ import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import kotlin.math.pow
|
||||
import kotlin.random.Random
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@HiltWorker
|
||||
class SuggestionsWorker @AssistedInject constructor(
|
||||
@@ -86,6 +88,7 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
private val historyRepository: HistoryRepository,
|
||||
private val favouritesRepository: FavouritesRepository,
|
||||
private val appSettings: AppSettings,
|
||||
private val workManager: WorkManager,
|
||||
private val mangaRepositoryFactory: MangaRepository.Factory,
|
||||
private val sourcesRepository: MangaSourcesRepository,
|
||||
) : CoroutineWorker(appContext, params) {
|
||||
@@ -116,6 +119,19 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
|
||||
val notification = NotificationCompat.Builder(applicationContext, WORKER_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setContentIntent(
|
||||
PendingIntentCompat.getActivity(
|
||||
applicationContext,
|
||||
0,
|
||||
SettingsActivity.newSuggestionsSettingsIntent(applicationContext),
|
||||
0,
|
||||
false,
|
||||
),
|
||||
).addAction(
|
||||
materialR.drawable.material_ic_clear_black_24dp,
|
||||
applicationContext.getString(android.R.string.cancel),
|
||||
workManager.createCancelPendingIntent(id),
|
||||
)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setDefaults(0)
|
||||
@@ -123,7 +139,13 @@ class SuggestionsWorker @AssistedInject constructor(
|
||||
.setSilent(true)
|
||||
.setProgress(0, 0, true)
|
||||
.setSmallIcon(android.R.drawable.stat_notify_sync)
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED)
|
||||
.setForegroundServiceBehavior(
|
||||
if (TAG_ONESHOT in tags) {
|
||||
NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE
|
||||
} else {
|
||||
NotificationCompat.FOREGROUND_SERVICE_DEFERRED
|
||||
},
|
||||
)
|
||||
.build()
|
||||
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
|
||||
@@ -39,7 +39,6 @@ import kotlinx.coroutines.NonCancellable
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.channelFlow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.toList
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
@@ -54,6 +53,7 @@ import org.koitharu.kotatsu.core.logs.TrackerLogger
|
||||
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||
import org.koitharu.kotatsu.core.util.ext.awaitUniqueWorkInfoByName
|
||||
import org.koitharu.kotatsu.core.util.ext.checkNotificationPermission
|
||||
import org.koitharu.kotatsu.core.util.ext.onEachIndexed
|
||||
import org.koitharu.kotatsu.core.util.ext.toBitmapOrNull
|
||||
import org.koitharu.kotatsu.core.util.ext.trySetForeground
|
||||
import org.koitharu.kotatsu.details.ui.DetailsActivity
|
||||
@@ -61,11 +61,13 @@ import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.runCatchingCancellable
|
||||
import org.koitharu.kotatsu.settings.SettingsActivity
|
||||
import org.koitharu.kotatsu.settings.work.PeriodicWorkScheduler
|
||||
import org.koitharu.kotatsu.tracker.domain.Tracker
|
||||
import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.inject.Inject
|
||||
import com.google.android.material.R as materialR
|
||||
|
||||
@HiltWorker
|
||||
class TrackWorker @AssistedInject constructor(
|
||||
@@ -74,6 +76,7 @@ class TrackWorker @AssistedInject constructor(
|
||||
private val coil: ImageLoader,
|
||||
private val settings: AppSettings,
|
||||
private val tracker: Tracker,
|
||||
private val workManager: WorkManager,
|
||||
@TrackerLogger private val logger: FileLogger,
|
||||
) : CoroutineWorker(context, workerParams) {
|
||||
|
||||
@@ -164,7 +167,10 @@ class TrackWorker @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
}.onEach {
|
||||
}.onEachIndexed { index, it ->
|
||||
if (applicationContext.checkNotificationPermission()) {
|
||||
notificationManager.notify(WORKER_NOTIFICATION_ID, createWorkerNotification(tracks.size, index + 1))
|
||||
}
|
||||
when (it) {
|
||||
is MangaUpdates.Failure -> {
|
||||
val e = it.error
|
||||
@@ -254,12 +260,11 @@ class TrackWorker @AssistedInject constructor(
|
||||
}
|
||||
|
||||
override suspend fun getForegroundInfo(): ForegroundInfo {
|
||||
val title = applicationContext.getString(R.string.check_for_new_chapters)
|
||||
val channel = NotificationChannelCompat.Builder(
|
||||
WORKER_CHANNEL_ID,
|
||||
NotificationManagerCompat.IMPORTANCE_LOW
|
||||
NotificationManagerCompat.IMPORTANCE_LOW,
|
||||
)
|
||||
.setName(title)
|
||||
.setName(applicationContext.getString(R.string.check_for_new_chapters))
|
||||
.setShowBadge(false)
|
||||
.setVibrationEnabled(false)
|
||||
.setSound(null, null)
|
||||
@@ -267,28 +272,56 @@ class TrackWorker @AssistedInject constructor(
|
||||
.build()
|
||||
notificationManager.createNotificationChannel(channel)
|
||||
|
||||
val notification = NotificationCompat.Builder(applicationContext, WORKER_CHANNEL_ID)
|
||||
.setContentTitle(title)
|
||||
.setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
.setDefaults(0)
|
||||
.setOngoing(false)
|
||||
.setSilent(true)
|
||||
.setProgress(0, 0, true)
|
||||
.setSmallIcon(android.R.drawable.stat_notify_sync)
|
||||
.setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED)
|
||||
.build()
|
||||
val notification = createWorkerNotification(0, 0)
|
||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ForegroundInfo(
|
||||
WORKER_NOTIFICATION_ID,
|
||||
notification,
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC
|
||||
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC,
|
||||
)
|
||||
} else {
|
||||
ForegroundInfo(WORKER_NOTIFICATION_ID, notification)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createWorkerNotification(max: Int, progress: Int) = NotificationCompat.Builder(
|
||||
applicationContext,
|
||||
WORKER_CHANNEL_ID,
|
||||
).apply {
|
||||
setContentTitle(applicationContext.getString(R.string.check_for_new_chapters))
|
||||
setPriority(NotificationCompat.PRIORITY_MIN)
|
||||
setCategory(NotificationCompat.CATEGORY_SERVICE)
|
||||
setDefaults(0)
|
||||
setOngoing(false)
|
||||
setSilent(true)
|
||||
setContentIntent(
|
||||
PendingIntentCompat.getActivity(
|
||||
applicationContext,
|
||||
0,
|
||||
SettingsActivity.newTrackerSettingsIntent(applicationContext),
|
||||
0,
|
||||
false,
|
||||
),
|
||||
)
|
||||
addAction(
|
||||
materialR.drawable.material_ic_clear_black_24dp,
|
||||
applicationContext.getString(android.R.string.cancel),
|
||||
workManager.createCancelPendingIntent(id),
|
||||
)
|
||||
if (max > 0) {
|
||||
setSubText(applicationContext.getString(R.string.fraction_pattern, progress, max))
|
||||
}
|
||||
setProgress(max, progress, max == 0)
|
||||
setSmallIcon(android.R.drawable.stat_notify_sync)
|
||||
setForegroundServiceBehavior(
|
||||
if (TAG_ONESHOT in tags) {
|
||||
NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE
|
||||
} else {
|
||||
NotificationCompat.FOREGROUND_SERVICE_DEFERRED
|
||||
},
|
||||
)
|
||||
}.build()
|
||||
|
||||
private suspend fun setRetryIds(ids: Set<Long>) = runInterruptible(Dispatchers.IO) {
|
||||
val prefs = applicationContext.getSharedPreferences(TAG, Context.MODE_PRIVATE)
|
||||
prefs.edit(commit = true) {
|
||||
|
||||
@@ -588,4 +588,5 @@
|
||||
<string name="default_webtoon_zoom_out">Default webtoon zoom out</string>
|
||||
<string name="fullscreen_mode">Fullscreen mode</string>
|
||||
<string name="reader_fullscreen_summary">Hide system status and navigation bars</string>
|
||||
<string name="fraction_pattern">%1$d/%2$d</string>
|
||||
</resources>
|
||||
|
||||
Reference in New Issue
Block a user