Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5ee1bb11a0 | ||
|
|
c1de45abce | ||
|
|
8805033c8d | ||
|
|
0ed59bb8a9 | ||
|
|
8163f2fd28 | ||
|
|
521a65c9d2 | ||
|
|
eb98424668 | ||
|
|
961c731743 | ||
|
|
5188769fb6 | ||
|
|
8f27d9e30f |
13
.idea/deploymentTargetDropDown.xml
generated
13
.idea/deploymentTargetDropDown.xml
generated
@@ -1,17 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="deploymentTargetDropDown">
|
<component name="deploymentTargetDropDown">
|
||||||
<runningDeviceTargetSelectedWithDropDown>
|
|
||||||
<Target>
|
|
||||||
<type value="RUNNING_DEVICE_TARGET" />
|
|
||||||
<deviceKey>
|
|
||||||
<Key>
|
|
||||||
<type value="VIRTUAL_DEVICE_PATH" />
|
|
||||||
<value value="$USER_HOME$/.android/avd/Pixel_2_API_31.avd" />
|
|
||||||
</Key>
|
|
||||||
</deviceKey>
|
|
||||||
</Target>
|
|
||||||
</runningDeviceTargetSelectedWithDropDown>
|
|
||||||
<targetSelectedWithDropDown>
|
<targetSelectedWithDropDown>
|
||||||
<Target>
|
<Target>
|
||||||
<type value="QUICK_BOOT_TARGET" />
|
<type value="QUICK_BOOT_TARGET" />
|
||||||
@@ -23,6 +12,6 @@
|
|||||||
</deviceKey>
|
</deviceKey>
|
||||||
</Target>
|
</Target>
|
||||||
</targetSelectedWithDropDown>
|
</targetSelectedWithDropDown>
|
||||||
<timeTargetWasSelectedWithDropDown value="2022-02-01T02:15:22.286886Z" />
|
<timeTargetWasSelectedWithDropDown value="2022-02-01T08:00:57.223690Z" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
*Pupil, Hitomi.la viewer for Android*
|
*Pupil, Hitomi.la viewer for Android*
|
||||||
|
|
||||||

|

