Files
Pupil/app/src/main/java/xyz/quaver/pupil/util/DownloadManager.kt
tom5079 0a1e0a2dcf WIP
2021-09-15 11:15:09 +09:00

116 lines
4.2 KiB
Kotlin

/*
* Pupil, Hitomi.la viewer for Android
* Copyright (C) 2021 tom5079
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package xyz.quaver.pupil.util
import android.content.Context
import android.content.ContextWrapper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.kodein.di.DIAware
import org.kodein.di.android.closestDI
import xyz.quaver.io.FileX
import xyz.quaver.io.util.*
import xyz.quaver.pupil.sources.ItemInfo
import xyz.quaver.pupil.sources.Source
class DownloadManager constructor(context: Context) : ContextWrapper(context), DIAware {
override val di by closestDI(context)
private val defaultDownloadFolder = FileX(this, getExternalFilesDir(null)!!)
val downloadFolder: FileX
get() = kotlin.runCatching {
FileX(this, Preferences.get<String>("download_folder"))
}.getOrElse {
Preferences["download_folder"] = defaultDownloadFolder.uri.toString()
defaultDownloadFolder
}
private var prevDownloadFolder: FileX? = null
private var downloadFolderMapInstance: MutableMap<String, String>? = null
private val downloadFolderMap: MutableMap<String, String>
@Synchronized
get() {
if (prevDownloadFolder != downloadFolder) {
prevDownloadFolder = downloadFolder
downloadFolderMapInstance = run {
val file = downloadFolder.getChild(".download")
val data = if (file.exists())
kotlin.runCatching {
file.readText()?.let<String, MutableMap<String, String>> { Json.decodeFromString(it) }
}.onFailure { file.delete() }.getOrNull()
else
null
data ?: run {
file.createNewFile()
mutableMapOf()
}
}
}
return downloadFolderMapInstance ?: mutableMapOf()
}
val downloads: Map<String, String>
get() = downloadFolderMap
@Synchronized
fun getDownloadFolder(source: String, itemID: String): FileX? =
downloadFolderMap["$source-$itemID"]?.let { downloadFolder.getChild(it) }
@Synchronized
fun download(source: String, itemID: String) = CoroutineScope(Dispatchers.IO).launch {
val source: Source by source(source)
val info = async { source.info(itemID) }
val images = async { source.images(itemID) }
val name = info.await().formatDownloadFolder()
val folder = downloadFolder.getChild("$source/$name")
if (folder.exists())
return@launch
folder.mkdir()
downloadFolderMap["$source/$itemID"] = folder.name
downloadFolder.getChild(".download").let { if (!it.exists()) it.createNewFile() }
downloadFolder.getChild(".download").writeText(Json.encodeToString(downloadFolderMap))
}
@Synchronized
fun delete(source: String, itemID: String) {
downloadFolderMap["$source/$itemID"]?.let {
kotlin.runCatching {
downloadFolder.getChild(it).deleteRecursively()
downloadFolderMap.remove("$source/$itemID")
downloadFolder.getChild(".download").let { if (!it.exists()) it.createNewFile() }
downloadFolder.getChild(".download").writeText(Json.encodeToString(downloadFolderMap))
}
}
}
}