Compare commits
37 Commits
4.1
...
4.2-beta2-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9922a9f82a | ||
|
|
445b9b4673 | ||
|
|
0ef7b358e0 | ||
|
|
2d3fb75576 | ||
|
|
d55ff6d68e | ||
|
|
079654a9c7 | ||
|
|
30263c6260 | ||
|
|
ceaa930623 | ||
|
|
6a8539106b | ||
|
|
7a24c3c08e | ||
|
|
251abeb090 | ||
|
|
a61fe9f98c | ||
|
|
d29c7bf91a | ||
|
|
ed4911c441 | ||
|
|
d40b4f3748 | ||
|
|
f3c4fe1914 | ||
|
|
55ee841bd0 | ||
|
|
657fb488ee | ||
|
|
4eef0b93fb | ||
|
|
f2be56435c | ||
|
|
fa6b3ad7ba | ||
|
|
52c05e6888 | ||
|
|
865bf0ba83 | ||
|
|
3f827d1bad | ||
|
|
0561d5f55c | ||
|
|
1bf2e1dacc | ||
|
|
db5a221b56 | ||
|
|
295285f132 | ||
|
|
5052b6c074 | ||
|
|
f98f45dc54 | ||
|
|
8d16950f46 | ||
|
|
74033b9f4a | ||
|
|
e497d47374 | ||
|
|
a97af59260 | ||
|
|
2197de98ea | ||
|
|
c004c7f71a | ||
|
|
69fc3ad4e8 |
@@ -13,8 +13,8 @@ android {
|
|||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 29
|
||||||
versionCode 30
|
versionCode 31
|
||||||
versionName "4.1"
|
versionName "4.2-beta2-hotfix1"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
multiDexEnabled true
|
multiDexEnabled true
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
@@ -25,7 +25,7 @@ android {
|
|||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
buildTypes.each {
|
buildTypes.each {
|
||||||
it.buildConfigField('boolean', 'PRERELEASE', 'false')
|
it.buildConfigField('boolean', 'PRERELEASE', 'true')
|
||||||
it.buildConfigField('boolean', 'CENSOR', 'false')
|
it.buildConfigField('boolean', 'CENSOR', 'false')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ dependencies {
|
|||||||
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.2.1'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0"
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||||
implementation 'androidx.preference:preference:1.1.0'
|
implementation 'androidx.preference:preference:1.1.0'
|
||||||
@@ -55,12 +55,12 @@ dependencies {
|
|||||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
|
implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'
|
||||||
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
|
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.1.0'
|
||||||
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
implementation "androidx.biometric:biometric:1.0.0-rc02"
|
implementation "androidx.biometric:biometric:1.0.0"
|
||||||
implementation 'com.android.support:multidex:1.0.3'
|
implementation 'com.android.support:multidex:1.0.3'
|
||||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||||
implementation 'com.google.android.material:material:1.2.0-alpha01'
|
implementation 'com.google.android.material:material:1.2.0-alpha02'
|
||||||
implementation 'com.google.firebase:firebase-core:17.2.1'
|
implementation 'com.google.firebase:firebase-core:17.2.1'
|
||||||
implementation 'com.google.firebase:firebase-perf:19.0.1'
|
implementation 'com.google.firebase:firebase-perf:19.0.3'
|
||||||
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
|
||||||
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
||||||
implementation 'com.github.clans:fab:1.6.4'
|
implementation 'com.github.clans:fab:1.6.4'
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":30,"versionName":"4.1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
[{"outputType":{"type":"APK"},"apkData":{"type":"MAIN","splits":[],"versionCode":31,"versionName":"4.2-beta2-hotfix1","enabled":true,"outputFile":"app-release.apk","fullName":"release","baseName":"release"},"path":"app-release.apk","properties":{}}]
|
||||||
@@ -25,6 +25,10 @@ import android.util.Log
|
|||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import androidx.test.rule.ActivityTestRule
|
import androidx.test.rule.ActivityTestRule
|
||||||
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
@@ -33,6 +37,9 @@ import xyz.quaver.hiyobi.createImgList
|
|||||||
import xyz.quaver.hiyobi.getReader
|
import xyz.quaver.hiyobi.getReader
|
||||||
import xyz.quaver.hiyobi.user_agent
|
import xyz.quaver.hiyobi.user_agent
|
||||||
import xyz.quaver.pupil.ui.LockActivity
|
import xyz.quaver.pupil.ui.LockActivity
|
||||||
|
import xyz.quaver.pupil.util.getDownloadDirectory
|
||||||
|
import xyz.quaver.pupil.util.updateOldReaderGalleries
|
||||||
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
@@ -48,6 +55,7 @@ class ExampleInstrumentedTest {
|
|||||||
fun useAppContext() {
|
fun useAppContext() {
|
||||||
// Context of the app under test.
|
// Context of the app under test.
|
||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
Log.i("PUPILD", getDownloadDirectory(appContext).absolutePath ?: "")
|
||||||
assertEquals("xyz.quaver.pupil", appContext.packageName)
|
assertEquals("xyz.quaver.pupil", appContext.packageName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,13 +65,11 @@ class ExampleInstrumentedTest {
|
|||||||
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
activityTestRule.launchActivity(Intent())
|
activityTestRule.launchActivity(Intent())
|
||||||
|
|
||||||
while(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_doSearch() {
|
fun test_doSearch() {
|
||||||
val reader = getReader(1426382)
|
val reader = getReader( 1426382)
|
||||||
|
|
||||||
val data: ByteArray
|
val data: ByteArray
|
||||||
|
|
||||||
@@ -76,4 +82,38 @@ class ExampleInstrumentedTest {
|
|||||||
|
|
||||||
Log.d("Pupil", data.size.toString())
|
Log.d("Pupil", data.size.toString())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ImplicitReflectionSerializer::class)
|
||||||
|
@Test
|
||||||
|
fun test_deleteCodeFromReader() {
|
||||||
|
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
|
val json = Json(JsonConfiguration.Stable)
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
getDownloadDirectory(context),
|
||||||
|
File(context.cacheDir, "imageCache")
|
||||||
|
).forEach { root ->
|
||||||
|
root.listFiles()?.forEach gallery@{ gallery ->
|
||||||
|
val reader = json.parseJson(File(gallery, "reader.json").apply {
|
||||||
|
if (!exists())
|
||||||
|
return@gallery
|
||||||
|
}.readText())
|
||||||
|
.jsonObject.toMutableMap()
|
||||||
|
|
||||||
|
Log.d("PUPILD", gallery.name)
|
||||||
|
|
||||||
|
reader.remove("code")
|
||||||
|
|
||||||
|
File(gallery, "reader.json").writeText(JsonObject(reader).toString())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_updateOldReader() {
|
||||||
|
val context = InstrumentationRegistry.getInstrumentation().targetContext
|
||||||
|
|
||||||
|
updateOldReaderGalleries(context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -20,6 +20,18 @@
|
|||||||
android:theme="@style/AppTheme"
|
android:theme="@style/AppTheme"
|
||||||
tools:replace="android:theme">
|
tools:replace="android:theme">
|
||||||
|
|
||||||
|
<provider
|
||||||
|
android:authorities="${applicationId}.fileprovider"
|
||||||
|
android:name="androidx.core.content.FileProvider"
|
||||||
|
android:exported="false"
|
||||||
|
android:grantUriPermissions="true">
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/file_paths"/>
|
||||||
|
|
||||||
|
</provider>
|
||||||
|
|
||||||
<activity android:name=".ui.LockActivity"/>
|
<activity android:name=".ui.LockActivity"/>
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.ReaderActivity"
|
android:name=".ui.ReaderActivity"
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ import androidx.preference.PreferenceManager
|
|||||||
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
|
import com.google.android.gms.common.GooglePlayServicesNotAvailableException
|
||||||
import com.google.android.gms.common.GooglePlayServicesRepairableException
|
import com.google.android.gms.common.GooglePlayServicesRepairableException
|
||||||
import com.google.android.gms.security.ProviderInstaller
|
import com.google.android.gms.security.ProviderInstaller
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import xyz.quaver.pupil.util.Histories
|
import xyz.quaver.pupil.util.Histories
|
||||||
|
import xyz.quaver.pupil.util.updateOldReaderGalleries
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
class Pupil : MultiDexApplication() {
|
class Pupil : MultiDexApplication() {
|
||||||
@@ -78,6 +82,10 @@ class Pupil : MultiDexApplication() {
|
|||||||
false -> AppCompatDelegate.MODE_NIGHT_NO
|
false -> AppCompatDelegate.MODE_NIGHT_NO
|
||||||
})
|
})
|
||||||
|
|
||||||
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
updateOldReaderGalleries(this@Pupil)
|
||||||
|
}
|
||||||
|
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -337,7 +337,7 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
|
|
||||||
holder.view.galleryblock_download.text = when(GalleryDownloader.get(gallery.first.id)) {
|
holder.view.galleryblock_download.text = when(GalleryDownloader.get(gallery.first.id)) {
|
||||||
null -> holder.view.context.getString(R.string.main_download)
|
null -> holder.view.context.getString(R.string.main_download)
|
||||||
else -> holder.view.context.getString(R.string.main_cancel_download)
|
else -> holder.view.context.getString(android.R.string.cancel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,12 +49,17 @@ class ReaderAdapter(private val glide: RequestManager,
|
|||||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
holder.view as ImageView
|
holder.view as ImageView
|
||||||
|
|
||||||
|
if (isFullScreen)
|
||||||
|
holder.view.layoutParams.height = RecyclerView.LayoutParams.MATCH_PARENT
|
||||||
|
else
|
||||||
|
holder.view.layoutParams.height = RecyclerView.LayoutParams.WRAP_CONTENT
|
||||||
|
|
||||||
glide
|
glide
|
||||||
.load(File(getCachedGallery(holder.view.context, galleryID), images[position]))
|
.load(File(getCachedGallery(holder.view.context, galleryID), images[position]))
|
||||||
.dontTransform()
|
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.error(R.drawable.image_broken_variant)
|
.error(R.drawable.image_broken_variant)
|
||||||
|
.dontTransform()
|
||||||
.apply {
|
.apply {
|
||||||
if (BuildConfig.CENSOR)
|
if (BuildConfig.CENSOR)
|
||||||
override(5, 8)
|
override(5, 8)
|
||||||
|
|||||||
@@ -576,6 +576,17 @@ class MainActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
histories.remove(galleryID)
|
||||||
|
|
||||||
|
if (this@MainActivity.mode == Mode.HISTORY) {
|
||||||
|
runOnUiThread {
|
||||||
|
cancelFetch()
|
||||||
|
clearGalleries()
|
||||||
|
fetchGalleries(query, sortMode)
|
||||||
|
loadBlocks()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
completeFlag.put(galleryID, false)
|
completeFlag.put(galleryID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -32,10 +32,15 @@ import android.widget.TextView
|
|||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.preference.Preference
|
import androidx.preference.Preference
|
||||||
import androidx.preference.PreferenceFragmentCompat
|
import androidx.preference.PreferenceFragmentCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.dialog_default_query.view.*
|
import kotlinx.android.synthetic.main.dialog_default_query.view.*
|
||||||
|
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.parseList
|
||||||
import xyz.quaver.pupil.Pupil
|
import xyz.quaver.pupil.Pupil
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.types.Tags
|
import xyz.quaver.pupil.types.Tags
|
||||||
@@ -43,10 +48,13 @@ import xyz.quaver.pupil.util.Lock
|
|||||||
import xyz.quaver.pupil.util.LockManager
|
import xyz.quaver.pupil.util.LockManager
|
||||||
import xyz.quaver.pupil.util.getDownloadDirectory
|
import xyz.quaver.pupil.util.getDownloadDirectory
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.nio.charset.Charset
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
|
|
||||||
val REQUEST_LOCK = 38238
|
val REQUEST_LOCK = 38238
|
||||||
|
val REQUEST_RESTORE = 16546
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
@@ -154,7 +162,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
with(findPreference<Preference>("delete_downloads")) {
|
with(findPreference<Preference>("delete_downloads")) {
|
||||||
this!!
|
this!!
|
||||||
|
|
||||||
val dir = getDownloadDirectory(context)!!
|
val dir = getDownloadDirectory(context)
|
||||||
|
|
||||||
summary = getDirSize(dir)
|
summary = getDirSize(dir)
|
||||||
|
|
||||||
@@ -278,7 +286,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
s ?: return
|
s ?: return
|
||||||
|
|
||||||
if (s.any { it.isUpperCase() })
|
if (s.any { it.isUpperCase() })
|
||||||
s.replace(0, s.length, s.toString().toLowerCase())
|
s.replace(0, s.length, s.toString().toLowerCase(Locale.getDefault()))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -352,6 +360,37 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
with(findPreference<Preference>("backup")) {
|
||||||
|
this!!
|
||||||
|
|
||||||
|
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
File(ContextCompat.getDataDir(context), "favorites.json").copyTo(
|
||||||
|
File(getDownloadDirectory(context), "favorites.json"),
|
||||||
|
true
|
||||||
|
)
|
||||||
|
|
||||||
|
Snackbar.make(this@SettingsFragment.listView, R.string.settings_backup_snackbar, Snackbar.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
with(findPreference<Preference>("restore")) {
|
||||||
|
this!!
|
||||||
|
|
||||||
|
onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
||||||
|
val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
|
||||||
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
|
type = "*/*"
|
||||||
|
}
|
||||||
|
|
||||||
|
activity?.startActivityForResult(intent, (activity as SettingsActivity).REQUEST_RESTORE)
|
||||||
|
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -415,6 +454,7 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseExperimental(ImplicitReflectionSerializer::class)
|
||||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||||
when(requestCode) {
|
when(requestCode) {
|
||||||
REQUEST_LOCK -> {
|
REQUEST_LOCK -> {
|
||||||
@@ -426,6 +466,33 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
.commitAllowingStateLoss()
|
.commitAllowingStateLoss()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
REQUEST_RESTORE -> {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
val uri = data?.data ?: return
|
||||||
|
|
||||||
|
try {
|
||||||
|
val json = contentResolver.openInputStream(uri).use { inputStream ->
|
||||||
|
inputStream!!
|
||||||
|
|
||||||
|
inputStream.readBytes().toString(Charset.defaultCharset())
|
||||||
|
}
|
||||||
|
|
||||||
|
(application as Pupil).favorites.addAll(Json.parseList<Int>(json).also {
|
||||||
|
Snackbar.make(
|
||||||
|
window.decorView,
|
||||||
|
getString(R.string.settings_restore_successful, it.size),
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
})
|
||||||
|
} catch (e: Exception) {
|
||||||
|
Snackbar.make(
|
||||||
|
window.decorView,
|
||||||
|
R.string.settings_restore_failed,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else -> super.onActivityResult(requestCode, resultCode, data)
|
else -> super.onActivityResult(requestCode, resultCode, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import com.crashlytics.android.Crashlytics
|
|||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
import kotlinx.serialization.json.JsonConfiguration
|
||||||
import xyz.quaver.availableInHiyobi
|
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReader
|
import xyz.quaver.hitomi.getReader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
@@ -124,7 +123,7 @@ class GalleryDownloader(
|
|||||||
val cached = json.parse(serializer, cache.readText())
|
val cached = json.parse(serializer, cache.readText())
|
||||||
|
|
||||||
if (cached.galleryInfo.isNotEmpty()) {
|
if (cached.galleryInfo.isNotEmpty()) {
|
||||||
useHiyobi = availableInHiyobi(galleryID)
|
useHiyobi = cached.code == Reader.Code.HIYOBI
|
||||||
|
|
||||||
onReaderLoadedHandler?.invoke(cached)
|
onReaderLoadedHandler?.invoke(cached)
|
||||||
|
|
||||||
@@ -187,15 +186,11 @@ class GalleryDownloader(
|
|||||||
async(Dispatchers.IO) {
|
async(Dispatchers.IO) {
|
||||||
val url = when(useHiyobi) {
|
val url = when(useHiyobi) {
|
||||||
true -> createImgList(galleryID, reader)[index].path
|
true -> createImgList(galleryID, reader)[index].path
|
||||||
false -> when (galleryInfo.haswebp) {
|
false -> when {
|
||||||
1 -> webpUrlFromUrl(
|
(!galleryInfo.hash.isNullOrBlank()) and (galleryInfo.haswebp == 1) ->
|
||||||
urlFromUrlFromHash(
|
urlFromUrlFromHash(galleryID, galleryInfo, "webp")
|
||||||
galleryID,
|
else ->
|
||||||
galleryInfo,
|
urlFromUrlFromHash(galleryID, galleryInfo)
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
else -> urlFromUrlFromHash(galleryID, galleryInfo)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,9 @@ fun getCachedGallery(context: Context, galleryID: Int): File {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
fun getDownloadDirectory(context: Context): File? {
|
fun getDownloadDirectory(context: Context): File {
|
||||||
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
|
||||||
context.getExternalFilesDir("Pupil")
|
context.getExternalFilesDir("Pupil")!!
|
||||||
else
|
else
|
||||||
File(Environment.getExternalStorageDirectory(), "Pupil")
|
File(Environment.getExternalStorageDirectory(), "Pupil")
|
||||||
}
|
}
|
||||||
@@ -18,8 +18,14 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.util
|
package xyz.quaver.pupil.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import kotlinx.serialization.InternalSerializationApi
|
||||||
|
import kotlinx.serialization.internal.EnumSerializer
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
|
import xyz.quaver.availableInHiyobi
|
||||||
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.pupil.BuildConfig
|
import xyz.quaver.pupil.BuildConfig
|
||||||
|
import java.io.File
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
fun getReleases(url: String) : JsonArray {
|
fun getReleases(url: String) : JsonArray {
|
||||||
@@ -62,3 +68,58 @@ fun getApkUrl(releases: JsonObject) : Pair<String?, String?>? {
|
|||||||
Pair(it.jsonObject["browser_download_url"]?.content, it.jsonObject["name"]?.content)
|
Pair(it.jsonObject["browser_download_url"]?.content, it.jsonObject["name"]?.content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getOldReaderGalleries(context: Context) : List<File> {
|
||||||
|
val oldGallery = mutableListOf<File>()
|
||||||
|
|
||||||
|
listOf(
|
||||||
|
getDownloadDirectory(context),
|
||||||
|
File(context.cacheDir, "imageCache")
|
||||||
|
).forEach { root ->
|
||||||
|
root.listFiles()?.forEach { gallery ->
|
||||||
|
File(gallery, "reader.json").let { readerFile ->
|
||||||
|
if (!readerFile.exists())
|
||||||
|
return@let
|
||||||
|
|
||||||
|
try {
|
||||||
|
Json(JsonConfiguration.Stable).parseJson(readerFile.readText())
|
||||||
|
.jsonObject.let { reader ->
|
||||||
|
if (!reader.contains("code"))
|
||||||
|
oldGallery.add(gallery)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return oldGallery
|
||||||
|
}
|
||||||
|
|
||||||
|
@UseExperimental(InternalSerializationApi::class)
|
||||||
|
fun updateOldReaderGalleries(context: Context) {
|
||||||
|
|
||||||
|
val json = Json(JsonConfiguration.Stable)
|
||||||
|
|
||||||
|
getOldReaderGalleries(context).forEach { gallery ->
|
||||||
|
val reader = json.parseJson(File(gallery, "reader.json").apply {
|
||||||
|
if (!exists())
|
||||||
|
return@forEach
|
||||||
|
}.readText())
|
||||||
|
.jsonObject.toMutableMap()
|
||||||
|
|
||||||
|
val codeSerializer = EnumSerializer(Reader.Code::class)
|
||||||
|
|
||||||
|
reader["code"] = when {
|
||||||
|
(File(gallery, "images").list()?.
|
||||||
|
all { !it.endsWith("webp") } ?: return@forEach) &&
|
||||||
|
availableInHiyobi(gallery.name.toIntOrNull() ?: return@forEach)
|
||||||
|
-> json.toJson(codeSerializer, Reader.Code.HIYOBI)
|
||||||
|
else -> json.toJson(codeSerializer, Reader.Code.HITOMI)
|
||||||
|
}
|
||||||
|
|
||||||
|
File(gallery, "reader.json").writeText(JsonObject(reader).toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -26,18 +26,11 @@
|
|||||||
android:background="@color/dark_gray"
|
android:background="@color/dark_gray"
|
||||||
tools:context=".ui.ReaderActivity">
|
tools:context=".ui.ReaderActivity">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/reader_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
android:layout_gravity="center_vertical">
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/reader_recyclerview"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -22,6 +22,4 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="100dp"
|
android:minHeight="100dp"
|
||||||
android:paddingBottom="8dp"
|
android:paddingBottom="8dp"/>
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:adjustViewBounds="true"/>
|
|
||||||
@@ -104,5 +104,10 @@
|
|||||||
<string name="reader_help">ヘルプ</string>
|
<string name="reader_help">ヘルプ</string>
|
||||||
<string name="main_delete">削除</string>
|
<string name="main_delete">削除</string>
|
||||||
<string name="main_download">ダウンロード</string>
|
<string name="main_download">ダウンロード</string>
|
||||||
<string name="main_cancel_download">キャンセル</string>
|
<string name="settings_backup_title">お気に入りバックアップ</string>
|
||||||
|
<string name="settings_restore_title">お気に入り復元</string>
|
||||||
|
<string name="settings_backup_snackbar">バックアップファイルを作成しました</string>
|
||||||
|
<string name="settings_backup_checkout">確認</string>
|
||||||
|
<string name="settings_restore_failed">復元に失敗しました</string>
|
||||||
|
<string name="settings_restore_successful">%1$d項目を復元しました</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
<string name="main_open_gallery_by_id">갤러리 번호로 열기</string>
|
<string name="main_open_gallery_by_id">갤러리 번호로 열기</string>
|
||||||
<string name="main_open_gallery_by_id_error">갤러리를 찾지 못했습니다</string>
|
<string name="main_open_gallery_by_id_error">갤러리를 찾지 못했습니다</string>
|
||||||
<string name="settings_storage">저장 공간</string>
|
<string name="settings_storage">저장 공간</string>
|
||||||
<string name="main_drawer_grouop_contact_discord">디스코드햐</string>
|
<string name="main_drawer_grouop_contact_discord">디스코드</string>
|
||||||
<string name="settings_app_lock">앱 잠금</string>
|
<string name="settings_app_lock">앱 잠금</string>
|
||||||
<string name="settings_app_lock_type">앱 잠금 종류</string>
|
<string name="settings_app_lock_type">앱 잠금 종류</string>
|
||||||
<string name="settings_app_version_title">앱 버전</string>
|
<string name="settings_app_version_title">앱 버전</string>
|
||||||
@@ -104,5 +104,10 @@
|
|||||||
<string name="reader_help">도움말</string>
|
<string name="reader_help">도움말</string>
|
||||||
<string name="main_delete">삭제</string>
|
<string name="main_delete">삭제</string>
|
||||||
<string name="main_download">다운로드</string>
|
<string name="main_download">다운로드</string>
|
||||||
<string name="main_cancel_download">취소</string>
|
<string name="settings_backup_title">즐겨찾기 백업</string>
|
||||||
|
<string name="settings_restore_title">즐겨찾기 복원</string>
|
||||||
|
<string name="settings_backup_snackbar">백업 파일을 생성하였습니다</string>
|
||||||
|
<string name="settings_backup_checkout">확인</string>
|
||||||
|
<string name="settings_restore_failed">복원에 실패했습니다</string>
|
||||||
|
<string name="settings_restore_successful">%1$d개 항목을 복원했습니다</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -72,7 +72,6 @@
|
|||||||
<string name="main_export_error">Error occurred during export</string>
|
<string name="main_export_error">Error occurred during export</string>
|
||||||
|
|
||||||
<string name="main_download">DOWNLOAD</string>
|
<string name="main_download">DOWNLOAD</string>
|
||||||
<string name="main_cancel_download">CANCEL</string>
|
|
||||||
<string name="main_delete">DELETE</string>
|
<string name="main_delete">DELETE</string>
|
||||||
|
|
||||||
<string name="update_title">Update available</string>
|
<string name="update_title">Update available</string>
|
||||||
@@ -133,6 +132,12 @@
|
|||||||
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</string>
|
<string name="settings_dark_mode_summary">Protect yourself against light attacks!</string>
|
||||||
<string name="settings_nomedia_title">Hide image from gallery</string>
|
<string name="settings_nomedia_title">Hide image from gallery</string>
|
||||||
<string name="settings_nomedia_summary">Hides image from gallery</string>
|
<string name="settings_nomedia_summary">Hides image from gallery</string>
|
||||||
|
<string name="settings_backup_title">Backup favorites</string>
|
||||||
|
<string name="settings_backup_snackbar">Backup file created</string>
|
||||||
|
<string name="settings_backup_checkout">Check out</string>
|
||||||
|
<string name="settings_restore_title">Restore favorites</string>
|
||||||
|
<string name="settings_restore_failed">Restore failed</string>
|
||||||
|
<string name="settings_restore_successful">%1$d entries restored</string>
|
||||||
|
|
||||||
<string name="settings_lock_none">None</string>
|
<string name="settings_lock_none">None</string>
|
||||||
<string name="settings_lock_pattern">Pattern</string>
|
<string name="settings_lock_pattern">Pattern</string>
|
||||||
|
|||||||
22
app/src/main/res/xml/file_paths.xml
Normal file
22
app/src/main/res/xml/file_paths.xml
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Pupil, Hitomi.la viewer for Android
|
||||||
|
~ Copyright (C) 2019 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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path name="external" path="/"/>
|
||||||
|
</paths>
|
||||||
@@ -73,6 +73,15 @@
|
|||||||
app:key="nomedia"
|
app:key="nomedia"
|
||||||
app:title="@string/settings_nomedia_title"
|
app:title="@string/settings_nomedia_title"
|
||||||
app:summary="@string/settings_nomedia_title"/>
|
app:summary="@string/settings_nomedia_title"/>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="backup"
|
||||||
|
app:title="@string/settings_backup_title"/>
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
app:key="restore"
|
||||||
|
app:title="@string/settings_restore_title"/>
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
|
|
||||||
</androidx.preference.PreferenceScreen>
|
</androidx.preference.PreferenceScreen>
|
||||||
|
|||||||
@@ -20,22 +20,19 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil
|
package xyz.quaver.pupil
|
||||||
|
|
||||||
import org.junit.Test
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example local unit test, which will execute on the development machine (host).
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
*
|
*
|
||||||
* See [testing documentation](http://d.android.com/tools/testing).
|
* See [testing documentation](http://d.android.com/tools/testing).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
class ExampleUnitTest {
|
class ExampleUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test() {
|
fun test() {
|
||||||
val current = "0.1"
|
|
||||||
val latest = "0.2"
|
|
||||||
|
|
||||||
print(current < latest)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.3.50'
|
ext.kotlin_version = '1.3.61'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven { url 'https://maven.fabric.io/public' }
|
maven { url 'https://maven.fabric.io/public' }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:3.5.1'
|
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
||||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||||
classpath 'com.google.gms:google-services:4.3.2'
|
classpath 'com.google.gms:google-services:4.3.3'
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
// in the individual module build.gradle files
|
// in the individual module build.gradle files
|
||||||
classpath 'io.fabric.tools:gradle:1.29.0'
|
classpath 'io.fabric.tools:gradle:1.29.0'
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ dependencies {
|
|||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.2.1'
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.11.0"
|
implementation "org.jetbrains.kotlinx:kotlinx-serialization-runtime:0.14.0"
|
||||||
implementation 'org.jsoup:jsoup:1.11.3'
|
implementation 'org.jsoup:jsoup:1.11.3'
|
||||||
testImplementation 'junit:junit:4.12'
|
testImplementation 'junit:junit:4.12'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ fun subdomainFromGalleryID(g: Int) : String {
|
|||||||
fun subdomainFromURL(url: String, base: String? = null) : String {
|
fun subdomainFromURL(url: String, base: String? = null) : String {
|
||||||
var retval = "a"
|
var retval = "a"
|
||||||
|
|
||||||
if (!base.isNullOrEmpty())
|
if (!base.isNullOrBlank())
|
||||||
retval = base
|
retval = base
|
||||||
|
|
||||||
val r = Regex("""/galleries/\d*(\d)/""")
|
val r = Regex("""/galleries/\d*(\d)/""")
|
||||||
@@ -60,7 +60,7 @@ fun subdomainFromURL(url: String, base: String? = null) : String {
|
|||||||
|
|
||||||
if (m == null) {
|
if (m == null) {
|
||||||
b = 16
|
b = 16
|
||||||
val r2 = Regex("""/images/[0-9a-f]/([0-9a-f]{2})/""")
|
val r2 = Regex("""/[0-9a-f]/([0-9a-f]{2})/""")
|
||||||
m = r2.find(url)
|
m = r2.find(url)
|
||||||
if (m == null)
|
if (m == null)
|
||||||
return retval
|
return retval
|
||||||
@@ -79,17 +79,20 @@ fun urlFromURL(url: String, base: String? = null) : String {
|
|||||||
|
|
||||||
fun fullPathFromHash(hash: String?) : String? {
|
fun fullPathFromHash(hash: String?) : String? {
|
||||||
return when {
|
return when {
|
||||||
hash?.length ?: 0 < 3 -> hash
|
(hash?.length ?: 0) < 3 -> hash
|
||||||
else -> hash!!.replace(Regex("^.*(..)(.)$"), "$2/$1/$hash")
|
else -> hash!!.replace(Regex("^.*(..)(.)$"), "$2/$1/$hash")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun urlFromHash(galleryID: Int, image: GalleryInfo, oldMethod: Boolean) : String {
|
fun urlFromHash(galleryID: Int, image: GalleryInfo, webp: String? = null) : String {
|
||||||
|
val ext = webp ?: image.name.split('.').last()
|
||||||
return when {
|
return when {
|
||||||
oldMethod or image.hash.isNullOrEmpty() -> "$protocol//a.hitomi.la/galleries/$galleryID/${image.name}"
|
image.hash.isNullOrBlank() ->
|
||||||
else -> "$protocol//a.hitomi.la/images/${fullPathFromHash(image.hash)}.${image.name.split('.').last()}"
|
"$protocol//a.hitomi.la/galleries/$galleryID/${image.name}"
|
||||||
|
else ->
|
||||||
|
"$protocol//a.hitomi.la/${webp?:"images"}/${fullPathFromHash(image.hash)}.$ext"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun urlFromUrlFromHash(galleryID: Int, image: GalleryInfo, oldMethod: Boolean = false) =
|
fun urlFromUrlFromHash(galleryID: Int, image: GalleryInfo, webp: String? = null) =
|
||||||
urlFromURL(urlFromHash(galleryID, image, oldMethod))
|
urlFromURL(urlFromHash(galleryID, image, webp))
|
||||||
@@ -26,13 +26,19 @@ fun webpUrlFromUrl(url: String) = url.replace("/galleries/", "/webp/") + ".webp"
|
|||||||
data class GalleryInfo(
|
data class GalleryInfo(
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val hash: String? = null,
|
val hash: String? = null,
|
||||||
val haswebp: Int,
|
val haswebp: Int = 0,
|
||||||
val name: String,
|
val name: String,
|
||||||
val height: Int
|
val height: Int
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
open class Reader(val title: String, val galleryInfo: List<GalleryInfo>)
|
data class Reader(val code: Code, val title: String, val galleryInfo: List<GalleryInfo>) {
|
||||||
|
enum class Code {
|
||||||
|
HITOMI,
|
||||||
|
HIYOBI,
|
||||||
|
SORALA
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//Set header `Referer` to reader url to avoid 403 error
|
//Set header `Referer` to reader url to avoid 403 error
|
||||||
fun getReader(galleryID: Int) : Reader {
|
fun getReader(galleryID: Int) : Reader {
|
||||||
@@ -40,5 +46,5 @@ fun getReader(galleryID: Int) : Reader {
|
|||||||
|
|
||||||
val doc = Jsoup.connect(readerUrl).get()
|
val doc = Jsoup.connect(readerUrl).get()
|
||||||
|
|
||||||
return Reader(doc.title(), getGalleryInfo(galleryID))
|
return Reader(Reader.Code.HITOMI, doc.title(), getGalleryInfo(galleryID))
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ import xyz.quaver.hitomi.protocol
|
|||||||
import java.net.URL
|
import java.net.URL
|
||||||
import javax.net.ssl.HttpsURLConnection
|
import javax.net.ssl.HttpsURLConnection
|
||||||
|
|
||||||
const val hiyobi = "xn--9w3b15m8vo.asia"
|
const val hiyobi = "hiyobi.me"
|
||||||
const val user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
|
const val user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
|
||||||
|
|
||||||
var cookie: String = ""
|
var cookie: String = ""
|
||||||
@@ -76,7 +76,7 @@ fun getReader(galleryID: Int) : Reader {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
return Reader(title, galleryInfo)
|
return Reader(Reader.Code.HIYOBI, title, galleryInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createImgList(galleryID: Int, reader: Reader) =
|
fun createImgList(galleryID: Int, reader: Reader) =
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ package xyz.quaver.hitomi
|
|||||||
|
|
||||||
import org.junit.Assert.assertEquals
|
import org.junit.Assert.assertEquals
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
import xyz.quaver.availableInHiyobi
|
||||||
|
|
||||||
class UnitTest {
|
class UnitTest {
|
||||||
@Test
|
@Test
|
||||||
@@ -86,10 +87,17 @@ class UnitTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun test_urlFromUrlFromHash() {
|
fun test_urlFromUrlFromHash() {
|
||||||
val url = urlFromUrlFromHash(1510702, GalleryInfo(
|
val url = urlFromUrlFromHash(1531795, GalleryInfo(
|
||||||
210, "56e9e1b8bb72194777ed93fee11b06070b905039dd11348b070bcf1793aaed7b", 1, "6.jpg", 300
|
212, "719d46a7556be0d0021c5105878507129b5b3308b02cf67f18901b69dbb3b5ef", 1, "00.jpg", 300
|
||||||
))
|
), "webp")
|
||||||
|
|
||||||
print(url)
|
print(url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun test_availableInHiyobi() {
|
||||||
|
val result = availableInHiyobi(1272781)
|
||||||
|
|
||||||
|
print(result)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user