diff --git a/app/build.gradle b/app/build.gradle index 0370e738..bd3755c2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -19,8 +19,8 @@ android { applicationId "xyz.quaver.pupil" minSdkVersion 16 targetSdkVersion 29 - versionCode 51 - versionName "4.15" + versionCode 52 + versionName "4.17" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" multiDexEnabled true vectorDrawables.useSupportLibrary = true @@ -54,20 +54,19 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3' implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.3' - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0" implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' - implementation 'androidx.preference:preference:1.1.0' + implementation 'androidx.preference:preference:1.1.1' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation "androidx.biometric:biometric:1.0.1" implementation 'androidx.multidex:multidex:2.0.1' implementation "com.daimajia.swipelayout:library:1.2.0@aar" - implementation 'com.google.android.material:material:1.2.0-alpha05' - implementation 'com.google.firebase:firebase-core:17.2.3' - implementation 'com.google.firebase:firebase-perf:19.0.5' + implementation 'com.google.android.material:material:1.3.0-alpha01' + implementation 'com.google.firebase:firebase-core:17.4.3' + implementation 'com.google.firebase:firebase-perf:19.0.7' implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1' implementation 'com.github.arimorty:floatingsearchview:2.1.1' implementation 'com.github.clans:fab:1.6.4' diff --git a/app/release/output.json b/app/release/output.json index 5c7bd789..41aaa36f 100644 --- a/app/release/output.json +++ b/app/release/output.json @@ -1 +1 @@ -[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":51,"versionName":"4.15","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}] \ No newline at end of file +[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":52,"versionName":"4.17","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release","dirName":""},"path":"app-release.apk","properties":{}}] \ No newline at end of file diff --git a/app/src/main/java/xyz/quaver/pupil/Pupil.kt b/app/src/main/java/xyz/quaver/pupil/Pupil.kt index 54543259..54b1b78c 100644 --- a/app/src/main/java/xyz/quaver/pupil/Pupil.kt +++ b/app/src/main/java/xyz/quaver/pupil/Pupil.kt @@ -59,6 +59,13 @@ class Pupil : MultiDexApplication() { preference.edit().remove("dl_location").apply() } + if (!preference.getBoolean("low_quality_reset", false)) { + preference.edit() + .putBoolean("low_quality", true) + .putBoolean("low_quality_reset", true) + .apply() + } + histories = Histories(File(ContextCompat.getDataDir(this), "histories.json")) favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json")) diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt index bf97d3a3..714d4fb2 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt @@ -52,7 +52,7 @@ import io.fabric.sdk.android.Fabric import kotlinx.android.synthetic.main.activity_main.* import kotlinx.android.synthetic.main.activity_main_content.* import kotlinx.coroutines.* -import kotlinx.serialization.list +import kotlinx.serialization.builtins.list import xyz.quaver.hitomi.GalleryBlock import xyz.quaver.hitomi.doSearch import xyz.quaver.hitomi.getGalleryIDsFromNozomi @@ -367,6 +367,29 @@ class MainActivity : AppCompatActivity() { } } + with(main_fab_random) { + setImageResource(R.drawable.shuffle_variant) + setOnClickListener { + runBlocking { + withTimeoutOrNull(100) { + galleryIDs?.await() + } + }.let { + if (it?.isEmpty() == false) { + val galleryID = it.random() + + val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply { + putExtra("galleryID", galleryID) + } + + startActivity(intent) + + histories.add(galleryID) + } + } + } + } + with(main_fab_id) { setImageResource(R.drawable.numeric) setOnClickListener { diff --git a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt index fecb401c..20621e38 100644 --- a/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt +++ b/app/src/main/java/xyz/quaver/pupil/ui/SettingsActivity.kt @@ -30,8 +30,8 @@ import androidx.appcompat.app.AppCompatActivity import androidx.preference.PreferenceManager import com.google.android.material.snackbar.Snackbar import kotlinx.android.synthetic.main.settings_activity.* -import kotlinx.serialization.list -import kotlinx.serialization.serializer +import kotlinx.serialization.builtins.list +import kotlinx.serialization.builtins.serializer import net.rdrei.android.dirchooser.DirectoryChooserActivity import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.R diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt b/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt index 97edd6f1..617d3dd3 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/Cache.kt @@ -26,7 +26,6 @@ import android.util.SparseArray import androidx.preference.PreferenceManager import com.crashlytics.android.Crashlytics import kotlinx.coroutines.* -import kotlinx.io.InputStream import xyz.quaver.Code import xyz.quaver.hitomi.GalleryBlock import xyz.quaver.hitomi.Reader @@ -35,10 +34,11 @@ import xyz.quaver.pupil.util.getCachedGallery import xyz.quaver.pupil.util.getDownloadDirectory import xyz.quaver.pupil.util.isParentOf import xyz.quaver.pupil.util.json +import java.io.BufferedInputStream import java.io.File import java.io.FileOutputStream +import java.io.InputStream import java.net.URL -import java.util.concurrent.Executors import java.util.concurrent.locks.Lock import java.util.concurrent.locks.ReentrantLock @@ -245,7 +245,7 @@ class Cache(context: Context) : ContextWrapper(context) { it.createNewFile() } - data.use { + BufferedInputStream(data).use { it.copyTo(FileOutputStream(cache)) } } diff --git a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt index eb05cc19..5c279c3b 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/download/DownloadWorker.kt @@ -46,11 +46,10 @@ import xyz.quaver.pupil.R import xyz.quaver.pupil.ui.ReaderActivity import java.io.File import java.io.IOException -import java.util.concurrent.Executors import java.util.concurrent.LinkedBlockingQueue import java.util.concurrent.TimeUnit -@UseExperimental(ExperimentalCoroutinesApi::class) +@OptIn(ExperimentalCoroutinesApi::class) class DownloadWorker private constructor(context: Context) : ContextWrapper(context) { private val preferences : SharedPreferences = PreferenceManager.getDefaultSharedPreferences(this) @@ -164,7 +163,10 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont .connectTimeout(0, TimeUnit.SECONDS) .addInterceptor(interceptor) .readTimeout(0, TimeUnit.SECONDS) - .dispatcher(Dispatcher(Executors.newFixedThreadPool(4))) + .dispatcher(Dispatcher().apply { + maxRequests = 4 + maxRequestsPerHost = 4 + }) .proxy(proxy) .build() @@ -222,7 +224,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont imageUrlFromImage( galleryID, reader.galleryInfo.files[index], - lowQuality + !lowQuality ) ) addHeader("Referer", getReferer(galleryID)) @@ -240,6 +242,8 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont }.build() client.newCall(request).enqueue(callback) + + Log.i("PUPILD", "DOWNLOADING ($galleryID, $index) from ${request.url()}") } private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch { diff --git a/app/src/main/java/xyz/quaver/pupil/util/history.kt b/app/src/main/java/xyz/quaver/pupil/util/history.kt index cb13c226..cc80275e 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/history.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/history.kt @@ -18,13 +18,14 @@ package xyz.quaver.pupil.util -import kotlinx.serialization.list -import kotlinx.serialization.serializer +import kotlinx.serialization.KSerializer +import kotlinx.serialization.builtins.list +import kotlinx.serialization.builtins.serializer import java.io.File class Histories(private val file: File) : ArrayList() { - val serializer = Int.serializer().list + val serializer: KSerializer> = Int.serializer().list init { if (!file.exists()) diff --git a/app/src/main/java/xyz/quaver/pupil/util/lock.kt b/app/src/main/java/xyz/quaver/pupil/util/lock.kt index 4f48b784..44397450 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/lock.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/lock.kt @@ -22,9 +22,7 @@ import android.content.Context import android.content.ContextWrapper import androidx.core.content.ContextCompat import kotlinx.serialization.Serializable -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonConfiguration -import kotlinx.serialization.list +import kotlinx.serialization.builtins.list import java.io.File import java.security.MessageDigest diff --git a/app/src/main/java/xyz/quaver/pupil/util/misc.kt b/app/src/main/java/xyz/quaver/pupil/util/misc.kt index ddee2443..fafad368 100644 --- a/app/src/main/java/xyz/quaver/pupil/util/misc.kt +++ b/app/src/main/java/xyz/quaver/pupil/util/misc.kt @@ -22,7 +22,7 @@ import android.annotation.SuppressLint import java.util.* import kotlin.collections.ArrayList -@UseExperimental(ExperimentalStdlibApi::class) +@OptIn(ExperimentalStdlibApi::class) fun String.wordCapitalize() : String { val result = ArrayList() diff --git a/app/src/main/res/drawable/shuffle_variant.xml b/app/src/main/res/drawable/shuffle_variant.xml new file mode 100644 index 00000000..b254ea08 --- /dev/null +++ b/app/src/main/res/drawable/shuffle_variant.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main_content.xml b/app/src/main/res/layout/activity_main_content.xml index 3bb527b7..e3ce7e65 100644 --- a/app/src/main/res/layout/activity_main_content.xml +++ b/app/src/main/res/layout/activity_main_content.xml @@ -100,6 +100,13 @@ app:fab_label="@string/main_jump_title" app:fab_size="mini"/> + + フォルダを読めません 旧ギャラリーインポート中… インポート完了 + ランダムギャラリーを開く \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index fa220ba8..598da2cc 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -140,4 +140,5 @@ 폴더를 읽을 수 없습니다 이전 버전 갤러리 가져오는 중… 가져오기 완료 + 무작위 갤러리 열기 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6dc09043..f21275ad 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -69,6 +69,7 @@ Current page: %1$d\nMaximum page: %2$d Open Gallery by ID Failed to open gallery + Open a random gallery Cancel all downloads Move to page %1$d diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml index 3572ada9..cd28fb7b 100644 --- a/app/src/main/res/xml/root_preferences.xml +++ b/app/src/main/res/xml/root_preferences.xml @@ -50,7 +50,8 @@ + app:summary="@string/settings_low_quality_summary" + app:defaultValue="true"/> diff --git a/build.gradle b/build.gradle index ccd12583..ad7f92dd 100644 --- a/build.gradle +++ b/build.gradle @@ -1,14 +1,14 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.3.61' + ext.kotlin_version = '1.3.72' repositories { google() jcenter() maven { url 'https://maven.fabric.io/public' } } dependencies { - classpath 'com.android.tools.build:gradle:3.6.1' + classpath 'com.android.tools.build:gradle:3.6.3' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" diff --git a/libpupil/build.gradle b/libpupil/build.gradle index 035a800e..b886c59e 100644 --- a/libpupil/build.gradle +++ b/libpupil/build.gradle @@ -6,7 +6,7 @@ dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.3' - implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0" + implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.20.0" implementation 'org.jsoup:jsoup:1.12.1' testImplementation 'junit:junit:4.13' } diff --git a/libpupil/src/main/java/xyz/quaver/Utils.kt b/libpupil/src/main/java/xyz/quaver/Utils.kt index 40e8b1b5..c598f697 100644 --- a/libpupil/src/main/java/xyz/quaver/Utils.kt +++ b/libpupil/src/main/java/xyz/quaver/Utils.kt @@ -16,10 +16,20 @@ package xyz.quaver +import kotlinx.serialization.UnstableDefault +import kotlinx.serialization.json.Json import java.net.Proxy var proxy = Proxy.NO_PROXY +@OptIn(UnstableDefault::class) +var json = Json { + isLenient = true + ignoreUnknownKeys = true + serializeSpecialFloatingPointValues = true + useArrayPolymorphism = true +} + fun availableInHiyobi(galleryID: Int) : Boolean { return try { xyz.quaver.hiyobi.getReader(galleryID) diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt index f80e15bd..56eea8c0 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/common.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/common.kt @@ -16,7 +16,7 @@ package xyz.quaver.hitomi -import kotlinx.serialization.json.Json +import xyz.quaver.json import xyz.quaver.proxy import java.net.URL @@ -24,7 +24,7 @@ const val protocol = "https:" @Suppress("EXPERIMENTAL_API_USAGE") fun getGalleryInfo(galleryID: Int) = - Json.nonstrict.parse( + json.parse( GalleryInfo.serializer(), URL("$protocol//$domain/galleries/$galleryID.js").openConnection(proxy).getInputStream().use { it.reader().readText() diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/search.kt b/libpupil/src/main/java/xyz/quaver/hitomi/search.kt index 927bb41d..b3e65769 100644 --- a/libpupil/src/main/java/xyz/quaver/hitomi/search.kt +++ b/libpupil/src/main/java/xyz/quaver/hitomi/search.kt @@ -39,7 +39,7 @@ fun sha256(data: ByteArray) : ByteArray { return MessageDigest.getInstance("SHA-256").digest(data) } -@UseExperimental(ExperimentalUnsignedTypes::class) +@OptIn(ExperimentalUnsignedTypes::class) fun hashTerm(term: String) : UByteArray { return sha256(term.toByteArray()).toUByteArray().sliceArray(0 until 4) } @@ -258,9 +258,9 @@ fun getURLAtRange(url: String, range: LongRange) : ByteArray? { } } -@UseExperimental(ExperimentalUnsignedTypes::class) +@OptIn(ExperimentalUnsignedTypes::class) data class Node(val keys: List, val datas: List>, val subNodeAddresses: List) -@UseExperimental(ExperimentalUnsignedTypes::class) +@OptIn(ExperimentalUnsignedTypes::class) fun decodeNode(data: ByteArray) : Node { val buffer = ByteBuffer .wrap(data) @@ -302,7 +302,7 @@ fun decodeNode(data: ByteArray) : Node { return Node(keys, datas, subNodeAddresses) } -@UseExperimental(ExperimentalUnsignedTypes::class) +@OptIn(ExperimentalUnsignedTypes::class) fun bSearch(field: String, key: UByteArray, node: Node) : Pair? { fun compareArrayBuffers(dv1: UByteArray, dv2: UByteArray) : Int { val top = Math.min(dv1.size, dv2.size) diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt index 945b5ffc..07babd9d 100644 --- a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt +++ b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt @@ -17,14 +17,14 @@ package xyz.quaver.hiyobi import kotlinx.serialization.UnstableDefault -import kotlinx.serialization.json.Json -import kotlinx.serialization.list +import kotlinx.serialization.builtins.list import org.jsoup.Jsoup import xyz.quaver.Code import xyz.quaver.hitomi.GalleryFiles import xyz.quaver.hitomi.GalleryInfo import xyz.quaver.hitomi.Reader import xyz.quaver.hitomi.protocol +import xyz.quaver.json import xyz.quaver.proxy import java.net.URL import javax.net.ssl.HttpsURLConnection @@ -62,14 +62,14 @@ fun renewCookie() : String { } } -@UseExperimental(UnstableDefault::class) +@OptIn(UnstableDefault::class) fun getReader(galleryID: Int) : Reader { val reader = "https://$hiyobi/reader/$galleryID" val url = "https://cdn.hiyobi.me/data/json/${galleryID}_list.json" val title = Jsoup.connect(reader).proxy(proxy).get().title() - val galleryFiles = Json.nonstrict.parse( + val galleryFiles = json.parse( GalleryFiles.serializer().list, with(URL(url).openConnection(proxy) as HttpsURLConnection) { setRequestProperty("User-Agent", user_agent)