Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
439a8e93ec | ||
|
|
83801feee9 | ||
|
|
8a6860c96e | ||
|
|
5c959f2987 | ||
|
|
4e4397287a | ||
|
|
fe02abc9e8 | ||
|
|
59347ab317 | ||
|
|
f408a91176 | ||
|
|
6f6956ce27 | ||
|
|
4ecad8eccc | ||
|
|
486fbe46a0 | ||
|
|
1ddb636dd0 |
5
.idea/jarRepositories.xml
generated
5
.idea/jarRepositories.xml
generated
@@ -56,5 +56,10 @@
|
|||||||
<option name="name" value="MavenLocal" />
|
<option name="name" value="MavenLocal" />
|
||||||
<option name="url" value="file:/$USER_HOME$/.m2/repository/" />
|
<option name="url" value="file:/$USER_HOME$/.m2/repository/" />
|
||||||
</remote-repository>
|
</remote-repository>
|
||||||
|
<remote-repository>
|
||||||
|
<option name="id" value="MavenLocal" />
|
||||||
|
<option name="name" value="MavenLocal" />
|
||||||
|
<option name="url" value="file:/$USER_HOME$/.m2/repository" />
|
||||||
|
</remote-repository>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
@@ -14,13 +14,13 @@ if (file("google-services.json").exists() && file("src/debug/google-services.jso
|
|||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 30
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "xyz.quaver.pupil"
|
applicationId "xyz.quaver.pupil"
|
||||||
minSdkVersion 16
|
minSdkVersion 16
|
||||||
targetSdkVersion 29
|
targetSdkVersion 30
|
||||||
versionCode 57
|
versionCode 57
|
||||||
versionName "5.0-beta2"
|
versionName "5.0-beta7"
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
vectorDrawables.useSupportLibrary = true
|
vectorDrawables.useSupportLibrary = true
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ dependencies {
|
|||||||
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.3.9"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.9"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC-HOTFIX1"
|
//implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC"
|
||||||
implementation 'androidx.appcompat:appcompat:1.2.0'
|
implementation 'androidx.appcompat:appcompat:1.2.0'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
|
||||||
implementation 'androidx.preference:preference:1.1.1'
|
implementation 'androidx.preference:preference:1.1.1'
|
||||||
@@ -78,6 +78,7 @@ dependencies {
|
|||||||
implementation 'com.google.firebase:firebase-perf:19.0.8'
|
implementation 'com.google.firebase:firebase-perf:19.0.8'
|
||||||
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'
|
||||||
|
//implementation 'com.quiph.ui:recyclerviewfastscroller:0.2.1'
|
||||||
//noinspection GradleDependency
|
//noinspection GradleDependency
|
||||||
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
|
implementation 'com.squareup.okhttp3:okhttp:3.12.12'
|
||||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
@@ -96,10 +97,10 @@ dependencies {
|
|||||||
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
|
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
|
||||||
//implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
//implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
||||||
implementation "ru.noties.markwon:core:3.1.0"
|
implementation "ru.noties.markwon:core:3.1.0"
|
||||||
implementation ("xyz.quaver:libpupil:1.3") {
|
implementation ("xyz.quaver:libpupil:1.5") {
|
||||||
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
|
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
|
||||||
}
|
}
|
||||||
implementation "xyz.quaver:documentfilex:0.2.14-alpha2"
|
implementation "xyz.quaver:documentfilex:0.2.15"
|
||||||
testImplementation 'junit:junit:4.13'
|
testImplementation 'junit:junit:4.13'
|
||||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||||
|
|||||||
BIN
app/libs/kotlinx-serialization-core-1.0.0-RC.jar
Normal file
BIN
app/libs/kotlinx-serialization-core-1.0.0-RC.jar
Normal file
Binary file not shown.
BIN
app/libs/recyclerviewfastscroller-release.aar
Normal file
BIN
app/libs/recyclerviewfastscroller-release.aar
Normal file
Binary file not shown.
@@ -12,7 +12,7 @@
|
|||||||
"filters": [],
|
"filters": [],
|
||||||
"properties": [],
|
"properties": [],
|
||||||
"versionCode": 57,
|
"versionCode": 57,
|
||||||
"versionName": "5.0-beta2",
|
"versionName": "5.0-beta7",
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"outputFile": "app-release.apk"
|
"outputFile": "app-release.apk"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ class Pupil : Application() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
Preferences.get<String>("download_folder").also {
|
Preferences.get<String>("download_folder").also {
|
||||||
if (Build.VERSION.SDK_INT > 19)
|
if (it.startsWith("content") && Build.VERSION.SDK_INT > 19)
|
||||||
contentResolver.takePersistableUriPermission(
|
contentResolver.takePersistableUriPermission(
|
||||||
Uri.parse(it),
|
Uri.parse(it),
|
||||||
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
|||||||
@@ -19,9 +19,6 @@
|
|||||||
package xyz.quaver.pupil.adapters
|
package xyz.quaver.pupil.adapters
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.PorterDuff
|
|
||||||
import android.graphics.PorterDuffColorFilter
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.util.SparseBooleanArray
|
import android.util.SparseBooleanArray
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
@@ -29,23 +26,26 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import androidx.cardview.widget.CardView
|
import androidx.cardview.widget.CardView
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
|
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
|
||||||
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
|
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
|
||||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||||
import com.bumptech.glide.RequestManager
|
import com.bumptech.glide.RequestManager
|
||||||
|
import com.bumptech.glide.load.DataSource
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
|
import com.bumptech.glide.load.engine.GlideException
|
||||||
|
import com.bumptech.glide.request.RequestListener
|
||||||
|
import com.bumptech.glide.request.target.Target
|
||||||
import com.daimajia.swipe.SwipeLayout
|
import com.daimajia.swipe.SwipeLayout
|
||||||
import com.daimajia.swipe.adapters.RecyclerSwipeAdapter
|
import com.daimajia.swipe.adapters.RecyclerSwipeAdapter
|
||||||
import com.daimajia.swipe.interfaces.SwipeAdapterInterface
|
import com.daimajia.swipe.interfaces.SwipeAdapterInterface
|
||||||
import com.google.android.material.chip.Chip
|
|
||||||
import kotlinx.android.synthetic.main.item_galleryblock.view.*
|
import kotlinx.android.synthetic.main.item_galleryblock.view.*
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import xyz.quaver.hitomi.getReader
|
import xyz.quaver.hitomi.getReader
|
||||||
|
import xyz.quaver.io.util.getChild
|
||||||
import xyz.quaver.pupil.BuildConfig
|
import xyz.quaver.pupil.BuildConfig
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.favorites
|
import xyz.quaver.pupil.favorites
|
||||||
@@ -88,11 +88,10 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
val imageList = cache.metadata.imageList!!
|
val imageList = cache.metadata.imageList!!
|
||||||
|
|
||||||
progress = imageList.filterNotNull().size
|
progress = imageList.filterNotNull().size
|
||||||
|
|
||||||
if (visibility == View.GONE) {
|
|
||||||
visibility = View.VISIBLE
|
|
||||||
max = imageList.size
|
max = imageList.size
|
||||||
}
|
|
||||||
|
if (visibility == View.GONE)
|
||||||
|
visibility = View.VISIBLE
|
||||||
|
|
||||||
if (progress == max) {
|
if (progress == max) {
|
||||||
val downloadManager = DownloadManager.getInstance(context)
|
val downloadManager = DownloadManager.getInstance(context)
|
||||||
@@ -158,6 +157,28 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
|
|||||||
.skipMemoryCache(true)
|
.skipMemoryCache(true)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
.error(R.drawable.image_broken_variant)
|
.error(R.drawable.image_broken_variant)
|
||||||
|
.listener(object: RequestListener<Drawable> {
|
||||||
|
override fun onLoadFailed(
|
||||||
|
e: GlideException?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Drawable>?,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean {
|
||||||
|
Cache.getInstance(context, galleryID).let {
|
||||||
|
it.cacheFolder.getChild(".thumbnail").let { if (it.exists()) it.delete() }
|
||||||
|
it.downloadFolder?.getChild(".thumbnail")?.let { if (it.exists()) it.delete() }
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResourceReady(
|
||||||
|
resource: Drawable?,
|
||||||
|
model: Any?,
|
||||||
|
target: Target<Drawable>?,
|
||||||
|
dataSource: DataSource?,
|
||||||
|
isFirstResource: Boolean
|
||||||
|
): Boolean = false
|
||||||
|
})
|
||||||
.apply {
|
.apply {
|
||||||
if (BuildConfig.CENSOR)
|
if (BuildConfig.CENSOR)
|
||||||
override(5, 8)
|
override(5, 8)
|
||||||
|
|||||||
@@ -40,9 +40,7 @@ import xyz.quaver.Code
|
|||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
import xyz.quaver.hitomi.imageUrlFromImage
|
import xyz.quaver.hitomi.imageUrlFromImage
|
||||||
import xyz.quaver.hiyobi.cookie
|
|
||||||
import xyz.quaver.hiyobi.createImgList
|
import xyz.quaver.hiyobi.createImgList
|
||||||
import xyz.quaver.hiyobi.user_agent
|
|
||||||
import xyz.quaver.io.util.readBytes
|
import xyz.quaver.io.util.readBytes
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.services.DownloadService
|
import xyz.quaver.pupil.services.DownloadService
|
||||||
@@ -116,10 +114,7 @@ class ReaderAdapter(private val activity: ReaderActivity,
|
|||||||
)
|
)
|
||||||
, LazyHeaders.Builder().addHeader("Referer", getReferer(galleryID)).build())
|
, LazyHeaders.Builder().addHeader("Referer", getReferer(galleryID)).build())
|
||||||
Code.HIYOBI ->
|
Code.HIYOBI ->
|
||||||
GlideUrl(createImgList(galleryID, reader!!, lowQuality)[position].path, LazyHeaders.Builder()
|
GlideUrl(createImgList(galleryID, reader!!, lowQuality)[position].path)
|
||||||
.addHeader("User-Agent", user_agent)
|
|
||||||
.addHeader("Cookie", cookie)
|
|
||||||
.build())
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
holder.view.image.post {
|
holder.view.image.post {
|
||||||
|
|||||||
@@ -307,13 +307,18 @@ class DownloadService : Service() {
|
|||||||
return@launch
|
return@launch
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress.indexOfKey(galleryID) < 0)
|
|
||||||
progress.put(galleryID, MutableList(reader.galleryInfo.files.size) { 0F })
|
progress.put(galleryID, MutableList(reader.galleryInfo.files.size) { 0F })
|
||||||
|
|
||||||
cache.metadata.imageList?.forEachIndexed { index, image ->
|
cache.metadata.imageList?.forEachIndexed { index, image ->
|
||||||
progress[galleryID]?.set(index, if (image != null) Float.POSITIVE_INFINITY else 0F)
|
progress[galleryID]?.set(index, if (image != null) Float.POSITIVE_INFINITY else 0F)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isCompleted(galleryID)) {
|
||||||
|
notificationManager.cancel(galleryID)
|
||||||
|
startId?.let { stopSelf(it) }
|
||||||
|
return@launch
|
||||||
|
}
|
||||||
|
|
||||||
notification[galleryID]?.setContentTitle(reader.galleryInfo.title?.ellipsize(30))
|
notification[galleryID]?.setContentTitle(reader.galleryInfo.title?.ellipsize(30))
|
||||||
notify(galleryID)
|
notify(galleryID)
|
||||||
|
|
||||||
@@ -328,10 +333,12 @@ class DownloadService : Service() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.requestBuilders.filterIndexed { index, _ -> progress[galleryID]?.get(index)?.isInfinite() != true }.forEachIndexed { index, it ->
|
reader.requestBuilders.forEachIndexed { index, it ->
|
||||||
|
if (progress[galleryID]?.get(index)?.isInfinite() != true) {
|
||||||
val request = it.tag(Tag(galleryID, index, startId)).build()
|
val request = it.tag(Tag(galleryID, index, startId)).build()
|
||||||
client.newCall(request).enqueue(callback)
|
client.newCall(request).enqueue(callback)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
queued.forEach { download(it) }
|
queued.forEach { download(it) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
package xyz.quaver.pupil.types
|
package xyz.quaver.pupil.types
|
||||||
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Transient
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Tag(val area: String?, val tag: String, val isNegative: Boolean = false) {
|
data class Tag(val area: String?, val tag: String, val isNegative: Boolean = false) {
|
||||||
|
|||||||
@@ -981,7 +981,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
if (query.isNotEmpty() && mode != Mode.SEARCH) {
|
if (query.isNotEmpty() && mode != Mode.SEARCH) {
|
||||||
Snackbar.make(this@MainActivity.main_recyclerview, R.string.search_all, Snackbar.LENGTH_SHORT).apply {
|
Snackbar.make(this@MainActivity.main_recyclerview, R.string.search_all, Snackbar.LENGTH_SHORT).apply {
|
||||||
setAction(android.R.string.yes) {
|
setAction(android.R.string.ok) {
|
||||||
cancelFetch()
|
cancelFetch()
|
||||||
clearGalleries()
|
clearGalleries()
|
||||||
currentPage = 0
|
currentPage = 0
|
||||||
@@ -1034,7 +1034,7 @@ class MainActivity : AppCompatActivity() {
|
|||||||
val downloads = DownloadManager.getInstance(this@MainActivity).downloadFolderMap.keys.toList()
|
val downloads = DownloadManager.getInstance(this@MainActivity).downloadFolderMap.keys.toList()
|
||||||
|
|
||||||
when {
|
when {
|
||||||
query.isEmpty() -> downloads.also {
|
query.isEmpty() -> downloads.reversed().also {
|
||||||
totalItems = it.size
|
totalItems = it.size
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ class ReaderActivity : AppCompatActivity() {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when(item?.itemId) {
|
when(item.itemId) {
|
||||||
R.id.reader_menu_page_indicator -> {
|
R.id.reader_menu_page_indicator -> {
|
||||||
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, reader_layout, false)
|
val view = LayoutInflater.from(this).inflate(R.layout.dialog_numberpicker, reader_layout, false)
|
||||||
with(view.dialog_number_picker) {
|
with(view.dialog_number_picker) {
|
||||||
|
|||||||
@@ -22,23 +22,19 @@ import android.annotation.SuppressLint
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.android.synthetic.main.settings_activity.*
|
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import net.rdrei.android.dirchooser.DirectoryChooserActivity
|
|
||||||
import xyz.quaver.io.FileX
|
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.favorites
|
import xyz.quaver.pupil.favorites
|
||||||
import xyz.quaver.pupil.ui.fragment.LockSettingsFragment
|
import xyz.quaver.pupil.ui.fragment.LockSettingsFragment
|
||||||
import xyz.quaver.pupil.ui.fragment.SettingsFragment
|
import xyz.quaver.pupil.ui.fragment.SettingsFragment
|
||||||
import xyz.quaver.pupil.util.*
|
import xyz.quaver.pupil.util.Preferences
|
||||||
import java.io.File
|
import xyz.quaver.pupil.util.normalizeID
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
class SettingsActivity : AppCompatActivity() {
|
class SettingsActivity : AppCompatActivity() {
|
||||||
@@ -68,8 +64,8 @@ class SettingsActivity : AppCompatActivity() {
|
|||||||
super.onResume()
|
super.onResume()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
when (item?.itemId) {
|
when (item.itemId) {
|
||||||
android.R.id.home -> onBackPressed()
|
android.R.id.home -> onBackPressed()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,9 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
|||||||
.setTitle(R.string.settings_download_folder)
|
.setTitle(R.string.settings_download_folder)
|
||||||
.setView(build())
|
.setView(build())
|
||||||
.setPositiveButton(requireContext().getText(android.R.string.ok)) { _, _ ->
|
.setPositiveButton(requireContext().getText(android.R.string.ok)) { _, _ ->
|
||||||
|
if (Preferences["download_folder", ""].isEmpty())
|
||||||
|
Preferences["download_folder"] = context?.getExternalFilesDir(null)?.canonicalPath ?: ""
|
||||||
|
|
||||||
DownloadManager.getInstance(requireContext()).migrate()
|
DownloadManager.getInstance(requireContext()).migrate()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class MirrorDialog(context: Context) : AlertDialog(context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onItemMoved = {
|
onItemMoved = {
|
||||||
Preferences["mirrors", it.joinToString(">")]
|
Preferences["mirrors"] = it.joinToString(">")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,11 +74,11 @@ class LockSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
setTitle(R.string.warning)
|
setTitle(R.string.warning)
|
||||||
setMessage(R.string.settings_lock_remove_message)
|
setMessage(R.string.settings_lock_remove_message)
|
||||||
|
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
lockManager.remove(Lock.Type.PATTERN)
|
lockManager.remove(Lock.Type.PATTERN)
|
||||||
onResume()
|
onResume()
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ -> }
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
}.show()
|
}.show()
|
||||||
} else {
|
} else {
|
||||||
val intent = Intent(requireContext(), LockActivity::class.java).apply {
|
val intent = Intent(requireContext(), LockActivity::class.java).apply {
|
||||||
@@ -107,11 +107,11 @@ class LockSettingsFragment : PreferenceFragmentCompat() {
|
|||||||
setTitle(R.string.warning)
|
setTitle(R.string.warning)
|
||||||
setMessage(R.string.settings_lock_remove_message)
|
setMessage(R.string.settings_lock_remove_message)
|
||||||
|
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
lockManager.remove(Lock.Type.PIN)
|
lockManager.remove(Lock.Type.PIN)
|
||||||
onResume()
|
onResume()
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ -> }
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
}.show()
|
}.show()
|
||||||
} else {
|
} else {
|
||||||
val intent = Intent(requireContext(), LockActivity::class.java).apply {
|
val intent = Intent(requireContext(), LockActivity::class.java).apply {
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc
|
|||||||
AlertDialog.Builder(context).apply {
|
AlertDialog.Builder(context).apply {
|
||||||
setTitle(R.string.warning)
|
setTitle(R.string.warning)
|
||||||
setMessage(R.string.settings_clear_cache_alert_message)
|
setMessage(R.string.settings_clear_cache_alert_message)
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
if (dir.exists())
|
if (dir.exists())
|
||||||
dir.deleteRecursively()
|
dir.deleteRecursively()
|
||||||
|
|
||||||
@@ -74,7 +74,7 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ -> }
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
"delete_downloads" -> {
|
"delete_downloads" -> {
|
||||||
@@ -83,7 +83,7 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc
|
|||||||
AlertDialog.Builder(context).apply {
|
AlertDialog.Builder(context).apply {
|
||||||
setTitle(R.string.warning)
|
setTitle(R.string.warning)
|
||||||
setMessage(R.string.settings_clear_downloads_alert_message)
|
setMessage(R.string.settings_clear_downloads_alert_message)
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
@@ -109,18 +109,18 @@ class ManageStorageFragment : PreferenceFragmentCompat(), Preference.OnPreferenc
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ -> }
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
"clear_history" -> {
|
"clear_history" -> {
|
||||||
AlertDialog.Builder(context).apply {
|
AlertDialog.Builder(context).apply {
|
||||||
setTitle(R.string.warning)
|
setTitle(R.string.warning)
|
||||||
setMessage(R.string.settings_clear_history_alert_message)
|
setMessage(R.string.settings_clear_history_alert_message)
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
histories.clear()
|
histories.clear()
|
||||||
summary = context.getString(R.string.settings_clear_history_summary, histories.size)
|
summary = context.getString(R.string.settings_clear_history_summary, histories.size)
|
||||||
}
|
}
|
||||||
setNegativeButton(android.R.string.no) { _, _ -> }
|
setNegativeButton(android.R.string.cancel) { _, _ -> }
|
||||||
}.show()
|
}.show()
|
||||||
}
|
}
|
||||||
else -> return false
|
else -> return false
|
||||||
|
|||||||
@@ -36,15 +36,17 @@ class GalleryList(private val file: File, private val list: MutableSet<Int> = mu
|
|||||||
fun load() {
|
fun load() {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
list.clear()
|
list.clear()
|
||||||
list.addAll(
|
kotlin.runCatching {
|
||||||
Json.decodeFromString<List<Int>>(file.bufferedReader().use { it.readText() })
|
Json.decodeFromString<List<Int>>(file.bufferedReader().use { it.readText() })
|
||||||
)
|
}.onSuccess {
|
||||||
|
list.addAll(it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun save() {
|
fun save() {
|
||||||
synchronized(this) {
|
synchronized(this) {
|
||||||
file.writeText(Json.encodeToString(list))
|
file.writeText(Json.encodeToString(list.toList()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import java.io.FileOutputStream
|
|||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use downloader.Cache instead")
|
@Deprecated("Use downloader.Cache instead")
|
||||||
class Cache(context: Context) : ContextWrapper(context) {
|
class Cache(context: Context) : ContextWrapper(context) {
|
||||||
|
|
||||||
|
|||||||
@@ -37,9 +37,7 @@ import xyz.quaver.Code
|
|||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
import xyz.quaver.hitomi.imageUrlFromImage
|
import xyz.quaver.hitomi.imageUrlFromImage
|
||||||
import xyz.quaver.hiyobi.cookie
|
|
||||||
import xyz.quaver.hiyobi.createImgList
|
import xyz.quaver.hiyobi.createImgList
|
||||||
import xyz.quaver.hiyobi.user_agent
|
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.client
|
import xyz.quaver.pupil.client
|
||||||
import xyz.quaver.pupil.interceptors
|
import xyz.quaver.pupil.interceptors
|
||||||
@@ -48,6 +46,7 @@ import java.io.File
|
|||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.util.concurrent.LinkedBlockingQueue
|
import java.util.concurrent.LinkedBlockingQueue
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use DownloadService instead")
|
@Deprecated("Use DownloadService instead")
|
||||||
@OptIn(ExperimentalCoroutinesApi::class)
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
class DownloadWorker private constructor(context: Context) : ContextWrapper(context) {
|
||||||
@@ -219,8 +218,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
|||||||
}
|
}
|
||||||
Code.HIYOBI -> {
|
Code.HIYOBI -> {
|
||||||
url(createImgList(galleryID, reader, lowQuality)[index].path)
|
url(createImgList(galleryID, reader, lowQuality)[index].path)
|
||||||
addHeader("User-Agent", user_agent)
|
|
||||||
addHeader("Cookie", cookie)
|
|
||||||
}
|
}
|
||||||
else -> {
|
else -> {
|
||||||
//shouldn't be called anyway
|
//shouldn't be called anyway
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import kotlinx.serialization.Serializable
|
|||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use downloader.Cache.Metadata instead")
|
@Deprecated("Use downloader.Cache.Metadata instead")
|
||||||
@Serializable
|
@Serializable
|
||||||
data class Metadata(
|
data class Metadata(
|
||||||
|
|||||||
@@ -34,10 +34,7 @@ import xyz.quaver.Code
|
|||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.io.FileX
|
import xyz.quaver.io.FileX
|
||||||
import xyz.quaver.io.util.getChild
|
import xyz.quaver.io.util.*
|
||||||
import xyz.quaver.io.util.readBytes
|
|
||||||
import xyz.quaver.io.util.readText
|
|
||||||
import xyz.quaver.io.util.writeBytes
|
|
||||||
import xyz.quaver.pupil.client
|
import xyz.quaver.pupil.client
|
||||||
import xyz.quaver.pupil.util.Preferences
|
import xyz.quaver.pupil.util.Preferences
|
||||||
|
|
||||||
@@ -60,6 +57,7 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW
|
|||||||
instances[galleryID] ?: Cache(context, galleryID).also { instances.put(galleryID, it) }
|
instances[galleryID] ?: Cache(context, galleryID).also { instances.put(galleryID, it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Synchronized
|
||||||
fun delete(galleryID: Int) {
|
fun delete(galleryID: Int) {
|
||||||
instances[galleryID]?.cacheFolder?.deleteRecursively()
|
instances[galleryID]?.cacheFolder?.deleteRecursively()
|
||||||
instances.delete(galleryID)
|
instances.delete(galleryID)
|
||||||
@@ -86,11 +84,11 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun findFile(fileName: String): FileX? =
|
fun findFile(fileName: String): FileX? =
|
||||||
cacheFolder.getChild(fileName).let {
|
downloadFolder?.let { downloadFolder -> downloadFolder.getChild(fileName).let {
|
||||||
if (it.exists()) it else null
|
if (it.exists()) it else null
|
||||||
} ?: downloadFolder?.let { downloadFolder -> downloadFolder.getChild(fileName).let {
|
} } ?: cacheFolder.getChild(fileName).let {
|
||||||
if (it.exists()) it else null
|
if (it.exists()) it else null
|
||||||
} }
|
}
|
||||||
|
|
||||||
@Suppress("BlockingMethodInNonBlockingContext")
|
@Suppress("BlockingMethodInNonBlockingContext")
|
||||||
fun setMetadata(change: (Metadata) -> Unit) {
|
fun setMetadata(change: (Metadata) -> Unit) {
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con
|
|||||||
|
|
||||||
downloadFolderMap[galleryID]?.let {
|
downloadFolderMap[galleryID]?.let {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
downloadFolder.getChild(it).delete()
|
downloadFolder.getChild(it).deleteRecursively()
|
||||||
downloadFolderMap.remove(galleryID)
|
downloadFolderMap.remove(galleryID)
|
||||||
|
|
||||||
downloadFolder.getChild(".download").let { if (!it.exists()) it.createNewFile() }
|
downloadFolder.getChild(".download").let { if (!it.exists()) it.createNewFile() }
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ import java.io.FileOutputStream
|
|||||||
import java.lang.reflect.Array
|
import java.lang.reflect.Array
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use downloader.Cache instead")
|
@Deprecated("Use downloader.Cache instead")
|
||||||
fun getCachedGallery(context: Context, galleryID: Int) =
|
fun getCachedGallery(context: Context, galleryID: Int) =
|
||||||
File(getDownloadDirectory(context), galleryID.toString()).let {
|
File(getDownloadDirectory(context), galleryID.toString()).let {
|
||||||
@@ -36,6 +37,7 @@ fun getCachedGallery(context: Context, galleryID: Int) =
|
|||||||
File(context.cacheDir, "imageCache/$galleryID")
|
File(context.cacheDir, "imageCache/$galleryID")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use downloader.Cache instead")
|
@Deprecated("Use downloader.Cache instead")
|
||||||
fun getDownloadDirectory(context: Context) =
|
fun getDownloadDirectory(context: Context) =
|
||||||
Preferences.get<String>("dl_location").let {
|
Preferences.get<String>("dl_location").let {
|
||||||
@@ -45,6 +47,7 @@ fun getDownloadDirectory(context: Context) =
|
|||||||
context.getExternalFilesDir(null)!!
|
context.getExternalFilesDir(null)!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION")
|
||||||
@Deprecated("Use FileX instead")
|
@Deprecated("Use FileX instead")
|
||||||
fun File.isParentOf(another: File) =
|
fun File.isParentOf(another: File) =
|
||||||
another.absolutePath.startsWith(this.absolutePath)
|
another.absolutePath.startsWith(this.absolutePath)
|
||||||
@@ -22,11 +22,6 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.coroutineScope
|
|
||||||
import kotlinx.coroutines.runBlocking
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import xyz.quaver.Code
|
import xyz.quaver.Code
|
||||||
@@ -34,11 +29,7 @@ import xyz.quaver.hitomi.GalleryBlock
|
|||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
import xyz.quaver.hitomi.getReferer
|
import xyz.quaver.hitomi.getReferer
|
||||||
import xyz.quaver.hitomi.imageUrlFromImage
|
import xyz.quaver.hitomi.imageUrlFromImage
|
||||||
import xyz.quaver.hiyobi.cookie
|
|
||||||
import xyz.quaver.hiyobi.createImgList
|
import xyz.quaver.hiyobi.createImgList
|
||||||
import xyz.quaver.hiyobi.user_agent
|
|
||||||
import xyz.quaver.pupil.util.downloader.Cache
|
|
||||||
import xyz.quaver.pupil.util.downloader.Metadata
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@@ -134,8 +125,6 @@ val Reader.requestBuilders: List<Request.Builder>
|
|||||||
createImgList(galleryID, this, lowQuality).map {
|
createImgList(galleryID, this, lowQuality).map {
|
||||||
Request.Builder()
|
Request.Builder()
|
||||||
.url(it.path)
|
.url(it.path)
|
||||||
.header("User-Agent", user_agent)
|
|
||||||
.header("Cookie", cookie)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import android.app.PendingIntent
|
|||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
|
import android.content.IntentFilter
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@@ -32,11 +33,13 @@ import androidx.appcompat.app.AlertDialog
|
|||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import okhttp3.Call
|
import okhttp3.Call
|
||||||
import okhttp3.Callback
|
import okhttp3.Callback
|
||||||
@@ -45,6 +48,8 @@ import okhttp3.Response
|
|||||||
import ru.noties.markwon.Markwon
|
import ru.noties.markwon.Markwon
|
||||||
import xyz.quaver.hitomi.GalleryBlock
|
import xyz.quaver.hitomi.GalleryBlock
|
||||||
import xyz.quaver.hitomi.Reader
|
import xyz.quaver.hitomi.Reader
|
||||||
|
import xyz.quaver.hitomi.getGalleryBlock
|
||||||
|
import xyz.quaver.hitomi.getReader
|
||||||
import xyz.quaver.io.FileX
|
import xyz.quaver.io.FileX
|
||||||
import xyz.quaver.io.util.getChild
|
import xyz.quaver.io.util.getChild
|
||||||
import xyz.quaver.io.util.*
|
import xyz.quaver.io.util.*
|
||||||
@@ -53,6 +58,7 @@ import xyz.quaver.pupil.R
|
|||||||
import xyz.quaver.pupil.client
|
import xyz.quaver.pupil.client
|
||||||
import xyz.quaver.pupil.services.DownloadService
|
import xyz.quaver.pupil.services.DownloadService
|
||||||
import xyz.quaver.pupil.util.downloader.Cache
|
import xyz.quaver.pupil.util.downloader.Cache
|
||||||
|
import xyz.quaver.pupil.util.downloader.Metadata
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
@@ -152,7 +158,7 @@ fun checkUpdate(context: Context, force: Boolean = false) {
|
|||||||
setTitle(R.string.update_title)
|
setTitle(R.string.update_title)
|
||||||
val msg = extractReleaseNote(update, Locale.getDefault())
|
val msg = extractReleaseNote(update, Locale.getDefault())
|
||||||
setMessage(Markwon.create(context).toMarkdown(msg))
|
setMessage(Markwon.create(context).toMarkdown(msg))
|
||||||
setPositiveButton(android.R.string.yes) { _, _ ->
|
setPositiveButton(android.R.string.ok) { _, _ ->
|
||||||
|
|
||||||
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||||
|
|
||||||
@@ -175,7 +181,7 @@ fun checkUpdate(context: Context, force: Boolean = false) {
|
|||||||
Preferences["update_download_id"] = it
|
Preferences["update_download_id"] = it
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setNegativeButton(if (force) android.R.string.no else R.string.ignore_update) { _, _ ->
|
setNegativeButton(if (force) android.R.string.cancel else R.string.ignore_update) { _, _ ->
|
||||||
if (!force)
|
if (!force)
|
||||||
preferences.edit()
|
preferences.edit()
|
||||||
.putLong("ignore_update_until", System.currentTimeMillis() + 604800000)
|
.putLong("ignore_update_until", System.currentTimeMillis() + 604800000)
|
||||||
@@ -226,12 +232,15 @@ private val receiver = object: BroadcastReceiver() {
|
|||||||
ACTION_CANCEL -> {
|
ACTION_CANCEL -> {
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
NotificationManagerCompat.from(context).cancel(R.id.notification_id_import)
|
NotificationManagerCompat.from(context).cancel(R.id.notification_id_import)
|
||||||
|
context.unregisterReceiver(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@SuppressLint("RestrictedApi")
|
@SuppressLint("RestrictedApi")
|
||||||
fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
||||||
|
registerReceiver(receiver, IntentFilter().apply { addAction(receiver.ACTION_CANCEL) })
|
||||||
|
|
||||||
val notificationManager = NotificationManagerCompat.from(this)
|
val notificationManager = NotificationManagerCompat.from(this)
|
||||||
val action = NotificationCompat.Action.Builder(0, getText(android.R.string.cancel),
|
val action = NotificationCompat.Action.Builder(0, getText(android.R.string.cancel),
|
||||||
PendingIntent.getBroadcast(this, R.id.notification_import_cancel_action.normalizeID(), Intent(receiver.ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)
|
PendingIntent.getBroadcast(this, R.id.notification_import_cancel_action.normalizeID(), Intent(receiver.ACTION_CANCEL), PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
@@ -247,55 +256,65 @@ fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
|||||||
|
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
job = CoroutineScope(Dispatchers.IO).launch {
|
job = CoroutineScope(Dispatchers.IO).launch {
|
||||||
val folders = downloadFolder.listFiles { folder ->
|
val downloadFolders = downloadFolder.listFiles { folder ->
|
||||||
(folder as? FileX)?.isDirectory == true && !downloadFolderMap.values.contains(folder.name)
|
(folder as? FileX)?.isDirectory == true && !downloadFolderMap.values.contains(folder.name)
|
||||||
}
|
}
|
||||||
if (folders.isNullOrEmpty()) return@launch
|
|
||||||
folders.forEachIndexed { index, folder ->
|
if (downloadFolders.isNullOrEmpty()) return@launch
|
||||||
|
|
||||||
|
downloadFolders.forEachIndexed { index, folder ->
|
||||||
notification
|
notification
|
||||||
.setContentText(getString(R.string.import_old_galleries_notification_text, index, folders.size))
|
.setContentText(getString(R.string.import_old_galleries_notification_text, index, downloadFolders.size))
|
||||||
.setProgress(index, folders.size, false)
|
.setProgress(index, downloadFolders.size, false)
|
||||||
notificationManager.notify(R.id.notification_id_import, notification.build())
|
notificationManager.notify(R.id.notification_id_import, notification.build())
|
||||||
|
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val folder = (folder as? FileX) ?: return@runCatching
|
if (folder !is FileX) return@runCatching
|
||||||
|
|
||||||
val metadata = folder.getChild(".metadata").readText()?.let { Json.parseToJsonElement(it).jsonObject } ?: return@runCatching
|
val metadata = kotlin.runCatching {
|
||||||
|
folder.getChild(".metadata").readText()?.let { Json.parseToJsonElement(it).jsonObject }
|
||||||
|
}.getOrNull()
|
||||||
|
|
||||||
val galleryBlock: GalleryBlock? =
|
val galleryID = folder.name.toIntOrNull() ?: return@runCatching
|
||||||
metadata["galleryBlock"]?.let { Json.decodeFromJsonElement<GalleryBlock>(it) }
|
|
||||||
val reader: Reader? =
|
|
||||||
metadata["reader"]?.let { Json.decodeFromJsonElement<Reader>(it) }
|
|
||||||
|
|
||||||
val galleryID = galleryBlock?.id ?: reader?.galleryInfo?.id ?: folder.name.toIntOrNull() ?: return@runCatching
|
val galleryBlock: GalleryBlock? = kotlin.runCatching {
|
||||||
|
metadata?.get("galleryBlock")?.let { Json.decodeFromJsonElement<GalleryBlock>(it) }
|
||||||
|
}.getOrNull() ?: getGalleryBlock(galleryID)
|
||||||
|
val reader: Reader? = kotlin.runCatching {
|
||||||
|
metadata?.get("reader")?.let { Json.decodeFromJsonElement<Reader>(it) }
|
||||||
|
}.getOrNull() ?: getReader(galleryID)
|
||||||
|
|
||||||
metadata["thumbnail"]?.jsonPrimitive?.contentOrNull.let { thumbnail ->
|
metadata?.get("thumbnail")?.jsonPrimitive?.contentOrNull?.also { thumbnail ->
|
||||||
val file = folder.getChild(".thumbnail").also {
|
val file = folder.getChild(".thumbnail").also {
|
||||||
if (!it.exists())
|
if (it.exists())
|
||||||
|
it.delete()
|
||||||
it.createNewFile()
|
it.createNewFile()
|
||||||
}
|
}
|
||||||
|
|
||||||
file.writeBytes(Base64.decode(thumbnail, Base64.DEFAULT))
|
file.writeBytes(Base64.decode(thumbnail, Base64.DEFAULT))
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadFolderMap[galleryID] = folder.name
|
|
||||||
|
|
||||||
val cache = Cache.getInstance(this@migrate, galleryID)
|
|
||||||
|
|
||||||
val list: MutableList<String?> =
|
val list: MutableList<String?> =
|
||||||
MutableList(cache.getReader()!!.galleryInfo.files.size) { null }
|
MutableList(reader!!.galleryInfo.files.size) { null }
|
||||||
|
|
||||||
folder.listFiles { dir ->
|
folder.listFiles { file ->
|
||||||
dir?.nameWithoutExtension?.toIntOrNull() != null
|
file?.nameWithoutExtension?.let {
|
||||||
|
Regex("""\d{5}""").matches(it) && it.toIntOrNull() != null
|
||||||
|
} == true
|
||||||
}?.forEach {
|
}?.forEach {
|
||||||
list[it.nameWithoutExtension.toInt()] = it.name
|
list[it.nameWithoutExtension.toInt()] = it.name
|
||||||
}
|
}
|
||||||
|
|
||||||
cache.setMetadata {
|
folder.getChild(".metadata").also { if (it.exists()) it.delete(); it.createNewFile() }.writeText(
|
||||||
it.galleryBlock = galleryBlock
|
Json.encodeToString(Metadata(galleryBlock, reader, list))
|
||||||
it.reader = reader
|
)
|
||||||
it.imageList = list
|
|
||||||
|
synchronized(Cache) {
|
||||||
|
Cache.delete(galleryID)
|
||||||
}
|
}
|
||||||
|
downloadFolderMap[galleryID] = folder.name
|
||||||
|
|
||||||
|
downloadFolder.getChild(".download").let { if (!it.exists()) it.createNewFile(); it.writeText(Json.encodeToString(downloadFolderMap)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,5 +324,9 @@ fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
|||||||
.setOngoing(false)
|
.setOngoing(false)
|
||||||
.mActions.clear()
|
.mActions.clear()
|
||||||
notificationManager.notify(R.id.notification_id_import, notification.build())
|
notificationManager.notify(R.id.notification_id_import, notification.build())
|
||||||
|
|
||||||
|
kotlin.runCatching {
|
||||||
|
unregisterReceiver(receiver)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -63,19 +63,23 @@
|
|||||||
android:text="@string/main_no_result"
|
android:text="@string/main_no_result"
|
||||||
android:visibility="invisible"/>
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
|
<com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:handleHeight="100dp"
|
||||||
|
app:addLastItemPadding="true"
|
||||||
|
app:popupDrawable="@color/transparent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/main_recyclerview"
|
android:id="@+id/main_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingTop="64dp"
|
android:paddingTop="64dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
app:fastScrollEnabled="true"
|
|
||||||
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollHorizontalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:fastScrollVerticalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
|
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionMenu
|
<com.github.clans.fab.FloatingActionMenu
|
||||||
android:id="@+id/main_fab"
|
android:id="@+id/main_fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -63,19 +63,23 @@
|
|||||||
android:text="@string/main_no_result"
|
android:text="@string/main_no_result"
|
||||||
android:visibility="invisible"/>
|
android:visibility="invisible"/>
|
||||||
|
|
||||||
|
<com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:handleHeight="100dp"
|
||||||
|
app:addLastItemPadding="true"
|
||||||
|
app:popupDrawable="@color/transparent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/main_recyclerview"
|
android:id="@+id/main_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingTop="64dp"
|
android:paddingTop="64dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
app:fastScrollEnabled="true"
|
|
||||||
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollHorizontalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:fastScrollVerticalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
|
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
||||||
|
|
||||||
<com.github.clans.fab.FloatingActionMenu
|
<com.github.clans.fab.FloatingActionMenu
|
||||||
android:id="@+id/main_fab"
|
android:id="@+id/main_fab"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -26,17 +26,21 @@
|
|||||||
android:background="@color/dark_gray"
|
android:background="@color/dark_gray"
|
||||||
tools:context=".ui.ReaderActivity">
|
tools:context=".ui.ReaderActivity">
|
||||||
|
|
||||||
|
<com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
app:handleHeight="100dp"
|
||||||
|
app:addLastItemPadding="true"
|
||||||
|
app:popupDrawable="@color/transparent">
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
android:id="@+id/reader_recyclerview"
|
android:id="@+id/reader_recyclerview"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:fastScrollEnabled="true"
|
|
||||||
app:fastScrollHorizontalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollVerticalThumbDrawable="@drawable/thumb_drawable"
|
|
||||||
app:fastScrollHorizontalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:fastScrollVerticalTrackDrawable="@drawable/track_drawable"
|
|
||||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"/>
|
||||||
|
|
||||||
|
</com.qtalk.recyclerviewfastscroller.RecyclerViewFastScroller>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ allprojects {
|
|||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
mavenLocal()
|
|
||||||
maven { url "https://jitpack.io" }
|
maven { url "https://jitpack.io" }
|
||||||
maven { url 'https://guardian.github.com/maven/repo-releases' }
|
maven { url 'https://guardian.github.com/maven/repo-releases' }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user