Cleanup temporary files

This commit is contained in:
Koitharu
2022-04-20 11:50:55 +03:00
parent d64bd9d9d3
commit 1f411b7530
5 changed files with 60 additions and 17 deletions

View File

@@ -44,6 +44,7 @@ class DownloadService : BaseService() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
isRunning = true
notificationSwitcher = ForegroundNotificationSwitcher(this) notificationSwitcher = ForegroundNotificationSwitcher(this)
val wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager) val wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager)
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading") .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kotatsu:downloading")
@@ -81,6 +82,7 @@ class DownloadService : BaseService() {
override fun onDestroy() { override fun onDestroy() {
unregisterReceiver(controlReceiver) unregisterReceiver(controlReceiver)
binder = null binder = null
isRunning = false
super.onDestroy() super.onDestroy()
} }
@@ -162,11 +164,12 @@ class DownloadService : BaseService() {
companion object { companion object {
const val ACTION_DOWNLOAD_COMPLETE = var isRunning: Boolean = false
"${BuildConfig.APPLICATION_ID}.action.ACTION_DOWNLOAD_COMPLETE" private set
private const val ACTION_DOWNLOAD_CANCEL = const val ACTION_DOWNLOAD_COMPLETE = "${BuildConfig.APPLICATION_ID}.action.ACTION_DOWNLOAD_COMPLETE"
"${BuildConfig.APPLICATION_ID}.action.ACTION_DOWNLOAD_CANCEL"
private const val ACTION_DOWNLOAD_CANCEL = "${BuildConfig.APPLICATION_ID}.action.ACTION_DOWNLOAD_CANCEL"
private const val EXTRA_MANGA = "manga" private const val EXTRA_MANGA = "manga"
private const val EXTRA_CHAPTERS_IDS = "chapters_ids" private const val EXTRA_CHAPTERS_IDS = "chapters_ids"

View File

@@ -7,6 +7,10 @@ import java.util.*
class CbzFilter : FilenameFilter { class CbzFilter : FilenameFilter {
override fun accept(dir: File, name: String): Boolean { override fun accept(dir: File, name: String): Boolean {
return isFileSupported(name)
}
fun isFileSupported(name: String): Boolean {
val ext = name.substringAfterLast('.', "").lowercase(Locale.ROOT) val ext = name.substringAfterLast('.', "").lowercase(Locale.ROOT)
return ext == "cbz" || ext == "zip" return ext == "cbz" || ext == "zip"
} }

View File

@@ -0,0 +1,11 @@
package org.koitharu.kotatsu.local.data
import java.io.File
import java.io.FilenameFilter
class TempFileFilter : FilenameFilter {
override fun accept(dir: File, name: String): Boolean {
return name.endsWith(".tmp", ignoreCase = true)
}
}

View File

@@ -7,18 +7,13 @@ import androidx.annotation.WorkerThread
import androidx.collection.ArraySet import androidx.collection.ArraySet
import androidx.core.net.toFile import androidx.core.net.toFile
import androidx.core.net.toUri 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 kotlinx.coroutines.*
import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException import org.koitharu.kotatsu.core.exceptions.UnsupportedFileException
import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.parser.MangaRepository
import org.koitharu.kotatsu.local.data.CbzFilter import org.koitharu.kotatsu.local.data.CbzFilter
import org.koitharu.kotatsu.local.data.LocalStorageManager import org.koitharu.kotatsu.local.data.LocalStorageManager
import org.koitharu.kotatsu.local.data.MangaIndex import org.koitharu.kotatsu.local.data.MangaIndex
import org.koitharu.kotatsu.local.data.TempFileFilter
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.longHashCode import org.koitharu.kotatsu.parsers.util.longHashCode
import org.koitharu.kotatsu.parsers.util.toCamelCase import org.koitharu.kotatsu.parsers.util.toCamelCase
@@ -26,6 +21,12 @@ import org.koitharu.kotatsu.utils.AlphanumComparator
import org.koitharu.kotatsu.utils.ext.deleteAwait import org.koitharu.kotatsu.utils.ext.deleteAwait
import org.koitharu.kotatsu.utils.ext.readText import org.koitharu.kotatsu.utils.ext.readText
import org.koitharu.kotatsu.utils.ext.resolveName 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 private const val MAX_PARALLELISM = 4
@@ -245,7 +246,7 @@ class LocalMangaRepository(private val storageManager: LocalStorageManager) : Ma
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val name = contentResolver.resolveName(uri) val name = contentResolver.resolveName(uri)
?: throw IOException("Cannot fetch name from uri: $uri") ?: throw IOException("Cannot fetch name from uri: $uri")
if (!isFileSupported(name)) { if (!filenameFilter.isFileSupported(name)) {
throw UnsupportedFileException("Unsupported file on $uri") throw UnsupportedFileException("Unsupported file on $uri")
} }
val dest = File( val dest = File(
@@ -262,15 +263,21 @@ class LocalMangaRepository(private val storageManager: LocalStorageManager) : Ma
} }
} }
fun isFileSupported(name: String): Boolean {
val ext = name.substringAfterLast('.').lowercase(Locale.ROOT)
return ext == "cbz" || ext == "zip"
}
suspend fun getOutputDir(): File? { suspend fun getOutputDir(): File? {
return storageManager.getDefaultWriteableDir() return storageManager.getDefaultWriteableDir()
} }
suspend fun cleanup() {
val dirs = storageManager.getWriteableDirs()
runInterruptible(Dispatchers.IO) {
dirs.flatMap { dir ->
dir.listFiles(TempFileFilter())?.toList().orEmpty()
}.forEach { file ->
file.delete()
}
}
}
private suspend fun getAllFiles() = storageManager.getReadableDirs().flatMap { dir -> private suspend fun getAllFiles() = storageManager.getReadableDirs().flatMap { dir ->
dir.listFiles(filenameFilter)?.toList().orEmpty() dir.listFiles(filenameFilter)?.toList().orEmpty()
} }

View File

@@ -3,16 +3,18 @@ package org.koitharu.kotatsu.local.ui
import android.net.Uri import android.net.Uri
import androidx.lifecycle.MutableLiveData import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import java.io.IOException
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.BuildConfig
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.os.ShortcutsRepository import org.koitharu.kotatsu.core.os.ShortcutsRepository
import org.koitharu.kotatsu.core.prefs.AppSettings import org.koitharu.kotatsu.core.prefs.AppSettings
import org.koitharu.kotatsu.download.ui.service.DownloadService
import org.koitharu.kotatsu.history.domain.HistoryRepository import org.koitharu.kotatsu.history.domain.HistoryRepository
import org.koitharu.kotatsu.list.ui.MangaListViewModel import org.koitharu.kotatsu.list.ui.MangaListViewModel
import org.koitharu.kotatsu.list.ui.model.* import org.koitharu.kotatsu.list.ui.model.*
@@ -21,6 +23,7 @@ import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.utils.SingleLiveEvent import org.koitharu.kotatsu.utils.SingleLiveEvent
import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct import org.koitharu.kotatsu.utils.ext.asLiveDataDistinct
import org.koitharu.kotatsu.utils.progress.Progress import org.koitharu.kotatsu.utils.progress.Progress
import java.io.IOException
class LocalListViewModel( class LocalListViewModel(
private val repository: LocalMangaRepository, private val repository: LocalMangaRepository,
@@ -64,6 +67,7 @@ class LocalListViewModel(
init { init {
onRefresh() onRefresh()
cleanup()
} }
override fun onRefresh() { override fun onRefresh() {
@@ -116,4 +120,18 @@ class LocalListViewModel(
listError.value = e listError.value = e
} }
} }
private fun cleanup() {
if (!DownloadService.isRunning) {
viewModelScope.launch {
runCatching {
repository.cleanup()
}.onFailure { error ->
if (BuildConfig.DEBUG) {
error.printStackTrace()
}
}
}
}
}
} }