diff --git a/.idea/misc.xml b/.idea/misc.xml
index 84da703c..7631aec3 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index 989ed597..9b1f14c2 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -1,5 +1,6 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlinx-serialization'
apply plugin: 'com.google.gms.google-services'
@@ -52,8 +53,13 @@ dependencies {
implementation 'com.crashlytics.sdk.android:crashlytics:2.10.1'
implementation 'com.github.arimorty:floatingsearchview:2.1.1'
implementation 'com.github.clans:fab:1.6.4'
+ implementation 'com.github.bumptech.glide:glide:4.9.0'
+ implementation ("com.github.bumptech.glide:recyclerview-integration:4.9.0") {
+ transitive = false
+ }
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'
implementation "ru.noties.markwon:core:${markwonVersion}"
+ kapt 'com.github.bumptech.glide:compiler:4.9.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test:rules:1.2.0'
diff --git a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
index 68b23485..bf314f69 100644
--- a/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
+++ b/app/src/main/java/xyz/quaver/pupil/adapters/GalleryBlockAdapter.kt
@@ -3,7 +3,6 @@ package xyz.quaver.pupil.adapters
import android.app.AlertDialog
import android.graphics.BitmapFactory
import android.graphics.drawable.Drawable
-import android.util.Log
import android.util.SparseBooleanArray
import android.view.LayoutInflater
import android.view.View
@@ -15,6 +14,8 @@ import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import androidx.vectordrawable.graphics.drawable.Animatable2Compat
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat
+import com.bumptech.glide.Glide
+import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.google.android.material.chip.Chip
import kotlinx.android.synthetic.main.item_galleryblock.view.*
import kotlinx.coroutines.CoroutineScope
@@ -23,9 +24,8 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
-import kotlinx.serialization.list
import xyz.quaver.hitomi.GalleryBlock
-import xyz.quaver.hitomi.ReaderItem
+import xyz.quaver.hitomi.Reader
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.types.Tag
@@ -47,8 +47,8 @@ class GalleryBlockAdapter(private val galleries: List>) {
+ inner class GalleryViewHolder(val view: CardView) : RecyclerView.ViewHolder(view) {
+ fun bind(holder: GalleryViewHolder, item: Pair>) {
with(view) {
val resources = context.resources
val languages = resources.getStringArray(R.array.languages).map {
@@ -62,17 +62,15 @@ class GalleryBlockAdapter(private val galleries: List) : RecyclerView.Adapter() {
@@ -25,47 +25,19 @@ class ReaderAdapter(private val images: List) : RecyclerView.Adapter reqHeight || width > reqWidth) {
-
- val halfHeight: Int = height / 2
- val halfWidth: Int = width / 2
-
- // Calculate the largest inSampleSize value that is a power of 2 and keeps both
- // height and width larger than the requested height and width.
- while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
- inSampleSize *= 2
- }
- }
-
- return inSampleSize
+ val progressDrawable = CircularProgressDrawable(holder.view.context).apply {
+ strokeWidth = 10f
+ centerRadius = 100f
+ start()
}
- with(holder.view as ImageView) {
- val options = BitmapFactory.Options()
-
- options.inJustDecodeBounds = true
- BitmapFactory.decodeFile(images[position], options)
-
- val (reqWidth, reqHeight) = context.resources.displayMetrics.let {
- Pair(it.widthPixels, it.heightPixels)
- }
-
- options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
-
- options.inPreferredConfig = Bitmap.Config.RGB_565
-
- options.inJustDecodeBounds = false
-
- val image = BitmapFactory.decodeFile(images[position], options)
-
- setImageBitmap(image)
- }
+ Glide.with(holder.view)
+ .load(images[position])
+ .diskCacheStrategy(DiskCacheStrategy.NONE)
+ .skipMemoryCache(true)
+ .placeholder(progressDrawable)
+ .error(R.drawable.image_broken_variant)
+ .into(holder.view as ImageView)
}
override fun getItemCount() = images.size
diff --git a/app/src/main/java/xyz/quaver/pupil/types/SelectorSuggestion.kt b/app/src/main/java/xyz/quaver/pupil/types/SelectorSuggestion.kt
new file mode 100644
index 00000000..a350228c
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/types/SelectorSuggestion.kt
@@ -0,0 +1,13 @@
+package xyz.quaver.pupil.types
+
+import com.arlib.floatingsearchview.suggestions.model.SearchSuggestion
+import kotlinx.android.parcel.Parcelize
+import xyz.quaver.hitomi.Suggestion
+
+@Parcelize
+class SelectorSuggestion : SearchSuggestion {
+
+ override fun getBody(): String {
+ return ""
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/xyz/quaver/pupil/types/TagSuggestion.kt b/app/src/main/java/xyz/quaver/pupil/types/TagSuggestion.kt
index 2b39db9f..f46a83a0 100644
--- a/app/src/main/java/xyz/quaver/pupil/types/TagSuggestion.kt
+++ b/app/src/main/java/xyz/quaver/pupil/types/TagSuggestion.kt
@@ -5,7 +5,7 @@ import kotlinx.android.parcel.Parcelize
import xyz.quaver.hitomi.Suggestion
@Parcelize
-data class TagSuggestion constructor(val s: String, val t: Int, val u: String, val n: String) : SearchSuggestion {
+data class TagSuggestion(val s: String, val t: Int, val u: String, val n: String) : SearchSuggestion {
constructor(s: Suggestion) : this(s.s, s.t, s.u, s.n)
override fun getBody(): String {
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
index a19254a9..084020b1 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/MainActivity.kt
@@ -55,6 +55,8 @@ import java.net.URL
import java.util.*
import javax.net.ssl.HttpsURLConnection
import kotlin.collections.ArrayList
+import kotlin.math.abs
+import kotlin.math.ceil
import kotlin.math.min
import kotlin.math.roundToInt
@@ -72,8 +74,10 @@ class MainActivity : AppCompatActivity() {
private var query = ""
set(value) {
field = value
- findViewById(R.id.search_bar_text)
- .setText(query, TextView.BufferType.EDITABLE)
+ with(findViewById(R.id.search_bar_text)) {
+ if (text.toString() != value)
+ setText(query, TextView.BufferType.EDITABLE)
+ }
}
private var mode = Mode.SEARCH
@@ -155,7 +159,7 @@ class MainActivity : AppCompatActivity() {
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val perPage = preference.getString("per_page", "25")!!.toInt()
- val maxPage = Math.ceil(totalItems / perPage.toDouble()).roundToInt()
+ val maxPage = ceil(totalItems / perPage.toDouble()).roundToInt()
return when(keyCode) {
KeyEvent.KEYCODE_VOLUME_DOWN -> {
@@ -380,9 +384,9 @@ class MainActivity : AppCompatActivity() {
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
val gallery = galleries[position].first
- intent.putExtra("galleryblock", Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery))
+ intent.putExtra("galleryID", gallery.id)
- //TODO: Maybe sprinke some transitions will be nice :D
+ //TODO: Maybe sprinkling some transitions will be nice :D
startActivity(intent)
histories.add(gallery.id)
@@ -391,7 +395,7 @@ class MainActivity : AppCompatActivity() {
if (v !is CardView)
return@setOnItemLongClickListener true
- val galleryBlock = galleries[position].first
+ val gallery = galleries[position].first
val view = LayoutInflater.from(this@MainActivity)
.inflate(R.layout.dialog_galleryblock, recyclerView, false)
@@ -400,15 +404,15 @@ class MainActivity : AppCompatActivity() {
}.create()
with(view.main_dialog_download) {
- text = when(GalleryDownloader.get(galleryBlock.id)) {
+ text = when(GalleryDownloader.get(gallery.id)) {
null -> getString(R.string.reader_fab_download)
else -> getString(R.string.reader_fab_download_cancel)
}
- isEnabled = !(adapter as GalleryBlockAdapter).completeFlag.get(galleryBlock.id, false)
+ isEnabled = !(adapter as GalleryBlockAdapter).completeFlag.get(gallery.id, false)
setOnClickListener {
- val downloader = GalleryDownloader.get(galleryBlock.id)
+ val downloader = GalleryDownloader.get(gallery.id)
if (downloader == null)
- GalleryDownloader(context, galleryBlock, true).start()
+ GalleryDownloader(context, gallery.id, true).start()
else {
downloader.cancel()
downloader.clearNotification()
@@ -420,16 +424,16 @@ class MainActivity : AppCompatActivity() {
view.main_dialog_delete.setOnClickListener {
CoroutineScope(Dispatchers.Default).launch {
- with(GalleryDownloader[galleryBlock.id]) {
+ with(GalleryDownloader[gallery.id]) {
this?.cancelAndJoin()
this?.clearNotification()
}
- val cache = File(cacheDir, "imageCache/${galleryBlock.id}")
- val data = getCachedGallery(context, galleryBlock.id)
+ val cache = File(cacheDir, "imageCache/${gallery.id}")
+ val data = getCachedGallery(context, gallery.id)
cache.deleteRecursively()
data.deleteRecursively()
- downloads.remove(galleryBlock.id)
+ downloads.remove(gallery.id)
if (mode == Mode.DOWNLOAD) {
runOnUiThread {
@@ -440,7 +444,7 @@ class MainActivity : AppCompatActivity() {
}
}
- (adapter as GalleryBlockAdapter).completeFlag.put(galleryBlock.id, false)
+ (adapter as GalleryBlockAdapter).completeFlag.put(gallery.id, false)
}
dialog.dismiss()
}
@@ -583,7 +587,7 @@ class MainActivity : AppCompatActivity() {
//BOTTOM
//Scrolling DOWN
- if (dist < 0 && currentPage != Math.ceil(totalItems.toDouble()/perPage).roundToInt()-1) {
+ if (dist < 0 && currentPage != ceil(totalItems.toDouble()/perPage).roundToInt()-1) {
with(main_recyclerview.adapter as GalleryBlockAdapter) {
if(!showNext) {
showNext = true
@@ -595,7 +599,7 @@ class MainActivity : AppCompatActivity() {
getChildAt(childCount-1)
}
- val absDist = Math.abs(dist)
+ val absDist = abs(dist)
if (next is LinearLayout) {
val icon = next.findViewById(R.id.icon_next)
@@ -701,7 +705,7 @@ class MainActivity : AppCompatActivity() {
setMessage(getString(
R.string.main_jump_message,
currentPage+1,
- Math.ceil(totalItems / perPage.toDouble()).roundToInt()
+ ceil(totalItems / perPage.toDouble()).roundToInt()
))
setPositiveButton(android.R.string.ok) { _, _ ->
@@ -729,10 +733,7 @@ class MainActivity : AppCompatActivity() {
val intent = Intent(this@MainActivity, ReaderActivity::class.java)
val gallery =
getGalleryBlock(editText.text.toString().toInt()) ?: throw Exception()
- intent.putExtra(
- "galleryblock",
- Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), gallery)
- )
+ intent.putExtra("galleryID", gallery.id)
startActivity(intent)
} catch (e: Exception) {
@@ -747,10 +748,17 @@ class MainActivity : AppCompatActivity() {
}
setOnQueryChangeListener { _, query ->
+ this@MainActivity.query = query
+
clearSuggestions()
- if (query.isEmpty() or query.endsWith(' '))
+ if (query.isEmpty() or query.endsWith(' ')) {
+ swapSuggestions(json.parse(serializer, favoritesFile.readText()).map {
+ TagSuggestion(it.tag, -1, "", it.area ?: "tag")
+ })
+
return@setOnQueryChangeListener
+ }
val currentQuery = query.split(" ").last().replace('_', ' ')
@@ -852,8 +860,6 @@ class MainActivity : AppCompatActivity() {
delete(if (lastIndexOf(' ') == -1) 0 else lastIndexOf(' ')+1, length)
append("${suggestion.n}:${suggestion.s.replace(Regex("\\s"), "_")} ")
}
-
- clearSuggestions()
}
override fun onSearchAction(currentQuery: String?) {
@@ -863,7 +869,7 @@ class MainActivity : AppCompatActivity() {
setOnFocusChangeListener(object: FloatingSearchView.OnFocusChangeListener {
override fun onFocus() {
- if (searchInputView.text.isEmpty())
+ if (query.isEmpty() or query.endsWith(' '))
swapSuggestions(json.parse(serializer, favoritesFile.readText()).map {
TagSuggestion(it.tag, -1, "", it.area ?: "tag")
})
diff --git a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
index e29b3111..6bd102b9 100644
--- a/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/ui/ReaderActivity.kt
@@ -7,6 +7,7 @@ import android.os.Bundle
import android.view.*
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
import androidx.preference.PreferenceManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
@@ -21,13 +22,8 @@ import kotlinx.android.synthetic.main.dialog_numberpicker.view.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
-import kotlinx.coroutines.runBlocking
import kotlinx.io.IOException
import kotlinx.serialization.ImplicitReflectionSerializer
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonConfiguration
-import xyz.quaver.hitomi.GalleryBlock
-import xyz.quaver.hitomi.getGalleryBlock
import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.ReaderAdapter
@@ -37,8 +33,8 @@ import xyz.quaver.pupil.util.ItemClickSupport
class ReaderActivity : AppCompatActivity() {
+ private var galleryID = 0
private val images = ArrayList()
- private lateinit var galleryBlock: GalleryBlock
private var gallerySize = 0
private var currentPage = 0
@@ -66,6 +62,9 @@ class ReaderActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ title = getString(R.string.reader_loading)
+ supportActionBar?.setDisplayHomeAsUpEnabled(false)
+
favorites = (application as Pupil).favorites
window.setFlags(
@@ -76,16 +75,13 @@ class ReaderActivity : AppCompatActivity() {
handleIntent(intent)
- Crashlytics.setInt("GalleryID", galleryBlock.id)
+ Crashlytics.setInt("GalleryID", galleryID)
- if (!::galleryBlock.isInitialized) {
+ if (galleryID == 0) {
onBackPressed()
return
}
- supportActionBar?.title = galleryBlock.title
- supportActionBar?.setDisplayHomeAsUpEnabled(false)
-
initDownloader()
initView()
@@ -106,25 +102,16 @@ class ReaderActivity : AppCompatActivity() {
if (uri != null && lastPathSegment != null) {
val nonNumber = Regex("[^-?0-9]+")
- val galleryID = when (uri.host) {
+ galleryID = when (uri.host) {
"hitomi.la" -> lastPathSegment.replace(nonNumber, "").toInt()
"히요비.asia" -> lastPathSegment.toInt()
"xn--9w3b15m8vo.asia" -> lastPathSegment.toInt()
"e-hentai.org" -> uri.pathSegments[1].toInt()
else -> return
}
-
- runBlocking {
- CoroutineScope(Dispatchers.IO).launch {
- galleryBlock = getGalleryBlock(galleryID) ?: return@launch
- }.join()
- }
}
} else {
- galleryBlock = Json(JsonConfiguration.Stable).parse(
- GalleryBlock.serializer(),
- intent.getStringExtra("galleryblock")!!
- )
+ galleryID = intent.getIntExtra("galleryID", 0)
}
}
@@ -148,7 +135,7 @@ class ReaderActivity : AppCompatActivity() {
with(menu?.findItem(R.id.reader_menu_favorite)) {
this ?: return@with
- if (favorites.contains(galleryBlock.id))
+ if (favorites.contains(galleryID))
(icon as Animatable).start()
}
@@ -176,7 +163,7 @@ class ReaderActivity : AppCompatActivity() {
dialog.show()
}
R.id.reader_menu_favorite -> {
- val id = galleryBlock.id
+ val id = galleryID
val favorite = menu?.findItem(R.id.reader_menu_favorite) ?: return true
if (favorites.contains(id)) {
@@ -215,11 +202,11 @@ class ReaderActivity : AppCompatActivity() {
}
private fun initDownloader() {
- var d: GalleryDownloader? = GalleryDownloader.get(galleryBlock.id)
+ var d: GalleryDownloader? = GalleryDownloader.get(galleryID)
if (d == null) {
try {
- d = GalleryDownloader(this, galleryBlock)
+ d = GalleryDownloader(this, galleryID)
} catch (e: IOException) {
Snackbar.make(reader_layout, R.string.unable_to_connect, Snackbar.LENGTH_LONG).show()
finish()
@@ -230,17 +217,18 @@ class ReaderActivity : AppCompatActivity() {
downloader = d.apply {
onReaderLoadedHandler = {
CoroutineScope(Dispatchers.Main).launch {
+ title = it.title
with(reader_download_progressbar) {
- max = it.size
+ max = it.readerItems.size
progress = 0
}
with(reader_progressbar) {
- max = it.size
+ max = it.readerItems.size
progress = 0
}
- gallerySize = it.size
- menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/${it.size}"
+ gallerySize = it.readerItems.size
+ menu?.findItem(R.id.reader_menu_page_indicator)?.title = "$currentPage/${it.readerItems.size}"
}
}
onProgressHandler = {
@@ -341,18 +329,24 @@ class ReaderActivity : AppCompatActivity() {
}
}
- reader_fab_fullscreen.setOnClickListener {
- isFullscreen = true
- fullscreen(isFullscreen)
+ with(reader_fab_download) {
+ setImageResource(R.drawable.ic_download)
+ setOnClickListener {
+ downloader.download = !downloader.download
- reader_fab.close(true)
+ if (!downloader.download)
+ downloader.clearNotification()
+ }
}
- reader_fab_download.setOnClickListener {
- downloader.download = !downloader.download
+ with(reader_fab_fullscreen) {
+ setImageResource(R.drawable.ic_fullscreen)
+ setOnClickListener {
+ isFullscreen = true
+ fullscreen(isFullscreen)
- if (!downloader.download)
- downloader.clearNotification()
+ this@ReaderActivity.reader_fab.close(true)
+ }
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
index 9be00515..53a46770 100644
--- a/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
+++ b/app/src/main/java/xyz/quaver/pupil/util/GalleryDownloader.kt
@@ -13,12 +13,13 @@ import kotlinx.coroutines.*
import kotlinx.io.IOException
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
-import kotlinx.serialization.list
-import xyz.quaver.hitomi.*
+import xyz.quaver.hitomi.Reader
+import xyz.quaver.hitomi.getReader
+import xyz.quaver.hitomi.getReferer
import xyz.quaver.hiyobi.cookie
import xyz.quaver.hiyobi.user_agent
-import xyz.quaver.pupil.R
import xyz.quaver.pupil.Pupil
+import xyz.quaver.pupil.R
import xyz.quaver.pupil.ui.ReaderActivity
import java.io.File
import java.io.FileOutputStream
@@ -30,7 +31,7 @@ import kotlin.concurrent.schedule
class GalleryDownloader(
base: Context,
- private val galleryBlock: GalleryBlock,
+ private val galleryID: Int,
_notify: Boolean = false
) : ContextWrapper(base) {
@@ -41,10 +42,10 @@ class GalleryDownloader(
set(value) {
if (value) {
field = true
- notificationManager.notify(galleryBlock.id, notificationBuilder.build())
+ notificationManager.notify(galleryID, notificationBuilder.build())
- val data = getCachedGallery(this, galleryBlock.id)
- val cache = File(cacheDir, "imageCache/${galleryBlock.id}")
+ val data = getCachedGallery(this, galleryID)
+ val cache = File(cacheDir, "imageCache/$galleryID")
if (File(cache, "images").exists() && !data.exists()) {
cache.copyRecursively(data, true)
@@ -54,7 +55,7 @@ class GalleryDownloader(
if (reader?.isActive == false && downloadJob?.isActive != true)
field = false
- downloads.add(galleryBlock.id)
+ downloads.add(galleryID)
} else {
field = false
}
@@ -78,24 +79,24 @@ class GalleryDownloader(
companion object : SparseArray()
init {
- put(galleryBlock.id, this)
+ put(galleryID, this)
initNotification()
reader = CoroutineScope(Dispatchers.IO).async {
download = _notify
val json = Json(JsonConfiguration.Stable)
- val serializer = ReaderItem.serializer().list
+ val serializer = Reader.serializer()
//Check cache
- val cache = File(getCachedGallery(this@GalleryDownloader, galleryBlock.id), "reader.json")
+ val cache = File(getCachedGallery(this@GalleryDownloader, galleryID), "reader.json")
if (cache.exists()) {
val cached = json.parse(serializer, cache.readText())
- if (cached.isNotEmpty()) {
+ if (cached.readerItems.isNotEmpty()) {
useHiyobi = when {
- cached.first().url.contains("hitomi.la") -> false
+ cached.readerItems[0].url.contains("hitomi.la") -> false
else -> true
}
@@ -108,22 +109,22 @@ class GalleryDownloader(
//Cache doesn't exist. Load from internet
val reader = when {
useHiyobi -> {
- xyz.quaver.hiyobi.getReader(galleryBlock.id).let {
+ xyz.quaver.hiyobi.getReader(galleryID).let {
when {
- it.isEmpty() -> {
+ it.readerItems.isEmpty() -> {
useHiyobi = false
- getReader(galleryBlock.id)
+ getReader(galleryID)
}
else -> it
}
}
}
else -> {
- getReader(galleryBlock.id)
+ getReader(galleryID)
}
}
- if (reader.isNotEmpty()) {
+ if (reader.readerItems.isNotEmpty()) {
//Save cache
if (cache.parentFile?.exists() == false)
cache.parentFile!!.mkdirs()
@@ -141,7 +142,7 @@ class GalleryDownloader(
downloadJob = CoroutineScope(Dispatchers.Default).launch {
val reader = reader!!.await()
- if (reader.isEmpty())
+ if (reader.readerItems.isEmpty())
onErrorHandler?.invoke(IOException("Couldn't retrieve Reader"))
val list = ArrayList()
@@ -149,29 +150,20 @@ class GalleryDownloader(
onReaderLoadedHandler?.invoke(reader)
notificationBuilder
- .setProgress(reader.size, 0, false)
- .setContentText("0/${reader.size}")
+ .setProgress(reader.readerItems.size, 0, false)
+ .setContentText("0/${reader.readerItems.size}")
- reader.chunked(4).forEachIndexed { chunkIndex, chunked ->
+ reader.readerItems.chunked(4).forEachIndexed { chunkIndex, chunked ->
chunked.mapIndexed { i, it ->
val index = chunkIndex*4+i
- onProgressHandler?.invoke(index)
-
- notificationBuilder
- .setProgress(reader.size, index, false)
- .setContentText("$index/${reader.size}")
-
- if (download)
- notificationManager.notify(galleryBlock.id, notificationBuilder.build())
-
async(Dispatchers.IO) {
val url = if (it.galleryInfo?.haswebp == 1) webpUrlFromUrl(it.url) else it.url
val name = "$index".padStart(4, '0')
val ext = url.split('.').last()
- val cache = File(getCachedGallery(this@GalleryDownloader, galleryBlock.id), "images/$name.$ext")
+ val cache = File(getCachedGallery(this@GalleryDownloader, galleryID), "images/$name.$ext")
if (!cache.exists())
try {
@@ -180,7 +172,7 @@ class GalleryDownloader(
setRequestProperty("User-Agent", user_agent)
setRequestProperty("Cookie", cookie)
} else
- setRequestProperty("Referer", getReferer(galleryBlock.id))
+ setRequestProperty("Referer", getReferer(galleryID))
if (cache.parentFile?.exists() == false)
cache.parentFile!!.mkdirs()
@@ -193,31 +185,43 @@ class GalleryDownloader(
onErrorHandler?.invoke(e)
notificationBuilder
- .setContentTitle(galleryBlock.title)
+ .setContentTitle(reader.title)
.setContentText(getString(R.string.reader_notification_error))
.setProgress(0, 0, false)
- notificationManager.notify(galleryBlock.id, notificationBuilder.build())
+ notificationManager.notify(galleryID, notificationBuilder.build())
}
cache.absolutePath
}
}.forEach {
list.add(it.await())
+
+ val index = list.size
+
+ onProgressHandler?.invoke(index)
+
+ notificationBuilder
+ .setProgress(reader.readerItems.size, index, false)
+ .setContentText("$index/${reader.readerItems.size}")
+
+ if (download)
+ notificationManager.notify(galleryID, notificationBuilder.build())
+
onDownloadedHandler?.invoke(list)
}
}
Timer(false).schedule(1000) {
notificationBuilder
- .setContentTitle(galleryBlock.title)
+ .setContentTitle(reader.title)
.setContentText(getString(R.string.reader_notification_complete))
.setProgress(0, 0, false)
if (download) {
- File(cacheDir, "imageCache/${galleryBlock.id}").let {
+ File(cacheDir, "imageCache/${galleryID}").let {
if (it.exists()) {
- val target = File(getDownloadDirectory(this@GalleryDownloader), galleryBlock.id.toString())
+ val target = File(getDownloadDirectory(this@GalleryDownloader), galleryID.toString())
if (!target.exists())
target.mkdirs()
@@ -227,7 +231,7 @@ class GalleryDownloader(
}
}
- notificationManager.notify(galleryBlock.id, notificationBuilder.build())
+ notificationManager.notify(galleryID, notificationBuilder.build())
download = false
}
@@ -235,20 +239,20 @@ class GalleryDownloader(
onCompleteHandler?.invoke()
}
- remove(galleryBlock.id)
+ remove(galleryID)
}
}
fun cancel() {
downloadJob?.cancel()
- remove(galleryBlock.id)
+ remove(galleryID)
}
suspend fun cancelAndJoin() {
downloadJob?.cancelAndJoin()
- remove(galleryBlock.id)
+ remove(galleryID)
}
fun invokeOnReaderLoaded() {
@@ -258,7 +262,7 @@ class GalleryDownloader(
}
fun clearNotification() {
- notificationManager.cancel(galleryBlock.id)
+ notificationManager.cancel(galleryID)
}
fun invokeOnNotifyChanged() {
@@ -267,22 +271,28 @@ class GalleryDownloader(
private fun initNotification() {
val intent = Intent(this, ReaderActivity::class.java).apply {
- putExtra("galleryblock", Json(JsonConfiguration.Stable).stringify(GalleryBlock.serializer(), galleryBlock))
+ putExtra("galleryID", galleryID)
}
val pendingIntent = TaskStackBuilder.create(this).run {
addNextIntentWithParentStack(intent)
getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
+ notificationManager = NotificationManagerCompat.from(this)
+
notificationBuilder = NotificationCompat.Builder(this, "download").apply {
- setContentTitle(galleryBlock.title)
+ setContentTitle(getString(R.string.reader_loading))
setContentText(getString(R.string.reader_notification_text))
setSmallIcon(R.drawable.ic_download)
setContentIntent(pendingIntent)
setProgress(0, 0, true)
priority = NotificationCompat.PRIORITY_LOW
}
- notificationManager = NotificationManagerCompat.from(this)
+
+ CoroutineScope(Dispatchers.Default).launch {
+ while (reader == null) ;
+ notificationBuilder.setContentTitle(reader.await().title)
+ }
}
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_reader.xml b/app/src/main/res/layout/item_reader.xml
index 9f5abe22..eb9909bd 100644
--- a/app/src/main/res/layout/item_reader.xml
+++ b/app/src/main/res/layout/item_reader.xml
@@ -3,6 +3,7 @@
android:contentDescription="@string/reader_imageview_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:minHeight="100dp"
android:paddingBottom="8dp"
android:scaleType="fitCenter"
android:adjustViewBounds="true"/>
\ No newline at end of file
diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml
index 8ea7ac44..8e0c1660 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -79,4 +79,5 @@
ロックが一致しません。やり直してください。
なし
ロックを無効にしますか?
+ ロード中
\ No newline at end of file
diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml
index a1fe7f96..8fe85791 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -79,4 +79,5 @@
잠금이 일치하지 않습니다. 다시 시도하세요.
없음
잠금을 해제할까요?
+ 로딩중
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3a2738d3..3bfb2b16 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -71,6 +71,7 @@
Type: %1$s
Language: %1$s
+ Loading
Go to page
Fullscreen
Background download
diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt b/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt
new file mode 100644
index 00000000..ef73d8da
--- /dev/null
+++ b/libpupil/src/main/java/xyz/quaver/hitomi/reader.kt
@@ -0,0 +1,72 @@
+package xyz.quaver.hitomi
+
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonConfiguration
+import kotlinx.serialization.list
+import org.jsoup.Jsoup
+import xyz.quaver.hiyobi.HiyobiReader
+import java.net.URL
+
+fun getReferer(galleryID: Int) = "https://hitomi.la/reader/$galleryID.html"
+fun webpUrlFromUrl(url: String) = url.replace("/galleries/", "/webp/") + ".webp"
+
+fun webpReaderFromReader(reader: Reader) : Reader {
+ if (reader is HiyobiReader)
+ return reader
+
+ return Reader(reader.title, reader.readerItems.map {
+ ReaderItem(
+ if (it.galleryInfo?.haswebp == 1) webpUrlFromUrl(it.url) else it.url,
+ it.galleryInfo
+ )
+ })
+}
+
+@Serializable
+data class GalleryInfo(
+ val width: Int,
+ val haswebp: Int,
+ val name: String,
+ val height: Int
+)
+@Serializable
+data class ReaderItem(
+ val url: String,
+ val galleryInfo: GalleryInfo?
+)
+
+@Serializable
+open class Reader(val title: String, val readerItems: List)
+
+//Set header `Referer` to reader url to avoid 403 error
+fun getReader(galleryID: Int) : Reader {
+ val readerUrl = "https://hitomi.la/reader/$galleryID.html"
+ val galleryInfoUrl = "https://ltn.hitomi.la/galleries/$galleryID.js"
+
+ val doc = Jsoup.connect(readerUrl).get()
+
+ val title = doc.title()
+
+ val images = doc.select(".img-url").map {
+ protocol + urlFromURL(it.text())
+ }
+
+ val galleryInfo = ArrayList()
+
+ galleryInfo.addAll(
+ Json(JsonConfiguration.Stable).parse(
+ GalleryInfo.serializer().list,
+ Regex("""\[.+]""").find(
+ URL(galleryInfoUrl).readText()
+ )?.value ?: "[]"
+ )
+ )
+
+ if (images.size > galleryInfo.size)
+ galleryInfo.addAll(arrayOfNulls(images.size - galleryInfo.size))
+
+ return Reader(title, (images zip galleryInfo).map {
+ ReaderItem(it.first, it.second)
+ })
+}
\ No newline at end of file
diff --git a/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt b/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt
deleted file mode 100644
index 0be173e9..00000000
--- a/libpupil/src/main/java/xyz/quaver/hitomi/readers.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-package xyz.quaver.hitomi
-
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.json.Json
-import kotlinx.serialization.json.JsonConfiguration
-import kotlinx.serialization.list
-import org.jsoup.Jsoup
-import java.net.URL
-
-fun getReferer(galleryID: Int) = "https://hitomi.la/reader/$galleryID.html"
-
-@Serializable
-data class GalleryInfo(
- val width: Int,
- val haswebp: Int,
- val name: String,
- val height: Int
-)
-@Serializable
-data class ReaderItem(
- val url: String,
- val galleryInfo: GalleryInfo?
-)
-typealias Reader = List
-//Set header `Referer` to reader url to avoid 403 error
-fun getReader(galleryID: Int) : Reader {
- val readerUrl = "https://hitomi.la/reader/$galleryID.html"
- val galleryInfoUrl = "https://ltn.hitomi.la/galleries/$galleryID.js"
-
- try {
- val doc = Jsoup.connect(readerUrl).get()
-
- val images = doc.select(".img-url").map {
- protocol + urlFromURL(it.text())
- }
-
- val galleryInfo = ArrayList()
-
- galleryInfo.addAll(
- Json(JsonConfiguration.Stable).parse(
- GalleryInfo.serializer().list,
- Regex("""\[.+]""").find(
- URL(galleryInfoUrl).readText()
- )?.value ?: "[]"
- )
- )
-
- if (images.size > galleryInfo.size)
- galleryInfo.addAll(arrayOfNulls(images.size - galleryInfo.size))
-
- return (images zip galleryInfo).map {
- ReaderItem(it.first, it.second)
- }
- } catch (e: Exception) {
- return emptyList()
- }
-}
\ No newline at end of file
diff --git a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
index a20de850..e02983fe 100644
--- a/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
+++ b/libpupil/src/main/java/xyz/quaver/hiyobi/reader.kt
@@ -1,9 +1,9 @@
package xyz.quaver.hiyobi
-import kotlinx.io.IOException
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonConfiguration
import kotlinx.serialization.json.content
+import org.jsoup.Jsoup
import xyz.quaver.hitomi.Reader
import xyz.quaver.hitomi.ReaderItem
import java.net.URL
@@ -12,13 +12,15 @@ import javax.net.ssl.HttpsURLConnection
const val hiyobi = "xn--9w3b15m8vo.asia"
const val user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36"
-var cookie: String = ""
-get() {
- if (field.isEmpty())
- field = renewCookie()
+class HiyobiReader(title: String, readerItems: List) : Reader(title, readerItems)
- return field
-}
+var cookie: String = ""
+ get() {
+ if (field.isEmpty())
+ field = renewCookie()
+
+ return field
+ }
fun renewCookie() : String {
val url = "https://$hiyobi/"
@@ -35,26 +37,25 @@ fun renewCookie() : String {
}
}
-fun getReader(galleryId: Int) : Reader {
- val url = "https://$hiyobi/data/json/${galleryId}_list.json"
+fun getReader(galleryID: Int) : Reader {
+ val reader = "https://$hiyobi/reader/$galleryID"
+ val url = "https://$hiyobi/data/json/${galleryID}_list.json"
- try {
- val json = Json(JsonConfiguration.Stable).parseJson(
- with(URL(url).openConnection() as HttpsURLConnection) {
- setRequestProperty("User-Agent", user_agent)
- setRequestProperty("Cookie", cookie)
- connectTimeout = 2000
- connect()
+ val title = Jsoup.connect(reader).get().title()
- inputStream.bufferedReader().use { it.readText() }
- }
- )
+ val json = Json(JsonConfiguration.Stable).parseJson(
+ with(URL(url).openConnection() as HttpsURLConnection) {
+ setRequestProperty("User-Agent", user_agent)
+ setRequestProperty("Cookie", cookie)
+ connectTimeout = 2000
+ connect()
- return json.jsonArray.map {
- val name = it.jsonObject["name"]!!.content
- ReaderItem("https://$hiyobi/data/$galleryId/$name", null)
+ inputStream.bufferedReader().use { it.readText() }
}
- } catch (e: Exception) {
- return emptyList()
- }
+ )
+
+ return Reader(title, json.jsonArray.map {
+ val name = it.jsonObject["name"]!!.content
+ ReaderItem("https://$hiyobi/data/$galleryID/$name", null)
+ })
}
\ No newline at end of file