diff --git a/.idea/gradle.xml b/.idea/gradle.xml index 6e5389ed9..a0de2a152 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -7,7 +7,7 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 8f80d9a29..05755e6f7 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,19 +67,19 @@ android { afterEvaluate { compileDebugKotlin { kotlinOptions { - freeCompilerArgs += ['-opt-in=kotlin.RequiresOptIn'] + freeCompilerArgs += ['-opt-in=org.koitharu.kotatsu.parsers.InternalParsersApi'] } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) - implementation('com.github.nv95:kotatsu-parsers:ab87a50e9b') { + implementation('com.github.nv95:kotatsu-parsers:0ed35a4b21') { exclude group: 'org.json', module: 'json' } implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.2' - implementation 'androidx.core:core-ktx:1.8.0-rc02' + implementation 'androidx.core:core-ktx:1.8.0' implementation 'androidx.activity:activity-ktx:1.5.0-rc01' implementation 'androidx.fragment:fragment-ktx:1.5.0-rc01' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.0-rc01' diff --git a/app/src/debug/java/org/koitharu/kotatsu/core/parser/DummyParser.kt b/app/src/debug/java/org/koitharu/kotatsu/core/parser/DummyParser.kt index 479ada3ec..7c6096a24 100644 --- a/app/src/debug/java/org/koitharu/kotatsu/core/parser/DummyParser.kt +++ b/app/src/debug/java/org/koitharu/kotatsu/core/parser/DummyParser.kt @@ -1,16 +1,14 @@ package org.koitharu.kotatsu.core.parser -import java.util.* -import org.koitharu.kotatsu.parsers.InternalParsersApi import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.* +import java.util.* /** * This parser is just for parser development, it should not be used in releases */ -@OptIn(InternalParsersApi::class) class DummyParser(override val context: MangaLoaderContext) : MangaParser(MangaSource.DUMMY) { override val configKeyDomain: ConfigKey.Domain diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt index 8ddc723d5..496a5539b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TrackLogsDao.kt @@ -21,7 +21,7 @@ interface TrackLogsDao { suspend fun removeAll(mangaId: Long) @Query("DELETE FROM track_logs WHERE manga_id NOT IN (SELECT manga_id FROM tracks)") - suspend fun cleanup() + suspend fun gc() @Query("SELECT COUNT(*) FROM track_logs") suspend fun count(): Int diff --git a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt index f8352524b..c0fb163a7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/db/dao/TracksDao.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.core.db.dao import androidx.room.* import org.koitharu.kotatsu.core.db.entity.TrackEntity - @Dao abstract class TracksDao { @@ -32,7 +31,7 @@ abstract class TracksDao { abstract suspend fun delete(mangaId: Long) @Query("DELETE FROM tracks WHERE manga_id NOT IN (SELECT manga_id FROM history UNION SELECT manga_id FROM favourites)") - abstract suspend fun cleanup() + abstract suspend fun gc() @Transaction open suspend fun upsert(entity: TrackEntity) { diff --git a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt index 353ff1ca6..e8c554107 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/exceptions/CompositeException.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.core.exceptions import org.koitharu.kotatsu.parsers.util.mapNotNullToSet -class CompositeException(val errors: Collection) : Exception( - message = errors.mapNotNullToSet { it.message }.joinToString() -) \ No newline at end of file +class CompositeException(val errors: Collection) : Exception() { + + override val message: String = errors.mapNotNullToSet { it.message }.joinToString() +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaTracking.kt b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaTracking.kt index 09af6176c..50814dff0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/model/MangaTracking.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/model/MangaTracking.kt @@ -1,14 +1,41 @@ package org.koitharu.kotatsu.core.model -import android.os.Parcelable import java.util.* -import kotlinx.parcelize.Parcelize import org.koitharu.kotatsu.parsers.model.Manga -data class MangaTracking( +class MangaTracking( val manga: Manga, val knownChaptersCount: Int, val lastChapterId: Long, val lastNotifiedChapterId: Long, - val lastCheck: Date? -) \ No newline at end of file + val lastCheck: Date?, +) { + + fun isEmpty(): Boolean { + return knownChaptersCount <= 0 || lastChapterId == 0L + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as MangaTracking + + if (manga != other.manga) return false + if (knownChaptersCount != other.knownChaptersCount) return false + if (lastChapterId != other.lastChapterId) return false + if (lastNotifiedChapterId != other.lastNotifiedChapterId) return false + if (lastCheck != other.lastCheck) return false + + return true + } + + override fun hashCode(): Int { + var result = manga.hashCode() + result = 31 * result + knownChaptersCount + result = 31 * result + lastChapterId.hashCode() + result = 31 * result + lastNotifiedChapterId.hashCode() + result = 31 * result + (lastCheck?.hashCode() ?: 0) + return result + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt index 812fc9e81..90c84d5a8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/MangaRepository.kt @@ -1,11 +1,11 @@ package org.koitharu.kotatsu.core.parser +import java.lang.ref.WeakReference +import java.util.* import org.koin.core.component.KoinComponent import org.koin.core.component.get import org.koitharu.kotatsu.local.domain.LocalMangaRepository import org.koitharu.kotatsu.parsers.model.* -import java.lang.ref.WeakReference -import java.util.* interface MangaRepository { @@ -13,7 +13,7 @@ interface MangaRepository { val sortOrders: Set - suspend fun getList(offset: Int, query: String?): List + suspend fun getList(offset: Int, query: String): List suspend fun getList(offset: Int, tags: Set?, sortOrder: SortOrder?): List diff --git a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt index 358bd2645..999ecb09b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/core/parser/RemoteMangaRepository.kt @@ -20,7 +20,7 @@ class RemoteMangaRepository(private val parser: MangaParser) : MangaRepository { getConfig().defaultSortOrder = value } - override suspend fun getList(offset: Int, query: String?): List { + override suspend fun getList(offset: Int, query: String): List { return parser.getList(offset, query) } diff --git a/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt b/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt index 6eef24c86..0fb9b63d3 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/domain/LocalMangaRepository.kt @@ -7,6 +7,12 @@ import androidx.annotation.WorkerThread import androidx.collection.ArraySet import androidx.core.net.toFile import androidx.core.net.toUri +import java.io.File +import java.io.IOException +import java.util.* +import java.util.zip.ZipEntry +import java.util.zip.ZipFile +import kotlin.coroutines.CoroutineContext import kotlinx.coroutines.* import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.parser.MangaRepository @@ -22,12 +28,6 @@ import org.koitharu.kotatsu.utils.ext.deleteAwait import org.koitharu.kotatsu.utils.ext.longHashCode import org.koitharu.kotatsu.utils.ext.readText import org.koitharu.kotatsu.utils.ext.resolveName -import java.io.File -import java.io.IOException -import java.util.* -import java.util.zip.ZipEntry -import java.util.zip.ZipFile -import kotlin.coroutines.CoroutineContext private const val MAX_PARALLELISM = 4 @@ -37,12 +37,12 @@ class LocalMangaRepository(private val storageManager: LocalStorageManager) : Ma private val filenameFilter = CbzFilter() private val locks = CompositeMutex() - override suspend fun getList(offset: Int, query: String?): List { + override suspend fun getList(offset: Int, query: String): List { if (offset > 0) { return emptyList() } val list = getRawList() - if (!query.isNullOrEmpty()) { + if (query.isNotEmpty()) { list.retainAll { x -> x.title.contains(query, ignoreCase = true) || x.altTitle?.contains(query, ignoreCase = true) == true diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/TrackerModule.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/TrackerModule.kt index 975e96d66..d1b44e64d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/TrackerModule.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/TrackerModule.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.tracker import org.koin.android.ext.koin.androidContext import org.koin.androidx.viewmodel.dsl.viewModel import org.koin.dsl.module +import org.koitharu.kotatsu.tracker.domain.Tracker import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.tracker.ui.FeedViewModel import org.koitharu.kotatsu.tracker.work.TrackerNotificationChannels @@ -13,5 +14,7 @@ val trackerModule factory { TrackingRepository(get()) } factory { TrackerNotificationChannels(androidContext(), get()) } + factory { Tracker(get()) } + viewModel { FeedViewModel(get()) } } \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt new file mode 100644 index 000000000..425cabcdf --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/Tracker.kt @@ -0,0 +1,132 @@ +package org.koitharu.kotatsu.tracker.domain + +import org.koitharu.kotatsu.core.model.MangaTracking +import org.koitharu.kotatsu.core.parser.MangaRepository +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.tracker.domain.model.MangaUpdates + +class Tracker( + private val repository: TrackingRepository, +) { + + suspend fun fetchUpdates(track: MangaTracking, commit: Boolean): MangaUpdates { + val repo = MangaRepository(track.manga.source) + val details = repo.getDetails(track.manga) + val chapters = details.chapters.orEmpty() + if (track.isEmpty()) { + // first check or manga was empty on last check + if (commit) { + repository.storeTrackResult( + mangaId = track.manga.id, + knownChaptersCount = chapters.size, + lastChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = 0L, + newChapters = emptyList(), + saveTrackLog = false, + ) + } + return MangaUpdates( + manga = details, + newChapters = emptyList(), + ) + } + val newChapters = details.getNewChapters(track.lastChapterId) + if (newChapters.isEmpty()) { + if (commit) { + repository.storeTrackResult( + mangaId = track.manga.id, + knownChaptersCount = chapters.size, + lastChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = 0L, + newChapters = emptyList(), + saveTrackLog = false, + ) + } + return MangaUpdates( + manga = details, + newChapters = emptyList(), + ) + } + return when { + + // the same chapters count + chapters.size == track.knownChaptersCount -> { + if (chapters.lastOrNull()?.id == track.lastChapterId) { + // manga was not updated. skip + MangaUpdates( + manga = details, + newChapters = emptyList(), + ) + } else { + // number of chapters still the same, bu last chapter changed. + // maybe some chapters are removed. we need to find last known chapter + val knownChapter = chapters.indexOfLast { it.id == track.lastChapterId } + if (knownChapter == -1) { + // confuse. reset anything + if (commit) { + repository.storeTrackResult( + mangaId = track.manga.id, + knownChaptersCount = chapters.size, + lastChapterId = chapters.lastOrNull()?.id ?: 0L, + previousTrackChapterId = 0L, + newChapters = emptyList(), + saveTrackLog = false, + ) + } + MangaUpdates( + manga = details, + newChapters = emptyList(), + ) + } else { + val newChapters = chapters.takeLast(chapters.size - knownChapter + 1) + if (commit) { + repository.storeTrackResult( + mangaId = track.manga.id, + knownChaptersCount = knownChapter + 1, + lastChapterId = track.lastChapterId, + previousTrackChapterId = track.lastNotifiedChapterId, + newChapters = newChapters, + saveTrackLog = true, + ) + } + MangaUpdates( + manga = details, + newChapters = details.getNewChapters(track.lastNotifiedChapterId), + ) + } + } + } + else -> { + val newChapters = chapters.takeLast(chapters.size - track.knownChaptersCount) + if (commit) { + repository.storeTrackResult( + mangaId = track.manga.id, + knownChaptersCount = track.knownChaptersCount, + lastChapterId = track.lastChapterId, + previousTrackChapterId = track.lastNotifiedChapterId, + newChapters = newChapters, + saveTrackLog = true, + ) + } + MangaUpdates( + manga = details, + newChapters = details.getNewChapters(track.lastNotifiedChapterId), + ) + } + } + } + + private fun Manga.getNewChapters(lastChapterId: Long): List { + val chapters = chapters ?: return emptyList() + if (lastChapterId == 0L) { + return emptyList() + } + val raw = chapters.takeLastWhile { x -> x.id != lastChapterId } + return if (raw.isEmpty() || raw.size == chapters.size) { + emptyList() + } else { + raw + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt index 2048c38e0..b9f7e46a0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/TrackingRepository.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.tracker.domain import androidx.room.withTransaction +import java.util.* import org.koitharu.kotatsu.core.db.MangaDatabase import org.koitharu.kotatsu.core.db.entity.* import org.koitharu.kotatsu.core.model.FavouriteCategory @@ -11,7 +12,6 @@ import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.mapToSet -import java.util.* class TrackingRepository( private val db: MangaDatabase, @@ -28,7 +28,8 @@ class TrackingRepository( suspend fun getFavouritesManga(): Map> { val categories = db.favouriteCategoriesDao.findAll() return categories.associateTo(LinkedHashMap(categories.size)) { categoryEntity -> - categoryEntity.toFavouriteCategory() to db.favouritesDao.findAllManga(categoryEntity.categoryId).toMangaList() + categoryEntity.toFavouriteCategory() to db.favouritesDao.findAllManga(categoryEntity.categoryId) + .toMangaList() } } @@ -68,10 +69,10 @@ class TrackingRepository( suspend fun clearLogs() = db.trackLogsDao.clear() - suspend fun cleanup() { + suspend fun gc() { db.withTransaction { - db.tracksDao.cleanup() - db.trackLogsDao.cleanup() + db.tracksDao.gc() + db.trackLogsDao.gc() } } diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt new file mode 100644 index 000000000..436849e02 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/domain/model/MangaUpdates.kt @@ -0,0 +1,9 @@ +package org.koitharu.kotatsu.tracker.domain.model + +import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter + +class MangaUpdates( + val manga: Manga, + val newChapters: List, +) \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt index ea249c7c4..9a659566e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/work/TrackWorker.kt @@ -14,35 +14,38 @@ import androidx.lifecycle.map import androidx.work.* import coil.ImageLoader import coil.request.ImageRequest +import java.util.concurrent.TimeUnit import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.koitharu.kotatsu.R -import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.tracker.domain.Tracker import org.koitharu.kotatsu.tracker.domain.TrackingRepository import org.koitharu.kotatsu.utils.PendingIntentCompat import org.koitharu.kotatsu.utils.ext.referer import org.koitharu.kotatsu.utils.ext.toBitmapOrNull import org.koitharu.kotatsu.utils.ext.trySetForeground import org.koitharu.kotatsu.utils.progress.Progress -import java.util.concurrent.TimeUnit class TrackWorker(context: Context, workerParams: WorkerParameters) : - CoroutineWorker(context, workerParams), KoinComponent { + CoroutineWorker(context, workerParams), + KoinComponent { private val notificationManager by lazy { applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager } private val coil by inject() + private val repository by inject() private val settings by inject() private val channels by inject() + private val tracker by inject() override suspend fun doWork(): Result { if (!settings.isTrackerEnabled) { @@ -54,84 +57,25 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val tracks = getAllTracks() var success = 0 - val workData = Data.Builder() - .putInt(DATA_TOTAL, tracks.size) + val workData = Data.Builder().putInt(DATA_TOTAL, tracks.size) for ((index, item) in tracks.withIndex()) { val (track, channelId) = item - val details = runCatching { - MangaRepository(track.manga.source).getDetails(track.manga) + val updates = runCatching { + tracker.fetchUpdates(track, commit = true) + }.onSuccess { + success++ }.getOrNull() workData.putInt(DATA_PROGRESS, index) setProgress(workData.build()) - val chapters = details?.chapters ?: continue - when { - // first check or manga was empty on last check - track.knownChaptersCount <= 0 || track.lastChapterId == 0L -> { - repository.storeTrackResult( - mangaId = track.manga.id, - knownChaptersCount = chapters.size, - lastChapterId = chapters.lastOrNull()?.id ?: 0L, - previousTrackChapterId = 0L, - newChapters = emptyList(), - saveTrackLog = false, - ) - } - // the same chapters count - chapters.size == track.knownChaptersCount -> { - if (chapters.lastOrNull()?.id == track.lastChapterId) { - // manga was not updated. skip - } else { - // number of chapters still the same, bu last chapter changed. - // maybe some chapters are removed. we need to find last known chapter - val knownChapter = chapters.indexOfLast { it.id == track.lastChapterId } - if (knownChapter == -1) { - // confuse. reset anything - repository.storeTrackResult( - mangaId = track.manga.id, - knownChaptersCount = chapters.size, - lastChapterId = chapters.lastOrNull()?.id ?: 0L, - previousTrackChapterId = 0L, - newChapters = emptyList(), - saveTrackLog = false, - ) - } else { - val newChapters = chapters.takeLast(chapters.size - knownChapter + 1) - repository.storeTrackResult( - mangaId = track.manga.id, - knownChaptersCount = knownChapter + 1, - lastChapterId = track.lastChapterId, - previousTrackChapterId = track.lastNotifiedChapterId, - newChapters = newChapters, - saveTrackLog = true, - ) - showNotification( - details, - channelId, - newChapters.takeLastWhile { x -> x.id != track.lastNotifiedChapterId }, - ) - } - } - } - else -> { - val newChapters = chapters.takeLast(chapters.size - track.knownChaptersCount) - repository.storeTrackResult( - mangaId = track.manga.id, - knownChaptersCount = track.knownChaptersCount, - lastChapterId = track.lastChapterId, - previousTrackChapterId = track.lastNotifiedChapterId, - newChapters = newChapters, - saveTrackLog = true, - ) - showNotification( - manga = track.manga, - channelId = channelId, - newChapters = newChapters.takeLastWhile { x -> x.id != track.lastNotifiedChapterId }, - ) - } + if (updates != null && updates.newChapters.isNotEmpty()) { + showNotification( + manga = updates.manga, + channelId = channelId, + newChapters = updates.newChapters, + ) } - success++ } - repository.cleanup() + repository.gc() return if (success == 0) { Result.retry() } else { @@ -194,8 +138,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val colorPrimary = ContextCompat.getColor(applicationContext, R.color.blue_primary) val builder = NotificationCompat.Builder(applicationContext, channelId) val summary = applicationContext.resources.getQuantityString( - R.plurals.new_chapters, - newChapters.size, newChapters.size + R.plurals.new_chapters, newChapters.size, newChapters.size ) with(builder) { setContentText(summary) @@ -203,10 +146,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : setNumber(newChapters.size) setLargeIcon( coil.execute( - ImageRequest.Builder(applicationContext) - .data(manga.coverUrl) - .referer(manga.publicUrl) - .build() + ImageRequest.Builder(applicationContext).data(manga.coverUrl).referer(manga.publicUrl).build() ).toBitmapOrNull() ) setSmallIcon(R.drawable.ic_stat_book_plus) @@ -220,8 +160,10 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val intent = DetailsActivity.newIntent(applicationContext, manga) setContentIntent( PendingIntent.getActivity( - applicationContext, id, - intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE + applicationContext, + id, + intent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntentCompat.FLAG_IMMUTABLE ) ) setAutoCancel(true) @@ -251,9 +193,7 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : val title = applicationContext.getString(R.string.check_for_new_chapters) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { val channel = NotificationChannel( - WORKER_CHANNEL_ID, - title, - NotificationManager.IMPORTANCE_LOW + WORKER_CHANNEL_ID, title, NotificationManager.IMPORTANCE_LOW ) channel.setShowBadge(false) channel.enableVibration(false) @@ -262,17 +202,11 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : notificationManager.createNotificationChannel(channel) } - val notification = NotificationCompat.Builder(applicationContext, WORKER_CHANNEL_ID) - .setContentTitle(title) - .setPriority(NotificationCompat.PRIORITY_MIN) - .setDefaults(0) - .setColor(ContextCompat.getColor(applicationContext, R.color.blue_primary_dark)) - .setSilent(true) - .setProgress(0, 0, true) - .setSmallIcon(android.R.drawable.stat_notify_sync) - .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED) - .setOngoing(true) - .build() + val notification = NotificationCompat.Builder(applicationContext, WORKER_CHANNEL_ID).setContentTitle(title) + .setPriority(NotificationCompat.PRIORITY_MIN).setDefaults(0) + .setColor(ContextCompat.getColor(applicationContext, R.color.blue_primary_dark)).setSilent(true) + .setProgress(0, 0, true).setSmallIcon(android.R.drawable.stat_notify_sync) + .setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_DEFERRED).setOngoing(true).build() return ForegroundInfo(WORKER_NOTIFICATION_ID, notification) } @@ -287,44 +221,31 @@ class TrackWorker(context: Context, workerParams: WorkerParameters) : private const val TAG_ONESHOT = "tracking_oneshot" fun setup(context: Context) { - val constraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - val request = PeriodicWorkRequestBuilder(4, TimeUnit.HOURS) - .setConstraints(constraints) - .addTag(TAG) - .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES) - .build() - WorkManager.getInstance(context) - .enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, request) + val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() + val request = + PeriodicWorkRequestBuilder(4, TimeUnit.HOURS).setConstraints(constraints).addTag(TAG) + .setBackoffCriteria(BackoffPolicy.LINEAR, 30, TimeUnit.MINUTES).build() + WorkManager.getInstance(context).enqueueUniquePeriodicWork(TAG, ExistingPeriodicWorkPolicy.KEEP, request) } fun startNow(context: Context) { - val constraints = Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build() - val request = OneTimeWorkRequestBuilder() - .setConstraints(constraints) - .addTag(TAG_ONESHOT) - .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) - .build() - WorkManager.getInstance(context) - .enqueue(request) + val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build() + val request = OneTimeWorkRequestBuilder().setConstraints(constraints).addTag(TAG_ONESHOT) + .setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST).build() + WorkManager.getInstance(context).enqueue(request) } fun getProgressLiveData(context: Context): LiveData { - return WorkManager.getInstance(context) - .getWorkInfosByTagLiveData(TAG) - .map { list -> - list.find { work -> - work.state == WorkInfo.State.RUNNING - }?.let { workInfo -> - Progress( - value = workInfo.progress.getInt(DATA_PROGRESS, 0), - total = workInfo.progress.getInt(DATA_TOTAL, -1) - ).takeUnless { it.isIndeterminate } - } + return WorkManager.getInstance(context).getWorkInfosByTagLiveData(TAG).map { list -> + list.find { work -> + work.state == WorkInfo.State.RUNNING + }?.let { workInfo -> + Progress( + value = workInfo.progress.getInt(DATA_PROGRESS, 0), + total = workInfo.progress.getInt(DATA_TOTAL, -1) + ).takeUnless { it.isIndeterminate } } + } } } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index f885d7072..152a7d981 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:7.2.0' + classpath 'com.android.tools.build:gradle:7.2.1' classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.21' // NOTE: Do not place your application dependencies here; they belong