Compare commits
27 Commits
4.18.1
...
4.19-hotfi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
684c5cf38b | ||
|
|
c34e15f0a1 | ||
|
|
bad004f892 | ||
|
|
828d3de020 | ||
|
|
132b3b9be1 | ||
|
|
388bc6fda5 | ||
|
|
a93edc184d | ||
|
|
08672d10ac | ||
|
|
b563dae3a8 | ||
|
|
917f9672dd | ||
|
|
9ddb19530b | ||
|
|
431e56a9f1 | ||
|
|
71093aac4c | ||
|
|
47c9e8127e | ||
|
|
24b801b346 | ||
|
|
70608c3ed9 | ||
|
|
f185196e85 | ||
|
|
a8766a8bbe | ||
|
|
27a8c93cfe | ||
|
|
a3cd29fda9 | ||
|
|
adda8ab640 | ||
|
|
1538ea5fc8 | ||
|
|
2367a97a54 | ||
|
|
090ec0e4af | ||
|
|
de7f552e5c | ||
|
|
d763f5dca0 | ||
|
|
9f41116241 |
@@ -4,7 +4,6 @@
|
||||
*Pupil, Hitomi.la viewer for Android*
|
||||
|
||||
[](https://discord.gg/Stj4b5v)
|
||||
I can speak English, Japanese and Korean. If you have any questions, head over to my discord server or DM me!
|
||||
|
||||
# Screenshot
|
||||

|
||||
|
||||
@@ -19,8 +19,8 @@ android {
|
||||
applicationId "xyz.quaver.pupil"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 29
|
||||
versionCode 54
|
||||
versionName "4.18.1"
|
||||
versionCode 57
|
||||
versionName "4.19-hotfix2"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
multiDexEnabled true
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
@@ -64,19 +64,22 @@ dependencies {
|
||||
implementation "androidx.biometric:biometric:1.0.1"
|
||||
implementation 'androidx.multidex:multidex:2.0.1'
|
||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha01'
|
||||
implementation 'com.google.firebase:firebase-core:17.4.3'
|
||||
implementation 'com.google.firebase:firebase-analytics:17.4.3'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.1.0'
|
||||
implementation 'com.google.firebase:firebase-perf:19.0.7'
|
||||
implementation 'com.google.android.material:material:1.3.0-alpha02'
|
||||
implementation 'com.google.firebase:firebase-core:17.4.4'
|
||||
implementation 'com.google.firebase:firebase-analytics:17.4.4'
|
||||
implementation 'com.google.firebase:firebase-crashlytics:17.1.1'
|
||||
implementation 'com.google.firebase:firebase-perf:19.0.8'
|
||||
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
|
||||
implementation 'com.github.clans:fab:1.6.4'
|
||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||
implementation "com.github.bumptech.glide:okhttp3-integration:4.11.0"
|
||||
implementation 'com.github.bumptech.glide:annotations:4.11.0'
|
||||
annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||
implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
|
||||
transitive = false
|
||||
}
|
||||
implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2'
|
||||
implementation 'net.rdrei.android.dirchooser:library:3.2@aar'
|
||||
implementation 'com.github.chrisbanes:PhotoView:2.3.0'
|
||||
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"properties": [],
|
||||
"versionCode": 54,
|
||||
"versionName": "54",
|
||||
"versionCode": 57,
|
||||
"versionName": "4.19-hotfix2",
|
||||
"enabled": true,
|
||||
"outputFile": "app-release.apk"
|
||||
}
|
||||
@@ -99,7 +99,7 @@ class ExampleInstrumentedTest {
|
||||
while(worker.progress.indexOfKey(galleryID) < 0 || worker.progress[galleryID] != null) {
|
||||
Log.i("PUPILD", worker.progress[galleryID]?.joinToString(" ") ?: "null")
|
||||
|
||||
if (worker.progress[galleryID]?.all { !it.isFinite() } == true)
|
||||
if (worker.progress[galleryID]?.all { it.isInfinite() } == true)
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -71,13 +71,6 @@ class Pupil : MultiDexApplication() {
|
||||
preference.edit().remove("dl_location").apply()
|
||||
}
|
||||
|
||||
if (!preference.getBoolean("low_quality_reset", false)) {
|
||||
preference.edit()
|
||||
.putBoolean("low_quality", true)
|
||||
.putBoolean("low_quality_reset", true)
|
||||
.apply()
|
||||
}
|
||||
|
||||
histories = Histories(File(ContextCompat.getDataDir(this), "histories.json"))
|
||||
favorites = Histories(File(ContextCompat.getDataDir(this), "favorites.json"))
|
||||
|
||||
|
||||
42
app/src/main/java/xyz/quaver/pupil/PupilGlideModule.kt
Normal file
42
app/src/main/java/xyz/quaver/pupil/PupilGlideModule.kt
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2020 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/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil
|
||||
|
||||
import android.content.Context
|
||||
import com.bumptech.glide.Glide
|
||||
import com.bumptech.glide.Registry
|
||||
import com.bumptech.glide.annotation.GlideModule
|
||||
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.module.AppGlideModule
|
||||
import xyz.quaver.pupil.util.download.DownloadWorker
|
||||
import java.io.InputStream
|
||||
|
||||
@GlideModule
|
||||
class PupilGlideModule : AppGlideModule() {
|
||||
|
||||
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
||||
registry.append(
|
||||
GlideUrl::class.java,
|
||||
InputStream::class.java,
|
||||
OkHttpUrlLoader.Factory(DownloadWorker.getInstance(context).client)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
package xyz.quaver.pupil.adapters
|
||||
|
||||
import android.app.Activity
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
@@ -28,9 +29,6 @@ import com.bumptech.glide.RequestManager
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.load.model.GlideUrl
|
||||
import com.bumptech.glide.load.model.LazyHeaders
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
import kotlinx.android.synthetic.main.activity_reader.view.*
|
||||
import kotlinx.android.synthetic.main.item_reader.view.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -50,7 +48,8 @@ import kotlin.concurrent.schedule
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class ReaderAdapter(private val glide: RequestManager,
|
||||
private val galleryID: Int) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() {
|
||||
private val galleryID: Int,
|
||||
private val activity: Activity) : RecyclerView.Adapter<ReaderAdapter.ViewHolder>() {
|
||||
|
||||
var reader: Reader? = null
|
||||
val timer = Timer()
|
||||
@@ -149,33 +148,13 @@ class ReaderAdapter(private val glide: RequestManager,
|
||||
|
||||
glide.clear(holder.view.image)
|
||||
|
||||
if (progress?.isNaN() == true) {
|
||||
FirebaseCrashlytics.getInstance().recordException(
|
||||
DownloadWorker.getInstance(holder.view.context).exception[galleryID]?.get(position)!!
|
||||
)
|
||||
holder.view.reader_item_progressbar.progress =
|
||||
if (progress?.isInfinite() == true)
|
||||
100
|
||||
else
|
||||
progress?.roundToInt() ?: 0
|
||||
|
||||
glide
|
||||
.load(R.drawable.image_broken_variant)
|
||||
.into(holder.view.image)
|
||||
|
||||
Snackbar.make(holder.view.reader_layout, R.string.reader_error_retry, Snackbar.LENGTH_SHORT).apply {
|
||||
setAction(android.R.string.no) { }
|
||||
setAction(android.R.string.yes) {
|
||||
downloadWorker!!.cancel(galleryID)
|
||||
downloadWorker!!.queue.add(galleryID)
|
||||
}
|
||||
}.show()
|
||||
|
||||
return
|
||||
} else {
|
||||
holder.view.reader_item_progressbar.progress =
|
||||
if (progress?.isInfinite() == true)
|
||||
100
|
||||
else
|
||||
progress?.roundToInt() ?: 0
|
||||
|
||||
holder.view.image.setImageDrawable(null)
|
||||
}
|
||||
holder.view.image.setImageDrawable(null)
|
||||
|
||||
timer.schedule(1000) {
|
||||
CoroutineScope(Dispatchers.Main).launch {
|
||||
|
||||
@@ -22,9 +22,10 @@ import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.RequestManager
|
||||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import xyz.quaver.pupil.BuildConfig
|
||||
|
||||
class ThumbnailAdapter(private val glide: RequestManager, private val thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailAdapter.ViewHolder>() {
|
||||
class ThumbnailAdapter(private val glide: RequestManager, var thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(val view: ImageView) : RecyclerView.ViewHolder(view)
|
||||
|
||||
@@ -35,6 +36,7 @@ class ThumbnailAdapter(private val glide: RequestManager, private val thumbnails
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
glide
|
||||
.load(thumbnails[position])
|
||||
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||
.apply {
|
||||
if (BuildConfig.CENSOR)
|
||||
override(5, 8)
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Pupil, Hitomi.la viewer for Android
|
||||
* Copyright (C) 2020 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/>.
|
||||
*/
|
||||
|
||||
package xyz.quaver.pupil.adapters
|
||||
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.bumptech.glide.RequestManager
|
||||
import kotlin.math.min
|
||||
|
||||
class ThumbnailPageAdapter(private val glide: RequestManager, private val thumbnails: List<String>) : RecyclerView.Adapter<ThumbnailPageAdapter.ViewHolder>() {
|
||||
|
||||
class ViewHolder(val view: RecyclerView) : RecyclerView.ViewHolder(view)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||
return ViewHolder(RecyclerView(parent.context).apply {
|
||||
layoutManager = GridLayoutManager(parent.context, 3)
|
||||
adapter = ThumbnailAdapter(glide, listOf())
|
||||
layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
})
|
||||
}
|
||||
|
||||
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||
(holder.view.adapter as ThumbnailAdapter).apply {
|
||||
thumbnails = this@ThumbnailPageAdapter.thumbnails.slice(9*position until min(9*position+9, this@ThumbnailPageAdapter.thumbnails.size))
|
||||
notifyDataSetChanged()
|
||||
|
||||
holder.view.layoutManager?.scrollToPosition(itemCount-1)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getItemCount() = if (thumbnails.isEmpty()) 0 else thumbnails.size/9 + if (thumbnails.size%9 != 0) 1 else 0
|
||||
|
||||
}
|
||||
@@ -26,6 +26,7 @@ import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.text.*
|
||||
import android.text.style.AlignmentSpan
|
||||
import android.util.TypedValue
|
||||
import android.view.KeyEvent
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
@@ -440,8 +441,10 @@ class MainActivity : AppCompatActivity() {
|
||||
if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean("cache_disable", false))
|
||||
Toast.makeText(context, R.string.settings_download_when_cache_disable_warning, Toast.LENGTH_SHORT).show()
|
||||
else {
|
||||
if (Cache(context).isDownloading(galleryID)) //download in progress
|
||||
if (worker.progress.indexOfKey(galleryID) >= 0 && Cache(context).isDownloading(galleryID)) { //download in progress
|
||||
Cache(context).setDownloading(galleryID, false)
|
||||
worker.cancel(galleryID)
|
||||
}
|
||||
else {
|
||||
Cache(context).setDownloading(galleryID, true)
|
||||
|
||||
@@ -843,6 +846,9 @@ class MainActivity : AppCompatActivity() {
|
||||
|
||||
val tag = "${item.n}:${item.s.replace(Regex("\\s"), "_")}"
|
||||
|
||||
val color = TypedValue()
|
||||
theme.resolveAttribute(R.attr.colorControlNormal, color, true)
|
||||
|
||||
leftIcon.setImageDrawable(
|
||||
ResourcesCompat.getDrawable(
|
||||
resources,
|
||||
@@ -856,7 +862,7 @@ class MainActivity : AppCompatActivity() {
|
||||
"artist" -> R.drawable.brush
|
||||
else -> R.drawable.tag
|
||||
},
|
||||
null)
|
||||
context.theme)
|
||||
)
|
||||
|
||||
with(suggestionView.findViewById<ImageView>(R.id.right_icon)) {
|
||||
|
||||
@@ -264,6 +264,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
|
||||
private fun initDownloader() {
|
||||
val worker = DownloadWorker.getInstance(this).apply {
|
||||
cancel(galleryID)
|
||||
queue.add(galleryID)
|
||||
}
|
||||
|
||||
@@ -280,7 +281,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
|
||||
runOnUiThread {
|
||||
reader_download_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
|
||||
reader_download_progressbar.progress = worker.progress[galleryID]?.count { !it.isFinite() } ?: 0
|
||||
reader_download_progressbar.progress = worker.progress[galleryID]?.count { it.isInfinite() } ?: 0
|
||||
reader_progressbar.max = reader_recyclerview.adapter?.itemCount ?: 0
|
||||
|
||||
if (title == getString(R.string.reader_loading)) {
|
||||
@@ -305,7 +306,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
if (worker.progress[galleryID]?.all { !it.isFinite() } == true) { //Download finished
|
||||
if (worker.progress[galleryID]?.all { it.isInfinite() } == true) { //Download finished
|
||||
reader_download_progressbar.visibility = View.GONE
|
||||
|
||||
animateDownloadFAB(false)
|
||||
@@ -316,7 +317,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
|
||||
private fun initView() {
|
||||
with(reader_recyclerview) {
|
||||
adapter = ReaderAdapter(Glide.with(this@ReaderActivity), galleryID).apply {
|
||||
adapter = ReaderAdapter(Glide.with(this@ReaderActivity), galleryID, this@ReaderActivity).apply {
|
||||
onItemClickListener = {
|
||||
if (isScroll) {
|
||||
isScroll = false
|
||||
@@ -428,7 +429,7 @@ class ReaderActivity : AppCompatActivity() {
|
||||
icon?.registerAnimationCallback(object : Animatable2Compat.AnimationCallback() {
|
||||
override fun onAnimationEnd(drawable: Drawable?) {
|
||||
val worker = DownloadWorker.getInstance(context)
|
||||
if (worker.progress[galleryID]?.all { !it.isFinite() } == true) // If download is finished, stop animating
|
||||
if (worker.progress[galleryID]?.all { it.isInfinite() } == true) // If download is finished, stop animating
|
||||
post {
|
||||
setImageResource(R.drawable.ic_download)
|
||||
labelText = getString(R.string.reader_fab_download_cancel)
|
||||
|
||||
@@ -26,14 +26,15 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.widget.LinearLayout.LayoutParams
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import androidx.viewpager2.widget.ViewPager2
|
||||
import com.bumptech.glide.RequestManager
|
||||
import com.google.android.material.chip.Chip
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.dialog_gallery.*
|
||||
import kotlinx.android.synthetic.main.gallery_details.view.*
|
||||
import kotlinx.android.synthetic.main.dialog_gallery_details.view.*
|
||||
import kotlinx.android.synthetic.main.dialog_gallery_dotindicator.view.*
|
||||
import kotlinx.android.synthetic.main.item_gallery_details.view.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -46,7 +47,7 @@ import xyz.quaver.pupil.BuildConfig
|
||||
import xyz.quaver.pupil.Pupil
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
|
||||
import xyz.quaver.pupil.adapters.ThumbnailAdapter
|
||||
import xyz.quaver.pupil.adapters.ThumbnailPageAdapter
|
||||
import xyz.quaver.pupil.types.Tag
|
||||
import xyz.quaver.pupil.ui.ReaderActivity
|
||||
import xyz.quaver.pupil.util.ItemClickSupport
|
||||
@@ -130,7 +131,7 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
|
||||
private fun addDetails(gallery: Gallery) {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
|
||||
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||
inflater.inflate(R.layout.dialog_gallery_details, gallery_contents, false).apply {
|
||||
gallery_details.setText(R.string.gallery_details)
|
||||
|
||||
listOf(
|
||||
@@ -206,15 +207,21 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
|
||||
private fun addThumbnails(gallery: Gallery) {
|
||||
val inflater = LayoutInflater.from(context)
|
||||
|
||||
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||
inflater.inflate(R.layout.dialog_gallery_details, gallery_contents, false).apply {
|
||||
gallery_details.setText(R.string.gallery_thumbnails)
|
||||
|
||||
RecyclerView(context).apply {
|
||||
layoutManager = GridLayoutManager(context, 3)
|
||||
adapter = ThumbnailAdapter(glide, gallery.thumbnails)
|
||||
}.let {
|
||||
gallery_details_contents.addView(it, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
|
||||
val pager = ViewPager2(context).apply {
|
||||
adapter = ThumbnailPageAdapter(glide, gallery.thumbnails)
|
||||
}
|
||||
|
||||
gallery_details_contents.addView(
|
||||
pager,
|
||||
LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
||||
)
|
||||
|
||||
LayoutInflater.from(context).inflate(R.layout.dialog_gallery_dotindicator, gallery_details_contents)
|
||||
|
||||
gallery_dotindicator.setViewPager2(pager)
|
||||
}.let {
|
||||
gallery_contents.addView(it)
|
||||
}
|
||||
@@ -245,7 +252,7 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
|
||||
}
|
||||
}
|
||||
|
||||
inflater.inflate(R.layout.gallery_details, gallery_contents, false).apply {
|
||||
inflater.inflate(R.layout.dialog_gallery_details, gallery_contents, false).apply {
|
||||
gallery_details.setText(R.string.gallery_related)
|
||||
|
||||
RecyclerView(context).apply {
|
||||
|
||||
@@ -21,7 +21,6 @@ package xyz.quaver.pupil.util.download
|
||||
import android.content.Context
|
||||
import android.content.ContextWrapper
|
||||
import android.util.Base64
|
||||
import android.util.Log
|
||||
import android.util.SparseArray
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.firebase.crashlytics.FirebaseCrashlytics
|
||||
@@ -69,7 +68,7 @@ class Cache(context: Context) : ContextWrapper(context) {
|
||||
// Search in this order
|
||||
// Download -> Cache
|
||||
fun getCachedGallery(galleryID: Int) = getCachedGallery(this, galleryID).also {
|
||||
if (!it.exists() && !preference.getBoolean("cache_disable", false))
|
||||
if (!it.exists())
|
||||
it.mkdirs()
|
||||
}
|
||||
|
||||
@@ -289,17 +288,17 @@ class Cache(context: Context) : ContextWrapper(context) {
|
||||
if (download.isParentOf(cache))
|
||||
return@launch
|
||||
|
||||
Log.i("PUPILD", "MOVING ${cache.canonicalPath} --> ${download.canonicalPath}")
|
||||
FirebaseCrashlytics.getInstance().log("MOVING ${cache.canonicalPath} --> ${download.canonicalPath}")
|
||||
|
||||
cache.copyRecursively(download, true) { file, err ->
|
||||
Log.i("PUPILD", "MOVING ERROR ${file.canonicalPath} ${err.message}")
|
||||
FirebaseCrashlytics.getInstance().log("MOVING ERROR ${file.canonicalPath} ${err.message}")
|
||||
OnErrorAction.SKIP
|
||||
}
|
||||
Log.i("PUPILD", "MOVED ${cache.canonicalPath}")
|
||||
FirebaseCrashlytics.getInstance().log("MOVED ${cache.canonicalPath}")
|
||||
|
||||
Log.i("PUPILD", "DELETING ${cache.canonicalPath}")
|
||||
FirebaseCrashlytics.getInstance().log("DELETING ${cache.canonicalPath}")
|
||||
cache.deleteRecursively()
|
||||
Log.i("PUPILD", "DELETED ${cache.canonicalPath}")
|
||||
FirebaseCrashlytics.getInstance().log("DELETED ${cache.canonicalPath}")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -128,22 +128,9 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
* SECONDARY VALUE
|
||||
* 0 <= value < 100 -> Download in progress
|
||||
* Float.POSITIVE_INFINITY -> Download completed
|
||||
* Float.NaN -> Exception
|
||||
*/
|
||||
val progress = SparseArray<MutableList<Float>?>()
|
||||
/*
|
||||
* KEY
|
||||
* primary galleryID
|
||||
* secondary index
|
||||
* PRIMARY VALUE
|
||||
* MutableList -> Download in progress / Loading
|
||||
* null -> Gallery doesn't exist
|
||||
* SECONDARY VALUE
|
||||
* Throwable -> Exception
|
||||
* null -> Download in progress / Loading
|
||||
*/
|
||||
val exception = SparseArray<MutableList<Throwable?>?>()
|
||||
val notification = SparseArray<NotificationCompat.Builder>()
|
||||
val notification = SparseArray<NotificationCompat.Builder?>()
|
||||
|
||||
private val loop = loop()
|
||||
private val worker = SparseArray<Job?>()
|
||||
@@ -194,7 +181,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
}
|
||||
|
||||
progress.clear()
|
||||
exception.clear()
|
||||
notification.clear()
|
||||
notificationManager.cancelAll()
|
||||
}
|
||||
@@ -210,15 +196,11 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
}
|
||||
|
||||
progress.remove(galleryID)
|
||||
exception.remove(galleryID)
|
||||
notification.remove(galleryID)
|
||||
notificationManager.cancel(galleryID)
|
||||
|
||||
if (progress.indexOfKey(galleryID) >= 0)
|
||||
Cache(this@DownloadWorker).setDownloading(galleryID, false)
|
||||
}
|
||||
|
||||
fun isCompleted(galleryID: Int) = progress[galleryID]?.all { !it.isFinite() } == true
|
||||
fun isCompleted(galleryID: Int) = progress[galleryID]?.all { it.isInfinite() } == true
|
||||
|
||||
private fun queueDownload(galleryID: Int, reader: Reader, index: Int, callback: Callback) {
|
||||
val lowQuality = preferences.getBoolean("low_quality", false)
|
||||
@@ -248,8 +230,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
}.build()
|
||||
|
||||
client.newCall(request).enqueue(callback)
|
||||
|
||||
Log.i("PUPILD", "DOWNLOADING ($galleryID, $index) from ${request.url()}")
|
||||
}
|
||||
|
||||
private fun download(galleryID: Int) = CoroutineScope(Dispatchers.IO).launch {
|
||||
@@ -258,7 +238,6 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
//gallery doesn't exist
|
||||
if (reader == null) {
|
||||
progress.put(galleryID, null)
|
||||
exception.put(galleryID, null)
|
||||
|
||||
Cache(this@DownloadWorker).setDownloading(galleryID, false)
|
||||
return@launch
|
||||
@@ -272,12 +251,11 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
else
|
||||
0F
|
||||
}.toMutableList())
|
||||
exception.put(galleryID, reader.galleryInfo.files.map { null }.toMutableList())
|
||||
|
||||
if (notification[galleryID] == null)
|
||||
initNotification(galleryID)
|
||||
|
||||
notification[galleryID].setContentTitle(reader.galleryInfo.title)
|
||||
notification[galleryID]?.setContentTitle(reader.galleryInfo.title)
|
||||
notify(galleryID)
|
||||
|
||||
if (isCompleted(galleryID)) {
|
||||
@@ -294,30 +272,21 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
for (i in reader.galleryInfo.files.indices) {
|
||||
val callback = object : Callback {
|
||||
override fun onFailure(call: Call, e: IOException) {
|
||||
if (e.message?.contains("cancel", true) != false)
|
||||
return
|
||||
|
||||
Log.i("PUPILD", "FAIL ${call.request().tag()} (${e.message})")
|
||||
if (e.message?.contains("cancel", true) != true)
|
||||
FirebaseCrashlytics.getInstance().recordException(e)
|
||||
|
||||
progress[galleryID]?.set(i, Float.NaN)
|
||||
exception[galleryID]?.set(i, e)
|
||||
|
||||
notify(galleryID)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
if (isCompleted(galleryID)) {
|
||||
with(Cache(this@DownloadWorker)) {
|
||||
if (isDownloading(galleryID)) {
|
||||
moveToDownload(galleryID)
|
||||
setDownloading(galleryID, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
FirebaseCrashlytics.getInstance().apply {
|
||||
log("FAIL ${call.request().tag()} (${e.message})")
|
||||
setCustomKey("POS", "FAIL")
|
||||
recordException(e)
|
||||
}
|
||||
|
||||
cancel(galleryID)
|
||||
queue.add(galleryID)
|
||||
}
|
||||
|
||||
override fun onResponse(call: Call, response: Response) {
|
||||
Log.i("PUPILD", "OK ${call.request().tag()}")
|
||||
|
||||
val ext = call.request().url().encodedPath().split('.').last()
|
||||
|
||||
try {
|
||||
@@ -338,47 +307,29 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.i("PUPILD", "SUCCESS ${call.request().tag()}")
|
||||
} catch (e: Exception) {
|
||||
|
||||
progress[galleryID]?.set(i, Float.NaN)
|
||||
exception[galleryID]?.set(i, e)
|
||||
|
||||
notify(galleryID)
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
if (isCompleted(galleryID)) {
|
||||
with(Cache(this@DownloadWorker)) {
|
||||
if (isDownloading(galleryID)) {
|
||||
moveToDownload(galleryID)
|
||||
setDownloading(galleryID, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
FirebaseCrashlytics.getInstance().apply {
|
||||
log("FAIL ON OK ${call.request().tag()} (${e.message})")
|
||||
setCustomKey("POS", "FAIL ON OK")
|
||||
recordException(e)
|
||||
}
|
||||
|
||||
File(Cache(this@DownloadWorker).getCachedGallery(galleryID), "%05d.$ext".format(i)).delete()
|
||||
|
||||
Log.i("PUPILD", "FAIL ON OK ${call.request().tag()} (${e.message})")
|
||||
cancel(galleryID)
|
||||
queue.add(galleryID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (progress[galleryID]?.get(i)?.isFinite() == true) {
|
||||
if (progress[galleryID]?.get(i)?.isFinite() == true)
|
||||
queueDownload(galleryID, reader, i, callback)
|
||||
Log.i("PUPILD", "$galleryID QUEUED $i")
|
||||
} else {
|
||||
Log.i("PUPILD", "$galleryID SKIPPED $i (${progress[galleryID]?.get(i)})")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun notify(galleryID: Int) {
|
||||
val max = progress[galleryID]?.size ?: 0
|
||||
val progress = progress[galleryID]?.count { !it.isFinite() } ?: 0
|
||||
|
||||
Log.i("PUPILD", "NOTIFY $galleryID ${isCompleted(galleryID)} $progress/$max")
|
||||
val progress = progress[galleryID]?.count { it.isInfinite() } ?: 0
|
||||
|
||||
if (isCompleted(galleryID)) {
|
||||
notification[galleryID]
|
||||
@@ -394,7 +345,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
?.setContentText("$progress/$max")
|
||||
|
||||
if (Cache(this).isDownloading(galleryID) && notification[galleryID] != null)
|
||||
notificationManager.notify(galleryID, notification[galleryID].build())
|
||||
notification[galleryID]?.let { notificationManager.notify(galleryID, it.build()) }
|
||||
else
|
||||
notificationManager.cancel(galleryID)
|
||||
}
|
||||
@@ -432,9 +383,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
|
||||
initNotification(galleryID)
|
||||
|
||||
if (Cache(this@DownloadWorker).isDownloading(galleryID))
|
||||
notificationManager.notify(galleryID, notification[galleryID].build())
|
||||
|
||||
Log.i("PUPILD", "QUEUED $galleryID")
|
||||
notification[galleryID]?.let { notificationManager.notify(galleryID, it.build()) }
|
||||
|
||||
worker.put(galleryID, download(galleryID))
|
||||
queue.poll()
|
||||
|
||||
@@ -41,7 +41,7 @@ class Histories(private val file: File) : ArrayList<Int>() {
|
||||
fun load() : Histories {
|
||||
return apply {
|
||||
super.clear()
|
||||
addAll(
|
||||
super.addAll(
|
||||
json.parse(
|
||||
serializer,
|
||||
file.bufferedReader().use { it.readText() }
|
||||
@@ -67,6 +67,20 @@ class Histories(private val file: File) : ArrayList<Int>() {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun addAll(elements: Collection<Int>): Boolean {
|
||||
load()
|
||||
|
||||
for (e in elements) {
|
||||
if (contains(e))
|
||||
super.remove(e)
|
||||
super.add(0, e)
|
||||
}
|
||||
|
||||
save()
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun remove(element: Int): Boolean {
|
||||
load()
|
||||
val retval = super.remove(element)
|
||||
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M12,5.5A3.5,3.5 0 0,1 15.5,9A3.5,3.5 0 0,1 12,12.5A3.5,3.5 0 0,1 8.5,9A3.5,3.5 0 0,1 12,5.5M5,8C5.56,8 6.08,8.15 6.53,8.42C6.38,9.85 6.8,11.27 7.66,12.38C7.16,13.34 6.16,14 5,14A3,3 0 0,1 2,11A3,3 0 0,1 5,8M19,8A3,3 0 0,1 22,11A3,3 0 0,1 19,14C17.84,14 16.84,13.34 16.34,12.38C17.2,11.27 17.62,9.85 17.47,8.42C17.92,8.15 18.44,8 19,8M5.5,18.25C5.5,16.18 8.41,14.5 12,14.5C15.59,14.5 18.5,16.18 18.5,18.25V20H5.5V18.25M0,20V18.5C0,17.11 1.89,15.94 4.45,15.6C3.86,16.28 3.5,17.22 3.5,18.25V20H0M24,20H20.5V18.25C20.5,17.22 20.14,16.28 19.55,15.6C22.11,15.94 24,17.11 24,18.5V20Z" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M15,14C12.33,14 7,15.33 7,18V20H23V18C23,15.33 17.67,14 15,14M15,12A4,4 0 0,0 19,8A4,4 0 0,0 15,4A4,4 0 0,0 11,8A4,4 0 0,0 15,12M5,13.28L7.45,14.77L6.8,11.96L9,10.08L6.11,9.83L5,7.19L3.87,9.83L1,10.08L3.18,11.96L2.5,14.77L5,13.28Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M15,14C12.33,14 7,15.33 7,18V20H23V18C23,15.33 17.67,14 15,14M15,12A4,4 0 0,0 19,8A4,4 0 0,0 15,4A4,4 0 0,0 11,8A4,4 0 0,0 15,12M5,13.28L7.45,14.77L6.8,11.96L9,10.08L6.11,9.83L5,7.19L3.87,9.83L1,10.08L3.18,11.96L2.5,14.77L5,13.28Z" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M13,12H20V13.5H13M13,9.5H20V11H13M13,14.5H20V16H13M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M21,19H12V6H21" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M13,12H20V13.5H13M13,9.5H20V11H13M13,14.5H20V16H13M21,4H3A2,2 0 0,0 1,6V19A2,2 0 0,0 3,21H21A2,2 0 0,0 23,19V6A2,2 0 0,0 21,4M21,19H12V6H21" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M20.71,4.63L19.37,3.29C19,2.9 18.35,2.9 17.96,3.29L9,12.25L11.75,15L20.71,6.04C21.1,5.65 21.1,5 20.71,4.63M7,14A3,3 0 0,0 4,17C4,18.31 2.84,19 2,19C2.92,20.22 4.5,21 6,21A4,4 0 0,0 10,17A3,3 0 0,0 7,14Z" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M12,4A6,6 0 0,1 18,10C18,12.97 15.84,15.44 13,15.92V18H15V20H13V22H11V20H9V18H11V15.92C8.16,15.44 6,12.97 6,10A6,6 0 0,1 12,4M12,6A4,4 0 0,0 8,10A4,4 0 0,0 12,14A4,4 0 0,0 16,10A4,4 0 0,0 12,6Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M12,4A6,6 0 0,1 18,10C18,12.97 15.84,15.44 13,15.92V18H15V20H13V22H11V20H9V18H11V15.92C8.16,15.44 6,12.97 6,10A6,6 0 0,1 12,4M12,6A4,4 0 0,0 8,10A4,4 0 0,0 12,14A4,4 0 0,0 16,10A4,4 0 0,0 12,6Z" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M9,9C10.29,9 11.5,9.41 12.47,10.11L17.58,5H13V3H21V11H19V6.41L13.89,11.5C14.59,12.5 15,13.7 15,15A6,6 0 0,1 9,21A6,6 0 0,1 3,15A6,6 0 0,1 9,9M9,11A4,4 0 0,0 5,15A4,4 0 0,0 9,19A4,4 0 0,0 13,15A4,4 0 0,0 9,11Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M9,9C10.29,9 11.5,9.41 12.47,10.11L17.58,5H13V3H21V11H19V6.41L13.89,11.5C14.59,12.5 15,13.7 15,15A6,6 0 0,1 9,21A6,6 0 0,1 3,15A6,6 0 0,1 9,9M9,11A4,4 0 0,0 5,15A4,4 0 0,0 9,19A4,4 0 0,0 13,15A4,4 0 0,0 9,11Z" />
|
||||
</vector>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 67 KiB |
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M5.5,7A1.5,1.5 0 0,1 4,5.5A1.5,1.5 0 0,1 5.5,4A1.5,1.5 0 0,1 7,5.5A1.5,1.5 0 0,1 5.5,7M21.41,11.58L12.41,2.58C12.05,2.22 11.55,2 11,2H4C2.89,2 2,2.89 2,4V11C2,11.55 2.22,12.05 2.59,12.41L11.58,21.41C11.95,21.77 12.45,22 13,22C13.55,22 14.05,21.77 14.41,21.41L21.41,14.41C21.78,14.05 22,13.55 22,13C22,12.44 21.77,11.94 21.41,11.58Z" />
|
||||
</vector>
|
||||
@@ -4,5 +4,5 @@
|
||||
android:width="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path android:fillColor="#fff" android:pathData="M12.87,15.07L10.33,12.56L10.36,12.53C12.1,10.59 13.34,8.36 14.07,6H17V4H10V2H8V4H1V6H12.17C11.5,7.92 10.44,9.75 9,11.35C8.07,10.32 7.3,9.19 6.69,8H4.69C5.42,9.63 6.42,11.17 7.67,12.56L2.58,17.58L4,19L9,14L12.11,17.11L12.87,15.07M18.5,10H16.5L12,22H14L15.12,19H19.87L21,22H23L18.5,10M15.88,17L17.5,12.67L19.12,17H15.88Z" />
|
||||
<path android:fillColor="?attr/colorControlNormal" android:pathData="M12.87,15.07L10.33,12.56L10.36,12.53C12.1,10.59 13.34,8.36 14.07,6H17V4H10V2H8V4H1V6H12.17C11.5,7.92 10.44,9.75 9,11.35C8.07,10.32 7.3,9.19 6.69,8H4.69C5.42,9.63 6.42,11.17 7.67,12.56L2.58,17.58L4,19L9,14L12.11,17.11L12.87,15.07M18.5,10H16.5L12,22H14L15.12,19H19.87L21,22H23L18.5,10M15.88,17L17.5,12.67L19.12,17H15.88Z" />
|
||||
</vector>
|
||||
144
app/src/main/res/layout-v23/activity_main_content.xml
Normal file
144
app/src/main/res/layout-v23/activity_main_content.xml
Normal file
@@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Pupil, Hitomi.la viewer for Android
|
||||
~ Copyright (C) 2020 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/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/main_layout"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".ui.MainActivity">
|
||||
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:id="@+id/main_appbar_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@color/transparent"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent">
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="64dp"
|
||||
android:visibility="invisible"
|
||||
android:background="@color/transparent"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:id="@+id/main_progressbar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/main_noresult"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/main_no_result"
|
||||
android:visibility="invisible"/>
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/main_recyclerview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:paddingTop="64dp"
|
||||
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"/>
|
||||
|
||||
<com.github.clans.fab.FloatingActionMenu
|
||||
android:id="@+id/main_fab"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
app:menu_colorNormal="@color/colorAccent">
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/main_fab_cancel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fab_label="@string/main_fab_cancel"
|
||||
app:fab_size="mini"/>
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/main_fab_jump"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fab_label="@string/main_jump_title"
|
||||
app:fab_size="mini"/>
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/main_fab_random"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fab_label="@string/main_fab_random"
|
||||
app:fab_size="mini"/>
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/main_fab_id"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:fab_label="@string/main_open_gallery_by_id"
|
||||
app:fab_size="mini"/>
|
||||
|
||||
</com.github.clans.fab.FloatingActionMenu>
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
<com.arlib.floatingsearchview.FloatingSearchViewDayNight
|
||||
android:id="@+id/main_searchview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:floatingSearch_backgroundColor="?android:attr/colorBackgroundFloating"
|
||||
app:floatingSearch_leftActionColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_menuItemIconColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_actionMenuOverflowColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_clearBtnColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_viewTextColor="?android:attr/textColorPrimary"
|
||||
app:floatingSearch_suggestionRightIconColor="@color/material_orange_500"
|
||||
app:floatingSearch_searchBarMarginLeft="8dp"
|
||||
app:floatingSearch_searchBarMarginRight="8dp"
|
||||
app:floatingSearch_searchBarMarginTop="8dp"
|
||||
app:floatingSearch_searchHint="@string/search_hint"
|
||||
app:floatingSearch_suggestionsListAnimDuration="250"
|
||||
app:floatingSearch_showSearchKey="true"
|
||||
app:floatingSearch_leftActionMode="showHamburger"
|
||||
app:floatingSearch_menu="@menu/main"
|
||||
app:floatingSearch_dismissOnOutsideTouch="true"
|
||||
app:floatingSearch_close_search_on_keyboard_dismiss="true"
|
||||
tools:ignore="NewApi" />
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -122,12 +122,6 @@
|
||||
android:id="@+id/main_searchview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:floatingSearch_backgroundColor="?android:attr/colorBackgroundFloating"
|
||||
app:floatingSearch_leftActionColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_menuItemIconColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_actionMenuOverflowColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_clearBtnColor="?attr/colorControlNormal"
|
||||
app:floatingSearch_viewTextColor="?android:attr/textColorPrimary"
|
||||
app:floatingSearch_suggestionRightIconColor="@color/material_orange_500"
|
||||
app:floatingSearch_searchBarMarginLeft="8dp"
|
||||
app:floatingSearch_searchBarMarginRight="8dp"
|
||||
|
||||
34
app/src/main/res/layout/dialog_gallery_dotindicator.xml
Normal file
34
app/src/main/res/layout/dialog_gallery_dotindicator.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Pupil, Hitomi.la viewer for Android
|
||||
~ Copyright (C) 2020 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/>.
|
||||
-->
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp">
|
||||
|
||||
<com.tbuonomo.viewpagerdotsindicator.DotsIndicator
|
||||
android:id="@+id/gallery_dotindicator"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:dotsSize="8dp"/>
|
||||
|
||||
</RelativeLayout>
|
||||
@@ -19,11 +19,14 @@
|
||||
|
||||
<ImageView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="@dimen/nav_header_height"
|
||||
android:background="@drawable/side_nav_bar"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/side_nav_bar"
|
||||
android:adjustViewBounds="true"
|
||||
android:paddingBottom="@dimen/activity_vertical_margin"
|
||||
android:paddingLeft="@dimen/activity_horizontal_margin"
|
||||
android:paddingRight="@dimen/activity_horizontal_margin"
|
||||
android:paddingTop="@dimen/activity_vertical_margin"
|
||||
android:gravity="bottom"/>
|
||||
android:gravity="bottom"
|
||||
tools:ignore="ContentDescription" />
|
||||
@@ -148,6 +148,6 @@
|
||||
<string name="settings_download_when_cache_disable_warning">캐시를 활성화 해야 다운로드를 진행할 수 있습니다</string>
|
||||
<string name="settings_user_id">유저 ID</string>
|
||||
<string name="settings_user_id_toast">유저 ID를 클립보드에 복사했습니다</string>
|
||||
<string name="reader_error_retry">다운로드 에러가 발생했습니다. 재시도 하시겠습니까?</string>
|
||||
<string name="reader_error_retry">다운로드 에러가 발생했습니. 재시도 하시겠습니까?</string>
|
||||
<string name="reader_fab_retry">재시도</string>
|
||||
</resources>
|
||||
@@ -121,7 +121,7 @@
|
||||
<string name="reader_notification_complete">Download complete</string>
|
||||
<string name="reader_notification_error">Download error</string>
|
||||
|
||||
<string name="reader_error_retry">Download Error occurred. Retry?</string>
|
||||
<string name="reader_error_retry">Download Error. Retry?</string>
|
||||
|
||||
<string name="reader_help">Help</string>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ buildscript {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.0.0'
|
||||
classpath 'com.android.tools.build:gradle:4.0.1'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
|
||||
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"
|
||||
|
||||
@@ -83,7 +83,7 @@ fun getGalleryBlock(galleryID: Int) : GalleryBlock? {
|
||||
|
||||
val galleryUrl = doc.selectFirst(".lillie").attr("href")
|
||||
|
||||
val thumbnails = doc.select("img").map { protocol + it.attr("data-src") }
|
||||
val thumbnails = doc.select(".dj-img-cont img").map { protocol + it.attr("src") }
|
||||
|
||||
val title = doc.selectFirst("h1.lillie > a").text()
|
||||
val artists = doc.select("div.artist-list a").map{ it.text() }
|
||||
|
||||
Reference in New Issue
Block a user