Compare commits
7 Commits
5.0
...
5.0-hotfix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a8de1429c1 | ||
|
|
3ba6cb81ae | ||
|
|
acc85da80f | ||
|
|
b53de8624d | ||
|
|
6e2eeb29cc | ||
|
|
62eb28ac01 | ||
|
|
fd298529bf |
1
.idea/vcs.xml
generated
1
.idea/vcs.xml
generated
@@ -2,5 +2,6 @@
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
<mapping directory="$PROJECT_DIR$/gh-pages" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
@@ -20,8 +20,8 @@ android {
|
||||
applicationId "xyz.quaver.pupil"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
versionCode 57
|
||||
versionName "5.0-beta8"
|
||||
versionCode 58
|
||||
versionName "5.0-hotfix4"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
@@ -99,7 +99,7 @@ dependencies {
|
||||
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
|
||||
//implementation 'com.andrognito.pinlockview:pinlockview:2.1.0'
|
||||
implementation "ru.noties.markwon:core:3.1.0"
|
||||
implementation ("xyz.quaver:libpupil:1.5") {
|
||||
implementation ("xyz.quaver:libpupil:1.6") {
|
||||
exclude group: 'org.jetbrains.kotlinx', module: 'kotlinx-serialization-core-jvm'
|
||||
}
|
||||
implementation "xyz.quaver:documentfilex:0.2.15"
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"properties": [],
|
||||
"versionCode": 57,
|
||||
"versionName": "5.0-beta8",
|
||||
"versionCode": 58,
|
||||
"versionName": "5.0-hotfix4",
|
||||
"enabled": true,
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
|
||||
@@ -18,10 +18,7 @@
|
||||
|
||||
package xyz.quaver.pupil
|
||||
|
||||
import android.app.Application
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.*
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
@@ -43,6 +40,7 @@ import okhttp3.Response
|
||||
import xyz.quaver.io.FileX
|
||||
import xyz.quaver.pupil.types.Tag
|
||||
import xyz.quaver.pupil.util.*
|
||||
import xyz.quaver.pupil.util.downloader.DownloadManager
|
||||
import xyz.quaver.setClient
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
@@ -110,6 +108,8 @@ class Pupil : Application() {
|
||||
|
||||
if (!FileX(this, it).canWrite())
|
||||
throw Exception()
|
||||
|
||||
DownloadManager.getInstance(this).migrate()
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Preferences.remove("download_folder")
|
||||
|
||||
@@ -42,6 +42,7 @@ import xyz.quaver.hitomi.getReferer
|
||||
import xyz.quaver.hitomi.imageUrlFromImage
|
||||
import xyz.quaver.hiyobi.createImgList
|
||||
import xyz.quaver.io.util.readBytes
|
||||
import xyz.quaver.pupil.BuildConfig
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.services.DownloadService
|
||||
import xyz.quaver.pupil.ui.ReaderActivity
|
||||
@@ -81,14 +82,9 @@ class ReaderAdapter(private val activity: ReaderActivity,
|
||||
cache = Cache.getInstance(holder.view.context, galleryID)
|
||||
|
||||
if (isFullScreen) {
|
||||
holder.view.layoutParams.height = RecyclerView.LayoutParams.MATCH_PARENT
|
||||
holder.view.container.layoutParams.height = ConstraintLayout.LayoutParams.MATCH_PARENT
|
||||
} else {
|
||||
holder.view.layoutParams.height = RecyclerView.LayoutParams.WRAP_CONTENT
|
||||
holder.view.container.layoutParams.height = 0
|
||||
|
||||
(holder.view.container.layoutParams as ConstraintLayout.LayoutParams)
|
||||
.dimensionRatio = "W,${reader!!.galleryInfo.files[position].width}:${reader!!.galleryInfo.files[position].height}"
|
||||
holder.view.container.layoutParams.height = ConstraintLayout.LayoutParams.WRAP_CONTENT
|
||||
}
|
||||
|
||||
holder.view.image.setOnPhotoTapListener { _, _, _ ->
|
||||
@@ -122,7 +118,16 @@ class ReaderAdapter(private val activity: ReaderActivity,
|
||||
.load(url!!)
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(false)
|
||||
.fitCenter()
|
||||
.error(R.drawable.image_broken_variant)
|
||||
.apply {
|
||||
if (BuildConfig.CENSOR)
|
||||
override(5, 8)
|
||||
else
|
||||
override(
|
||||
holder.view.context.resources.displayMetrics.widthPixels,
|
||||
holder.view.context.resources.getDimensionPixelSize(R.dimen.reader_max_height)
|
||||
)
|
||||
}
|
||||
.error(R.drawable.image_broken_variant)
|
||||
.into(holder.view.image)
|
||||
}
|
||||
@@ -138,7 +143,15 @@ class ReaderAdapter(private val activity: ReaderActivity,
|
||||
.load(image.readBytes())
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.skipMemoryCache(true)
|
||||
.fitCenter()
|
||||
.apply {
|
||||
if (BuildConfig.CENSOR)
|
||||
override(5, 8)
|
||||
else
|
||||
override(
|
||||
holder.view.context.resources.displayMetrics.widthPixels,
|
||||
holder.view.context.resources.getDimensionPixelSize(R.dimen.reader_max_height)
|
||||
)
|
||||
}
|
||||
.error(R.drawable.image_broken_variant)
|
||||
.listener(object: RequestListener<Drawable> {
|
||||
override fun onLoadFailed(
|
||||
@@ -154,8 +167,13 @@ class ReaderAdapter(private val activity: ReaderActivity,
|
||||
return true
|
||||
}
|
||||
|
||||
override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean) =
|
||||
false
|
||||
override fun onResourceReady(
|
||||
resource: Drawable?,
|
||||
model: Any?,
|
||||
target: Target<Drawable>?,
|
||||
dataSource: DataSource?,
|
||||
isFirstResource: Boolean
|
||||
) = false
|
||||
}).let { launch(Dispatchers.Main) { it.into(holder.view.image) } }
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.util.SparseArray
|
||||
import androidx.core.app.NotificationCompat
|
||||
import androidx.core.app.NotificationManagerCompat
|
||||
import androidx.core.app.TaskStackBuilder
|
||||
import androidx.core.content.ContextCompat
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -46,7 +47,6 @@ import xyz.quaver.pupil.util.downloader.DownloadManager
|
||||
import xyz.quaver.pupil.util.ellipsize
|
||||
import xyz.quaver.pupil.util.normalizeID
|
||||
import xyz.quaver.pupil.util.requestBuilders
|
||||
import xyz.quaver.pupil.util.startForegroundServiceCompat
|
||||
import java.io.IOException
|
||||
|
||||
private typealias ProgressListener = (DownloadService.Tag, Long, Long, Boolean) -> Unit
|
||||
@@ -215,7 +215,7 @@ class DownloadService : Service() {
|
||||
val ext = call.request().url().encodedPath().split('.').last()
|
||||
|
||||
kotlin.runCatching {
|
||||
val image = response.body()?.use { it.bytes() } ?: throw Exception()
|
||||
val image = response.also { if (it.code() != 200) throw IOException() }.body()?.use { it.bytes() } ?: throw Exception()
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
kotlin.runCatching {
|
||||
@@ -354,7 +354,7 @@ class DownloadService : Service() {
|
||||
const val COMMAND_DELETE = "DELETE"
|
||||
|
||||
private fun command(context: Context, extras: Intent.() -> Unit) {
|
||||
context.startForegroundServiceCompat(Intent(context, DownloadService::class.java).apply(extras))
|
||||
ContextCompat.startForegroundService(context, Intent(context, DownloadService::class.java).apply(extras))
|
||||
}
|
||||
|
||||
fun download(context: Context, galleryID: Int, priority: Boolean = false) {
|
||||
@@ -381,6 +381,8 @@ class DownloadService : Service() {
|
||||
}
|
||||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
startForeground(R.id.downloader_notification_id, serviceNotification.build())
|
||||
|
||||
when (intent?.getStringExtra(KEY_COMMAND)) {
|
||||
COMMAND_DOWNLOAD -> intent.getIntExtra(KEY_ID, -1).let { if (it > 0)
|
||||
download(it, intent.getBooleanExtra(KEY_PRIORITY, false), startId)
|
||||
|
||||
@@ -39,10 +39,10 @@ import xyz.quaver.pupil.util.Lock
|
||||
import xyz.quaver.pupil.util.LockManager
|
||||
import xyz.quaver.pupil.util.Preferences
|
||||
|
||||
private var lastUnlocked = 0L
|
||||
class LockActivity : AppCompatActivity() {
|
||||
|
||||
private lateinit var lockManager: LockManager
|
||||
private var lastUnlocked = 0L
|
||||
private var mode: String? = null
|
||||
|
||||
private val patternLockFragment = PatternLockFragment().apply {
|
||||
|
||||
@@ -968,4 +968,14 @@ class MainActivity :
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
Glide.get(this).onLowMemory()
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
super.onTrimMemory(level)
|
||||
Glide.get(this).onTrimMemory(level)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import androidx.recyclerview.widget.PagerSnapHelper
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
|
||||
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
import com.bumptech.glide.Glide
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import kotlinx.android.synthetic.main.activity_reader.*
|
||||
@@ -473,4 +474,14 @@ class ReaderActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
Glide.get(this).onLowMemory()
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
super.onTrimMemory(level)
|
||||
Glide.get(this).onTrimMemory(level)
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
||||
.setView(build())
|
||||
.setPositiveButton(requireContext().getText(android.R.string.ok)) { _, _ ->
|
||||
if (Preferences["download_folder", ""].isEmpty())
|
||||
Preferences["download_folder"] = context?.getExternalFilesDir(null)?.canonicalPath ?: ""
|
||||
Preferences["download_folder"] = context?.getExternalFilesDir(null)?.toUri()?.toString() ?: ""
|
||||
|
||||
DownloadManager.getInstance(requireContext()).migrate()
|
||||
}
|
||||
|
||||
@@ -62,6 +62,11 @@ class ManageFavoritesFragment : PreferenceFragmentCompat() {
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.code() != 200) {
|
||||
response.close()
|
||||
return
|
||||
}
|
||||
|
||||
Intent(Intent.ACTION_SEND).apply {
|
||||
type = "text/plain"
|
||||
putExtra(Intent.EXTRA_TEXT, response.body()?.use { it.string() }?.replace("\n", ""))
|
||||
|
||||
@@ -277,6 +277,12 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
if (response.code() != 200) {
|
||||
response.close()
|
||||
onFailure(call, IOException())
|
||||
return
|
||||
}
|
||||
|
||||
val ext = call.request().url().encodedPath().split('.').last()
|
||||
|
||||
try {
|
||||
|
||||
@@ -37,6 +37,7 @@ import xyz.quaver.io.FileX
|
||||
import xyz.quaver.io.util.*
|
||||
import xyz.quaver.pupil.client
|
||||
import xyz.quaver.pupil.util.Preferences
|
||||
import java.io.IOException
|
||||
|
||||
@Serializable
|
||||
data class Metadata(
|
||||
@@ -138,7 +139,7 @@ class Cache private constructor(context: Context, val galleryID: Int) : ContextW
|
||||
.url(it)
|
||||
.build()
|
||||
|
||||
client.newCall(request).execute().body()?.use { it.bytes() }
|
||||
client.newCall(request).execute().also { if (it.code() != 200) throw IOException() }.body()?.use { it.bytes() }
|
||||
}.getOrNull()?.also { kotlin.run {
|
||||
cacheFolder.getChild(".thumbnail").writeBytes(it)
|
||||
} }
|
||||
|
||||
@@ -75,7 +75,6 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con
|
||||
|
||||
data ?: {
|
||||
file.createNewFile()
|
||||
file.writeText("{}")
|
||||
mutableMapOf<Int, String>()
|
||||
}.invoke()
|
||||
}.invoke()
|
||||
@@ -99,9 +98,6 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con
|
||||
|
||||
@Synchronized
|
||||
fun addDownloadFolder(galleryID: Int) {
|
||||
if (downloadFolderMap.containsKey(galleryID))
|
||||
return
|
||||
|
||||
val name = runBlocking {
|
||||
Cache.getInstance(this@DownloadManager, galleryID).getGalleryBlock()
|
||||
}?.formatDownloadFolder() ?: return
|
||||
@@ -119,9 +115,6 @@ class DownloadManager private constructor(context: Context) : ContextWrapper(con
|
||||
|
||||
@Synchronized
|
||||
fun deleteDownloadFolder(galleryID: Int) {
|
||||
if (!downloadFolderMap.containsKey(galleryID))
|
||||
return
|
||||
|
||||
downloadFolderMap[galleryID]?.let {
|
||||
kotlin.runCatching {
|
||||
downloadFolder.getChild(it).deleteRecursively()
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import androidx.core.content.ContextCompat
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import xyz.quaver.Code
|
||||
@@ -92,21 +93,14 @@ fun GalleryBlock.formatDownloadFolder(): String =
|
||||
formatMap.entries.fold(it) { str, (k, v) ->
|
||||
str.replace(k, v.invoke(this), true)
|
||||
}
|
||||
}
|
||||
}.replace("/", "")
|
||||
|
||||
fun GalleryBlock.formatDownloadFolderTest(format: String): String =
|
||||
format.let {
|
||||
formatMap.entries.fold(it) { str, (k, v) ->
|
||||
str.replace(k, v.invoke(this), true)
|
||||
}
|
||||
}
|
||||
|
||||
fun Context.startForegroundServiceCompat(service: Intent) {
|
||||
if (Build.VERSION.SDK_INT >= 26)
|
||||
startForegroundService(service)
|
||||
else
|
||||
startService(service)
|
||||
}
|
||||
}.replace("/", "")
|
||||
|
||||
val Reader.requestBuilders: List<Request.Builder>
|
||||
get() {
|
||||
|
||||
@@ -214,7 +214,7 @@ fun restore(url: String, onFailure: ((Throwable) -> Unit)? = null, onSuccess: ((
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
kotlin.runCatching {
|
||||
Json.decodeFromString<List<Int>>(response.body().use { it?.string() } ?: "[]").let {
|
||||
Json.decodeFromString<List<Int>>(response.also { if (it.code() != 200) throw IOException() }.body().use { it?.string() } ?: "[]").let {
|
||||
favorites.addAll(it)
|
||||
onSuccess?.invoke(it)
|
||||
}
|
||||
@@ -258,7 +258,12 @@ fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
||||
job?.cancel()
|
||||
job = CoroutineScope(Dispatchers.IO).launch {
|
||||
val downloadFolders = downloadFolder.listFiles { folder ->
|
||||
(folder as? FileX)?.isDirectory == true && !downloadFolderMap.values.contains(folder.name)
|
||||
folder.isDirectory && !downloadFolderMap.values.contains(folder.name)
|
||||
}?.map {
|
||||
if (it !is FileX)
|
||||
FileX(this@migrate, it)
|
||||
else
|
||||
it
|
||||
}
|
||||
|
||||
if (downloadFolders.isNullOrEmpty()) return@launch
|
||||
@@ -270,8 +275,6 @@ fun xyz.quaver.pupil.util.downloader.DownloadManager.migrate() {
|
||||
notificationManager.notify(R.id.notification_id_import, notification.build())
|
||||
|
||||
kotlin.runCatching {
|
||||
if (folder !is FileX) return@runCatching
|
||||
|
||||
val metadata = kotlin.runCatching {
|
||||
folder.getChild(".metadata").readText()?.let { Json.parseToJsonElement(it).jsonObject }
|
||||
}.getOrNull()
|
||||
|
||||
@@ -17,61 +17,52 @@
|
||||
~ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
app:layout_constraintHeight_max="2000dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
android:paddingBottom="8dp"
|
||||
android:background="@drawable/reader_item_boundary">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintHeight_max="2000dp"
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:background="@drawable/reader_item_boundary">
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
<ProgressBar
|
||||
android:id="@+id/reader_item_progressbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
style="?android:progressBarStyleHorizontal"
|
||||
android:indeterminate="false"
|
||||
android:progress="0"
|
||||
android:max="100"
|
||||
android:visibility="visible"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/reader_item_progressbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="?android:progressBarStyleHorizontal"
|
||||
android:indeterminate="false"
|
||||
android:progress="0"
|
||||
android:max="100"
|
||||
android:visibility="visible"/>
|
||||
<TextView
|
||||
android:id="@+id/reader_index"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AppCompat.Caption"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/reader_index"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/TextAppearance.AppCompat.Caption"/>
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
android:id="@+id/image"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitCenter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
android:paddingBottom="8dp"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<com.github.chrisbanes.photoview.PhotoView
|
||||
android:id="@+id/image"
|
||||
android:adjustViewBounds="true"
|
||||
android:scaleType="fitXY"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@@ -5,4 +5,6 @@
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
<dimen name="galleryblock_thumbnail_thin">100dp</dimen>
|
||||
|
||||
<dimen name="reader_max_height">2000dp</dimen>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user