|
||||||
[](https://github.com/tom5079/Pupil/releases/download/5.3.0/Pupil-v5.3.0.apk)
|
[](https://github.com/tom5079/Pupil/releases/download/5.3.3/Pupil-v5.3.3.apk)
|
||||||
[](https://discord.gg/Stj4b5v)
|
[](https://discord.gg/Stj4b5v)
|
||||||
|
|
||||||
# Features
|
# Features
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ android {
|
|||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode 69
|
versionCode 69
|
||||||
versionName "5.3.0"
|
versionName "5.3.4"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
|
|||||||
1
app/proguard-rules.pro
vendored
1
app/proguard-rules.pro
vendored
@@ -34,3 +34,4 @@
|
|||||||
-keep class xyz.quaver.pupil.ui.fragment.ManageFavoritesFragment
|
-keep class xyz.quaver.pupil.ui.fragment.ManageFavoritesFragment
|
||||||
-keep class xyz.quaver.pupil.ui.fragment.ManageStorageFragment
|
-keep class xyz.quaver.pupil.ui.fragment.ManageStorageFragment
|
||||||
-keep class xyz.quaver.pupil.** { *; }
|
-keep class xyz.quaver.pupil.** { *; }
|
||||||
|
-keep class app.cash.zipline.** { *; }
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
"filters": [],
|
"filters": [],
|
||||||
"attributes": [],
|
"attributes": [],
|
||||||
"versionCode": 69,
|
"versionCode": 69,
|
||||||
"versionName": "5.3.0",
|
"versionName": "5.3.4",
|
||||||
"outputFile": "app-release.apk"
|
"outputFile": "app-release.apk"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -102,19 +102,19 @@ class ExampleInstrumentedTest {
|
|||||||
Log.d("PUPILD", r.take(10).toString())
|
Log.d("PUPILD", r.take(10).toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
fun test_getBlock() {
|
// fun test_getBlock() {
|
||||||
val galleryBlock = getGalleryBlock(2097576)
|
// val galleryBlock = getGalleryBlock(2097576)
|
||||||
|
//
|
||||||
print(galleryBlock)
|
// print(galleryBlock)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
@Test
|
// @Test
|
||||||
fun test_getGallery() {
|
// fun test_getGallery() {
|
||||||
val gallery = getGallery(2097751)
|
// val gallery = getGallery(2097751)
|
||||||
|
//
|
||||||
print(gallery)
|
// print(gallery)
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_getGalleryInfo() {
|
fun test_getGalleryInfo() {
|
||||||
@@ -125,42 +125,44 @@ class ExampleInstrumentedTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_getReader() {
|
fun test_getReader() {
|
||||||
val reader = getGalleryInfo(1722144)
|
val reader = getGalleryInfo(2128654)
|
||||||
|
|
||||||
print(reader)
|
Log.d("PUPILD", reader.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_getImages() {
|
fun test_getImages() { runBlocking {
|
||||||
val galleryID = 2099306
|
val galleryID = 2128654
|
||||||
|
|
||||||
val images = getGalleryInfo(galleryID).files.map {
|
val images = getGalleryInfo(galleryID).files.map {
|
||||||
imageUrlFromImage(galleryID, it,false)
|
imageUrlFromImage(galleryID, it,false)
|
||||||
}
|
}
|
||||||
|
|
||||||
images.forEachIndexed { index, image ->
|
Log.d("PUPILD", images.toString())
|
||||||
println("Testing $index/${images.size}: $image")
|
|
||||||
val response = client.newCall(
|
|
||||||
Request.Builder()
|
|
||||||
.url(image)
|
|
||||||
.header("Referer", "https://hitomi.la/")
|
|
||||||
.build()
|
|
||||||
).execute()
|
|
||||||
|
|
||||||
assertEquals(200, response.code())
|
// images.forEachIndexed { index, image ->
|
||||||
|
// println("Testing $index/${images.size}: $image")
|
||||||
|
// val response = client.newCall(
|
||||||
|
// Request.Builder()
|
||||||
|
// .url(image)
|
||||||
|
// .header("Referer", "https://hitomi.la/")
|
||||||
|
// .build()
|
||||||
|
// ).execute()
|
||||||
|
//
|
||||||
|
// assertEquals(200, response.code())
|
||||||
|
//
|
||||||
|
// println("$index/${images.size} Passed")
|
||||||
|
// }
|
||||||
|
} }
|
||||||
|
|
||||||
println("$index/${images.size} Passed")
|
// @Test
|
||||||
}
|
// fun test_urlFromUrlFromHash() {
|
||||||
}
|
// val url = urlFromUrlFromHash(1531795, GalleryFiles(
|
||||||
|
// 212, "719d46a7556be0d0021c5105878507129b5b3308b02cf67f18901b69dbb3b5ef", 1, "00.jpg", 300
|
||||||
@Test
|
// ), "webp")
|
||||||
fun test_urlFromUrlFromHash() {
|
//
|
||||||
val url = urlFromUrlFromHash(1531795, GalleryFiles(
|
// print(url)
|
||||||
212, "719d46a7556be0d0021c5105878507129b5b3308b02cf67f18901b69dbb3b5ef", 1, "00.jpg", 300
|
// }
|
||||||
), "webp")
|
|
||||||
|
|
||||||
print(url)
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
// suspend fun test_doSearch_extreme() {
|
// suspend fun test_doSearch_extreme() {
|
||||||
@@ -173,9 +175,9 @@ class ExampleInstrumentedTest {
|
|||||||
// print(doSearch("-male:yaoi -female:yaoi -female:loli").size)
|
// print(doSearch("-male:yaoi -female:yaoi -female:loli").size)
|
||||||
// }
|
// }
|
||||||
|
|
||||||
@Test
|
// @Test
|
||||||
fun test_subdomainFromUrl() {
|
// fun test_subdomainFromUrl() {
|
||||||
val galleryInfo = getGalleryInfo(1929109).files[2]
|
// val galleryInfo = getGalleryInfo(1929109).files[2]
|
||||||
print(urlFromUrlFromHash(1929109, galleryInfo, "webp", null, "a"))
|
// print(urlFromUrlFromHash(1929109, galleryInfo, "webp", null, "a"))
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
@@ -81,10 +81,8 @@ private var version = ""
|
|||||||
var runtimeReady = false
|
var runtimeReady = false
|
||||||
private set
|
private set
|
||||||
lateinit var runtime: QuickJs
|
lateinit var runtime: QuickJs
|
||||||
private set
|
|
||||||
|
|
||||||
class Pupil : Application() {
|
class Pupil : Application() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
lateinit var instance: Pupil
|
lateinit var instance: Pupil
|
||||||
private set
|
private set
|
||||||
@@ -92,7 +90,7 @@ class Pupil : Application() {
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
withContext(evaluationContext) {
|
withContext(Dispatchers.Main) {
|
||||||
runtime = QuickJs.create()
|
runtime = QuickJs.create()
|
||||||
}
|
}
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -101,15 +99,18 @@ class Pupil : Application() {
|
|||||||
|
|
||||||
if (version != newVersion) {
|
if (version != newVersion) {
|
||||||
runtimeReady = false
|
runtimeReady = false
|
||||||
version = newVersion
|
|
||||||
evaluationContext.cancelChildren()
|
evaluationContext.cancelChildren()
|
||||||
withContext(evaluationContext) {
|
kotlin.runCatching {
|
||||||
Log.d("PUPILD", "UPDATE!")
|
URL("https://tom5079.github.io/PupilSources/assets/js/gg.js").readText()
|
||||||
runtime.evaluate(URL("https://tom5079.github.io/PupilSources/assets/js/gg.js").readText())
|
}.getOrNull()?.also { gg ->
|
||||||
|
withContext(Dispatchers.Main) {
|
||||||
|
runtime.evaluate(gg)
|
||||||
|
version = newVersion
|
||||||
runtimeReady = true
|
runtimeReady = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delay(10000)
|
delay(10000)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,16 +16,14 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.hitomi
|
package xyz.quaver.pupil.hitomi
|
||||||
|
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import xyz.quaver.pupil.client
|
import xyz.quaver.pupil.client
|
||||||
import xyz.quaver.pupil.runtime
|
import xyz.quaver.pupil.runtime
|
||||||
|
import xyz.quaver.pupil.runtimeReady
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
@@ -84,11 +82,11 @@ data class GalleryInfo(
|
|||||||
val groups: List<Group>? = null,
|
val groups: List<Group>? = null,
|
||||||
val parodys: List<Parody>? = null,
|
val parodys: List<Parody>? = null,
|
||||||
val tags: List<Tag>? = null,
|
val tags: List<Tag>? = null,
|
||||||
val related: List<Int>,
|
val related: List<Int> = emptyList(),
|
||||||
val languages: List<Language>,
|
val languages: List<Language> = emptyList(),
|
||||||
val characters: List<Character>? = null,
|
val characters: List<Character>? = null,
|
||||||
val scene_indexes: List<Int>,
|
val scene_indexes: List<Int>? = emptyList(),
|
||||||
val files: List<GalleryFiles>
|
val files: List<GalleryFiles> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
val json = Json {
|
val json = Json {
|
||||||
@@ -130,18 +128,21 @@ const val galleryblockextension = ".html"
|
|||||||
const val galleryblockdir = "galleryblock"
|
const val galleryblockdir = "galleryblock"
|
||||||
const val nozomiextension = ".nozomi"
|
const val nozomiextension = ".nozomi"
|
||||||
|
|
||||||
val evaluationContext = Executors.newSingleThreadExecutor().asCoroutineDispatcher() + Job()
|
val evaluationContext = Dispatchers.Main + Job()
|
||||||
|
|
||||||
object gg {
|
object gg {
|
||||||
|
|
||||||
suspend fun m(g: Int): Int = withContext(evaluationContext) {
|
suspend fun m(g: Int): Int = withContext(evaluationContext) {
|
||||||
|
while (!runtimeReady) delay(1000)
|
||||||
runtime.evaluate("gg.m($g)").toString().toInt()
|
runtime.evaluate("gg.m($g)").toString().toInt()
|
||||||
}
|
}
|
||||||
suspend fun b(): String = withContext(evaluationContext) {
|
suspend fun b(): String = withContext(evaluationContext) {
|
||||||
|
while (!runtimeReady) delay(1000)
|
||||||
runtime.evaluate("gg.b").toString()
|
runtime.evaluate("gg.b").toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun s(h: String): String = withContext(evaluationContext) {
|
suspend fun s(h: String): String = withContext(evaluationContext) {
|
||||||
|
while (!runtimeReady) delay(1000)
|
||||||
runtime.evaluate("gg.s('$h')").toString()
|
runtime.evaluate("gg.s('$h')").toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -197,14 +198,15 @@ suspend fun rewriteTnPaths(html: String) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
suspend fun imageUrlFromImage(galleryID: Int, image: GalleryFiles, noWebp: Boolean) : String {
|
suspend fun imageUrlFromImage(galleryID: Int, image: GalleryFiles, noWebp: Boolean) : String {
|
||||||
return when {
|
return urlFromUrlFromHash(galleryID, image, "webp", null, "a")
|
||||||
noWebp ->
|
// return when {
|
||||||
urlFromUrlFromHash(galleryID, image)
|
// noWebp ->
|
||||||
// image.hasavif != 0 ->
|
// urlFromUrlFromHash(galleryID, image)
|
||||||
// urlFromUrlFromHash(galleryID, image, "avif", null, "a")
|
//// image.hasavif != 0 ->
|
||||||
image.haswebp != 0 ->
|
//// urlFromUrlFromHash(galleryID, image, "avif", null, "a")
|
||||||
urlFromUrlFromHash(galleryID, image, "webp", null, "a")
|
// image.haswebp != 0 ->
|
||||||
else ->
|
// urlFromUrlFromHash(galleryID, image, "webp", null, "a")
|
||||||
urlFromUrlFromHash(galleryID, image)
|
// else ->
|
||||||
}
|
// urlFromUrlFromHash(galleryID, image)
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ data class GalleryBlock(
|
|||||||
val type: String,
|
val type: String,
|
||||||
val language: String,
|
val language: String,
|
||||||
val relatedTags: List<String>,
|
val relatedTags: List<String>,
|
||||||
val groups: List<String>
|
val groups: List<String> = emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
suspend fun getGalleryBlock(galleryID: Int) : GalleryBlock {
|
suspend fun getGalleryBlock(galleryID: Int) : GalleryBlock {
|
||||||
|
|||||||
@@ -220,15 +220,11 @@ class DownloadService : Service() {
|
|||||||
|
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
runCatching {
|
runCatching {
|
||||||
response.also {
|
val image = response.also { if (it.code() != 200) throw IOException( "$galleryID $index ${response.request().url()} CODE ${it.code()}" ) }.body()?.use { it.bytes() } ?: throw Exception("Response null")
|
||||||
if (it.code() != 200) throw IOException(
|
|
||||||
"$galleryID $index ${response.request().url()} CODE ${it.code()}"
|
|
||||||
)
|
|
||||||
}.body()?.use {
|
|
||||||
val padding = ceil(progress[galleryID]?.size?.let { log10(it.toFloat()) } ?: 0F).toInt()
|
val padding = ceil(progress[galleryID]?.size?.let { log10(it.toFloat()) } ?: 0F).toInt()
|
||||||
|
|
||||||
Cache.getInstance(this@DownloadService, galleryID)
|
Cache.getInstance(this@DownloadService, galleryID)
|
||||||
.putImage(index, "${index.toString().padStart(padding, '0')}.$ext", it.byteStream())
|
.putImage(index, "${index.toString().padStart(padding, '0')}.$ext", image)
|
||||||
|
|
||||||
progress[galleryID]?.set(index, Float.POSITIVE_INFINITY)
|
progress[galleryID]?.set(index, Float.POSITIVE_INFINITY)
|
||||||
notify(galleryID)
|
notify(galleryID)
|
||||||
@@ -241,7 +237,6 @@ class DownloadService : Service() {
|
|||||||
|
|
||||||
startId?.let { stopSelf(it) }
|
startId?.let { stopSelf(it) }
|
||||||
}
|
}
|
||||||
} ?: throw Exception("Response null")
|
|
||||||
}.onFailure {
|
}.onFailure {
|
||||||
FirebaseCrashlytics.getInstance().recordException(it)
|
FirebaseCrashlytics.getInstance().recordException(it)
|
||||||
}
|
}
|
||||||
@@ -329,6 +324,7 @@ class DownloadService : Service() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isCompleted(galleryID)) {
|
if (isCompleted(galleryID)) {
|
||||||
|
if (DownloadManager.getInstance(this@DownloadService).getDownloadFolder(galleryID) != null)
|
||||||
Cache.getInstance(this@DownloadService, galleryID).moveToDownload()
|
Cache.getInstance(this@DownloadService, galleryID).moveToDownload()
|
||||||
|
|
||||||
notificationManager.cancel(galleryID)
|
notificationManager.cancel(galleryID)
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ import xyz.quaver.io.util.readText
|
|||||||
import xyz.quaver.io.util.writeText
|
import xyz.quaver.io.util.writeText
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.histories
|
import xyz.quaver.pupil.histories
|
||||||
|
import xyz.quaver.pupil.hitomi.json
|
||||||
import xyz.quaver.pupil.util.byteToString
|
import xyz.quaver.pupil.util.byteToString
|
||||||
import xyz.quaver.pupil.util.downloader.Cache
|
import xyz.quaver.pupil.util.downloader.Cache
|
||||||
import xyz.quaver.pupil.util.downloader.DownloadManager
|
import xyz.quaver.pupil.util.downloader.DownloadManager
|
||||||
@@ -118,7 +119,7 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc
|
|||||||
if (!metadataFile.exists()) return@forEach
|
if (!metadataFile.exists()) return@forEach
|
||||||
|
|
||||||
val metadata = metadataFile.readText()?.let {
|
val metadata = metadataFile.readText()?.let {
|
||||||
Json.decodeFromString<Metadata>(it)
|
json.decodeFromString<Metadata>(it)
|
||||||
} ?: return@forEach
|
} ?: return@forEach
|
||||||
|
|
||||||
val galleryID = metadata.galleryBlock?.id ?: metadata.galleryInfo?.id?.toIntOrNull() ?: return@forEach
|
val galleryID = metadata.galleryBlock?.id ?: metadata.galleryInfo?.id?.toIntOrNull() ?: return@forEach
|
||||||
|
|||||||
@@ -21,12 +21,9 @@ package xyz.quaver.pupil.util.downloader
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
@@ -35,35 +32,50 @@ import okhttp3.Request
|
|||||||
import xyz.quaver.io.FileX
|
import xyz.quaver.io.FileX
|
||||||
import xyz.quaver.io.util.*
|
import xyz.quaver.io.util.*
|
||||||
import xyz.quaver.pupil.client
|
import xyz.quaver.pupil.client
|
||||||
import xyz.quaver.pupil.hitomi.GalleryBlock
|
import xyz.quaver.pupil.hitomi.*
|
||||||
import xyz.quaver.pupil.hitomi.GalleryInfo
|
|
||||||
import xyz.quaver.pupil.hitomi.getGalleryBlock
|
|
||||||
import xyz.quaver.pupil.hitomi.getGalleryInfo
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class OldGalleryBlock(
|
data class OldGalleryInfo(
|
||||||
val code: String,
|
val language_localname: String? = null,
|
||||||
val id: Int,
|
val language: String? = null,
|
||||||
val galleryUrl: String,
|
val date: String? = null,
|
||||||
val thumbnails: List<String>,
|
val files: List<OldGalleryFiles>,
|
||||||
val title: String,
|
val id: Int? = null,
|
||||||
val artists: List<String>,
|
val type: String? = null,
|
||||||
val series: List<String>,
|
val title: String? = null
|
||||||
val type: String,
|
|
||||||
val language: String,
|
|
||||||
val relatedTags: List<String>
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OldGalleryFiles(
|
||||||
|
val width: Int,
|
||||||
|
val hash: String,
|
||||||
|
val haswebp: Int = 0,
|
||||||
|
val name: String,
|
||||||
|
val height: Int,
|
||||||
|
val hasavif: Int = 0,
|
||||||
|
val hasavifsmalltn: Int? = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class OldMetadata(
|
||||||
|
var galleryBlock: GalleryBlock? = null,
|
||||||
|
var reader: OldGalleryInfo? = null,
|
||||||
|
var imageList: MutableList<String?>? = null
|
||||||
|
) {
|
||||||
|
fun copy(): OldMetadata = OldMetadata(galleryBlock, reader, imageList?.let { MutableList(it.size) { i -> it[i] } })
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Metadata(
|
data class Metadata(
|
||||||
var galleryBlock: GalleryBlock? = null,
|
var galleryBlock: GalleryBlock? = null,
|
||||||
var galleryInfo: GalleryInfo? = null,
|
var galleryInfo: GalleryInfo? = null,
|
||||||
var imageList: MutableList<String?>? = null
|
var imageList: MutableList<String?>? = null
|
||||||
) {
|
) {
|
||||||
|
constructor(old: OldMetadata) : this(old.galleryBlock, getGalleryInfo(old.galleryBlock?.id ?: throw Exception()), old.imageList)
|
||||||
fun copy(): Metadata = Metadata(galleryBlock, galleryInfo, imageList?.let { MutableList(it.size) { i -> it[i] } })
|
fun copy(): Metadata = Metadata(galleryBlock, galleryInfo, imageList?.let { MutableList(it.size) { i -> it[i] } })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,9 +102,13 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW
|
|||||||
|
|
||||||
var metadata = kotlin.runCatching {
|
var metadata = kotlin.runCatching {
|
||||||
findFile(".metadata")?.readText()?.let { metadata ->
|
findFile(".metadata")?.readText()?.let { metadata ->
|
||||||
Json.decodeFromString<Metadata>(metadata)
|
kotlin.runCatching {
|
||||||
|
json.decodeFromString<Metadata>(metadata)
|
||||||
|
}.getOrElse {
|
||||||
|
Metadata(json.decodeFromString<OldMetadata>(metadata))
|
||||||
}
|
}
|
||||||
}.getOrNull() ?: Metadata()
|
}
|
||||||
|
}.onFailure { it.printStackTrace() }.getOrNull() ?: Metadata()
|
||||||
|
|
||||||
val downloadFolder: FileX?
|
val downloadFolder: FileX?
|
||||||
get() = DownloadManager.getInstance(this).getDownloadFolder(galleryID)
|
get() = DownloadManager.getInstance(this).getDownloadFolder(galleryID)
|
||||||
@@ -179,14 +195,13 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW
|
|||||||
metadata.imageList?.getOrNull(index)?.let { findFile(it) }
|
metadata.imageList?.getOrNull(index)?.let { findFile(it) }
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
fun putImage(index: Int, fileName: String, data: InputStream) {
|
suspend fun putImage(index: Int, fileName: String, data: ByteArray) = coroutineScope {
|
||||||
val file = cacheFolder.getChild(fileName)
|
val file = cacheFolder.getChild(fileName)
|
||||||
|
|
||||||
if (!file.exists())
|
if (!file.exists())
|
||||||
file.createNewFile()
|
file.createNewFile()
|
||||||
file.outputStream()?.use {
|
|
||||||
data.copyTo(it)
|
file.writeBytes(data)
|
||||||
}
|
|
||||||
setMetadata { metadata -> metadata.imageList!![index] = fileName }
|
setMetadata { metadata -> metadata.imageList!![index] = fileName }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ fun OkHttpClient.Builder.proxyInfo(proxyInfo: ProxyInfo) = this.apply {
|
|||||||
val formatMap = mapOf<String, GalleryBlock.() -> (String)>(
|
val formatMap = mapOf<String, GalleryBlock.() -> (String)>(
|
||||||
"-id-" to { id.toString() },
|
"-id-" to { id.toString() },
|
||||||
"-title-" to { title },
|
"-title-" to { title },
|
||||||
"-artist-" to { artists.joinToString() },
|
"-artist-" to { if (artists.isNotEmpty()) artists.joinToString() else "N/A" },
|
||||||
"-group-" to { groups.joinToString() }
|
"-group-" to { if (groups.isNotEmpty()) groups.joinToString() else "N/A" }
|
||||||
// TODO
|
// TODO
|
||||||
)
|
)
|
||||||
/**
|
/**
|
||||||
@@ -100,13 +100,11 @@ fun GalleryBlock.formatDownloadFolderTest(format: String): String =
|
|||||||
|
|
||||||
suspend fun GalleryInfo.getRequestBuilders(): List<Request.Builder> {
|
suspend fun GalleryInfo.getRequestBuilders(): List<Request.Builder> {
|
||||||
val galleryID = this.id.toIntOrNull() ?: 0
|
val galleryID = this.id.toIntOrNull() ?: 0
|
||||||
val lowQuality = Preferences["low_quality", true]
|
|
||||||
|
|
||||||
return this.files.map {
|
return this.files.map {
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url(
|
.url(
|
||||||
runCatching {
|
runCatching {
|
||||||
imageUrlFromImage(galleryID, it, !lowQuality)
|
imageUrlFromImage(galleryID, it, false)
|
||||||
}
|
}
|
||||||
.onFailure {
|
.onFailure {
|
||||||
FirebaseCrashlytics.getInstance().recordException(it)
|
FirebaseCrashlytics.getInstance().recordException(it)
|
||||||
|
|||||||
@@ -56,12 +56,6 @@
|
|||||||
app:key="nomedia"
|
app:key="nomedia"
|
||||||
app:title="@string/settings_nomedia_title"/>
|
app:title="@string/settings_nomedia_title"/>
|
||||||
|
|
||||||
<SwitchPreferenceCompat
|
|
||||||
app:key="low_quality"
|
|
||||||
app:title="@string/settings_low_quality"
|
|
||||||
app:summary="@string/settings_low_quality_summary"
|
|
||||||
app:defaultValue="true"/>
|
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
|
|||||||
Reference in New Issue
Block a user