Compare commits

...

20 Commits
4.18.4 ... 4.21

Author SHA1 Message Date
tom5079
9415ab4ef9 Fixed some images crashing
Added auto pageturn timer
2020-08-08 15:55:17 +09:00
tom5079
647294daf2 what were i thinking?! 2020-08-04 17:50:07 +09:00
tom5079
6ebc386474 Fixed app crashing when deleting cache/download 2020-08-04 12:14:14 +09:00
tom5079
3e657bdc09 Merge branch 'dev' 2020-08-03 21:54:28 +09:00
tom5079
0b0adb76a1 Merge branch 'master' into dev
# Conflicts:
#	app/build.gradle
#	app/release/app-release.apk
#	app/release/output-metadata.json
2020-08-03 21:54:14 +09:00
tom5079
17b3e010aa fuck git 2020-08-03 21:49:04 +09:00
tom5079
20003acd73 App built
resolves #98
2020-08-03 21:34:24 +09:00
tom5079
2ab7672092 Search Backtracking Added 2020-08-03 21:31:39 +09:00
tom5079
c317abe64b Open Gallery Info dialog instead of opening up the gallery when opening a random gallery 2020-08-03 21:19:08 +09:00
tom5079
bc33ce1ebc Fix Settings opening up too late if the download folder is too big 2020-08-03 21:14:47 +09:00
Pupil
684c5cf38b Merge pull request #105 from tom5079/dev
4.19-hotfix2
2020-08-03 02:10:17 +09:00
tom5079
c34e15f0a1 Fixed image corruption when not using cache 2020-08-03 02:06:37 +09:00
Pupil
bad004f892 Merge pull request #104 from tom5079/dev
Version 4.19-hotfix1
2020-08-02 17:48:32 +09:00
tom5079
828d3de020 Fixed app crashing between android version 5.0 and 5.1 2020-08-02 17:45:24 +09:00
tom5079
132b3b9be1 Unable to fetch thumbnails fixed 2020-07-29 10:53:50 +09:00
Pupil
388bc6fda5 Merge pull request #103 from tom5079/Pupil-99
resolves #99
2020-07-29 10:28:01 +09:00
tom5079
a93edc184d resolves #99 2020-07-23 22:42:38 +09:00
tom5079
08672d10ac oops 2020-07-23 20:48:24 +09:00
tom5079
b563dae3a8 App rebuilt 2020-07-23 20:37:38 +09:00
tom5079
917f9672dd bug fix - unable to run on older devices
Version 4.18.4
2020-07-23 20:32:45 +09:00
27 changed files with 532 additions and 57 deletions

55
.idea/jarRepositories.xml generated Normal file
View File

@@ -0,0 +1,55 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="http://guardian.github.com/maven/repo-releases" />
</remote-repository>
<remote-repository>
<option name="id" value="BintrayJCenter" />
<option name="name" value="BintrayJCenter" />
<option name="url" value="https://jcenter.bintray.com/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven" />
<option name="name" value="maven" />
<option name="url" value="https://jitpack.io" />
</remote-repository>
<remote-repository>
<option name="id" value="Google" />
<option name="name" value="Google" />
<option name="url" value="https://dl.google.com/dl/android/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="MavenRepo" />
<option name="name" value="MavenRepo" />
<option name="url" value="https://repo.maven.apache.org/maven2/" />
</remote-repository>
<remote-repository>
<option name="id" value="maven2" />
<option name="name" value="maven2" />
<option name="url" value="https://guardian.github.com/maven/repo-releases" />
</remote-repository>
<remote-repository>
<option name="id" value="maven3" />
<option name="name" value="maven3" />
<option name="url" value="https://s3.amazonaws.com/fabric-artifacts-private/internal-snapshots" />
</remote-repository>
<remote-repository>
<option name="id" value="maven4" />
<option name="name" value="maven4" />
<option name="url" value="https://maven.fabric.io/public" />
</remote-repository>
</component>
</project>

View File

@@ -19,8 +19,8 @@ android {
applicationId "xyz.quaver.pupil"
minSdkVersion 16
targetSdkVersion 29
versionCode 56
versionName "4.18.3"
versionCode 57
versionName "4.21"
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.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.7'
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'

View File

@@ -11,8 +11,8 @@
"type": "SINGLE",
"filters": [],
"properties": [],
"versionCode": 56,
"versionName": "56",
"versionCode": 57,
"versionName": "4.21",
"enabled": true,
"outputFile": "app-release.apk"
}

View File

@@ -21,7 +21,6 @@
package xyz.quaver.pupil
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.rule.ActivityTestRule
@@ -36,6 +35,8 @@ import xyz.quaver.hiyobi.user_agent
import xyz.quaver.pupil.ui.LockActivity
import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker
import xyz.quaver.pupil.util.getDownloadDirectory
import java.io.InputStreamReader
import java.net.URL
import javax.net.ssl.HttpsURLConnection
@@ -58,8 +59,10 @@ class ExampleInstrumentedTest {
val activityTestRule = ActivityTestRule(LockActivity::class.java)
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
ContextCompat.getExternalFilesDirs(appContext, null).forEachIndexed { index, file ->
Log.i("PUPILD", "$index: ${file?.absolutePath}")
Runtime.getRuntime().exec("du -hs " + getDownloadDirectory(appContext)).let {
InputStreamReader(it.inputStream).readLines().forEach { res ->
Log.i("PUPILD", res)
}
}
}

View 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)
)
}
}

View File

@@ -19,6 +19,9 @@
package xyz.quaver.pupil.adapters
import android.content.Context
import android.graphics.Color
import android.graphics.PorterDuff
import android.graphics.PorterDuffColorFilter
import android.graphics.drawable.Drawable
import android.util.Base64
import android.util.SparseBooleanArray
@@ -221,12 +224,16 @@ class GalleryBlockAdapter(private val glide: RequestManager, private val galleri
"male" -> {
setChipBackgroundColorResource(R.color.material_blue_700)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
ContextCompat.getDrawable(context, R.drawable.gender_male)
ContextCompat.getDrawable(context, R.drawable.gender_male)?.apply {
colorFilter = PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)
}
}
"female" -> {
setChipBackgroundColorResource(R.color.material_pink_600)
setTextColor(ContextCompat.getColor(context, android.R.color.white))
ContextCompat.getDrawable(context, R.drawable.gender_female)
ContextCompat.getDrawable(context, R.drawable.gender_female)?.apply {
colorFilter = PorterDuffColorFilter(Color.WHITE, PorterDuff.Mode.SRC_ATOP)
}
}
else -> null
}

View File

@@ -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)

View File

@@ -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
}

View File

@@ -98,6 +98,7 @@ class MainActivity : AppCompatActivity() {
setText(query, TextView.BufferType.EDITABLE)
}
}
private var queryStack = mutableListOf<String>()
private var mode = Mode.SEARCH
private var sortMode = SortMode.NEWEST
@@ -159,11 +160,12 @@ class MainActivity : AppCompatActivity() {
initView()
}
@OptIn(ExperimentalStdlibApi::class)
override fun onBackPressed() {
when {
main_drawer_layout.isDrawerOpen(GravityCompat.START) -> main_drawer_layout.closeDrawer(GravityCompat.START)
query.isNotEmpty() -> runOnUiThread {
query = ""
queryStack.removeLastOrNull() != null && queryStack.isNotEmpty() -> runOnUiThread {
query = queryStack.last()
cancelFetch()
clearGalleries()
@@ -278,6 +280,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries()
currentPage = 0
query = ""
queryStack.clear()
mode = Mode.SEARCH
fetchGalleries(query, sortMode)
loadBlocks()
@@ -287,6 +290,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries()
currentPage = 0
query = ""
queryStack.clear()
mode = Mode.HISTORY
fetchGalleries(query, sortMode)
loadBlocks()
@@ -296,6 +300,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries()
currentPage = 0
query = ""
queryStack.clear()
mode = Mode.DOWNLOAD
fetchGalleries(query, sortMode)
loadBlocks()
@@ -305,6 +310,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries()
currentPage = 0
query = ""
queryStack.clear()
mode = Mode.FAVORITE
fetchGalleries(query, sortMode)
loadBlocks()
@@ -377,13 +383,24 @@ class MainActivity : AppCompatActivity() {
if (it?.isEmpty() == false) {
val galleryID = it.random()
val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply {
putExtra("galleryID", galleryID)
}
GalleryDialog(
this@MainActivity,
Glide.with(this@MainActivity),
galleryID
).apply {
onChipClickedHandler.add {
runOnUiThread {
query = it.toQuery()
currentPage = 0
startActivity(intent)
histories.add(galleryID)
cancelFetch()
clearGalleries()
fetchGalleries(query, sortMode)
loadBlocks()
}
dismiss()
}
}.show()
}
}
}
@@ -979,6 +996,11 @@ class MainActivity : AppCompatActivity() {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val defaultQuery = preference.getString("default_query", "")!!
if (query != queryStack.lastOrNull()) {
queryStack.remove(query)
queryStack.add(query)
}
galleryIDs = null
if (galleryIDs?.isActive == true)

View File

@@ -51,6 +51,7 @@ import xyz.quaver.pupil.util.download.Cache
import xyz.quaver.pupil.util.download.DownloadWorker
import java.util.*
import kotlin.concurrent.schedule
import kotlin.concurrent.timer
class ReaderActivity : AppCompatActivity() {
@@ -71,6 +72,7 @@ class ReaderActivity : AppCompatActivity() {
}
private val timer = Timer()
private var autoTimer: Timer? = null
private val snapHelper = PagerSnapHelper()
@@ -380,6 +382,30 @@ class ReaderActivity : AppCompatActivity() {
}
}
with(reader_fab_auto) {
setImageResource(R.drawable.clock_start)
setOnClickListener {
if (autoTimer == null) {
autoTimer = timer(initialDelay = 10000L, period = 10000L) {
CoroutineScope(Dispatchers.Main).launch {
with(this@ReaderActivity.reader_recyclerview) {
val lastItem =
(layoutManager as LinearLayoutManager).findLastCompletelyVisibleItemPosition()
if (lastItem < adapter!!.itemCount - 1)
(layoutManager as LinearLayoutManager).scrollToPosition(lastItem + 1)
}
}
}
setImageResource(R.drawable.clock_end)
} else {
autoTimer?.cancel()
autoTimer = null
setImageResource(R.drawable.clock_start)
}
}
}
with(reader_fab_fullscreen) {
setImageResource(R.drawable.ic_fullscreen)
setOnClickListener {

View File

@@ -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 {

View File

@@ -33,6 +33,9 @@ import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import net.rdrei.android.dirchooser.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig
import xyz.quaver.pupil.Pupil
@@ -44,7 +47,9 @@ import xyz.quaver.pupil.ui.dialog.DownloadLocationDialog
import xyz.quaver.pupil.ui.dialog.MirrorDialog
import xyz.quaver.pupil.ui.dialog.ProxyDialog
import xyz.quaver.pupil.util.*
import java.io.BufferedReader
import java.io.File
import java.io.InputStreamReader
class SettingsFragment :
@@ -74,9 +79,16 @@ class SettingsFragment :
}
private fun getDirSize(dir: File) : String {
val size = dir.walk().map { it.length() }.sum()
return getString(R.string.settings_clear_summary, byteToString(size))
return if (activity != null)
getString(R.string.settings_storage_usage,
Runtime.getRuntime().exec("du -hs " + dir.absolutePath).let {
BufferedReader(InputStreamReader(it.inputStream)).use { reader ->
reader.readLine()?.split('\t')?.firstOrNull() ?: "0"
}
}
)
else
""
}
override fun onPreferenceClick(preference: Preference?): Boolean {
@@ -97,7 +109,15 @@ class SettingsFragment :
if (dir.exists())
dir.deleteRecursively()
summary = getDirSize(dir)
summary = getString(R.string.settings_storage_usage_loading)
CoroutineScope(Dispatchers.IO).launch {
getDirSize(dir).let {
launch(Dispatchers.Main) {
this@with.summary = it
}
}
}
}
setNegativeButton(android.R.string.no) { _, _ -> }
}.show()
@@ -112,7 +132,15 @@ class SettingsFragment :
if (dir.exists())
dir.deleteRecursively()
summary = getDirSize(dir)
summary = getString(R.string.settings_storage_usage_loading)
CoroutineScope(Dispatchers.IO).launch {
getDirSize(dir).let {
launch(Dispatchers.Main) {
this@with.summary = it
}
}
}
}
setNegativeButton(android.R.string.no) { _, _ -> }
}.show()
@@ -276,13 +304,29 @@ class SettingsFragment :
}
"delete_cache" -> {
val dir = File(requireContext().cacheDir, "imageCache")
summary = getDirSize(dir)
summary = getString(R.string.settings_storage_usage_loading)
CoroutineScope(Dispatchers.IO).launch {
getDirSize(dir).let {
launch(Dispatchers.Main) {
this@with.summary = it
}
}
}
onPreferenceClickListener = this@SettingsFragment
}
"delete_downloads" -> {
val dir = getDownloadDirectory(requireContext())
summary = getDirSize(dir)
summary = getString(R.string.settings_storage_usage_loading)
CoroutineScope(Dispatchers.IO).launch {
getDirSize(dir).let {
launch(Dispatchers.Main) {
this@with.summary = it
}
}
}
onPreferenceClickListener = this@SettingsFragment
}

View File

@@ -130,7 +130,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
* Float.POSITIVE_INFINITY -> Download completed
*/
val progress = SparseArray<MutableList<Float>?>()
val notification = SparseArray<NotificationCompat.Builder>()
val notification = SparseArray<NotificationCompat.Builder?>()
private val loop = loop()
private val worker = SparseArray<Job?>()
@@ -255,7 +255,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
if (notification[galleryID] == null)
initNotification(galleryID)
notification[galleryID].setContentTitle(reader.galleryInfo.title)
notification[galleryID]?.setContentTitle(reader.galleryInfo.title)
notify(galleryID)
if (isCompleted(galleryID)) {
@@ -345,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)
}
@@ -383,7 +383,7 @@ class DownloadWorker private constructor(context: Context) : ContextWrapper(cont
initNotification(galleryID)
if (Cache(this@DownloadWorker).isDownloading(galleryID))
notificationManager.notify(galleryID, notification[galleryID].build())
notification[galleryID]?.let { notificationManager.notify(galleryID, it.build()) }
worker.put(galleryID, download(galleryID))
queue.poll()

View File

@@ -0,0 +1,8 @@
<!-- drawable/clock_end.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M12,1C8.14,1 5,4.14 5,8A7,7 0 0,0 12,15C15.86,15 19,11.87 19,8C19,4.14 15.86,1 12,1M12,3.15C14.67,3.15 16.85,5.32 16.85,8C16.85,10.68 14.67,12.85 12,12.85A4.85,4.85 0 0,1 7.15,8A4.85,4.85 0 0,1 12,3.15M11,5V8.69L14.19,10.53L14.94,9.23L12.5,7.82V5M15,16V19H3V21H15V24L19,20M19,20V24H21V16H19" />
</vector>

View File

@@ -0,0 +1,8 @@
<!-- drawable/clock_start.xml -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:height="24dp"
android:width="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path android:fillColor="#fff" android:pathData="M12,1C8.14,1 5,4.14 5,8A7,7 0 0,0 12,15C15.86,15 19,11.87 19,8C19,4.14 15.86,1 12,1M12,3.15C14.67,3.15 16.85,5.32 16.85,8C16.85,10.68 14.67,12.85 12,12.85A4.85,4.85 0 0,1 7.15,8A4.85,4.85 0 0,1 12,3.15M11,5V8.69L14.19,10.53L14.94,9.23L12.5,7.82V5M4,16V24H6V21H18V24L22,20L18,16V19H6V16" />
</vector>

View 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>

View File

@@ -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"

View File

@@ -82,6 +82,13 @@
app:fab_label="@string/reader_fab_retry"
app:fab_size="mini"/>
<com.github.clans.fab.FloatingActionButton
android:id="@+id/reader_fab_auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fab_label="@string/reader_fab_auto"
app:fab_size="mini"/>
<com.github.clans.fab.FloatingActionButton
android:id="@+id/reader_fab_fullscreen"
android:layout_width="wrap_content"

View 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>

View File

@@ -9,7 +9,8 @@
<string name="search_hint_with_page">ギャラリー検索</string>
<string name="settings_clear_cache">キャッシュクリア</string>
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</string>
<string name="settings_clear_summary">サイズ: %s</string>
<string name="settings_storage_usage">%s使用中</string>
<string name="settings_storage_usage_loading">ストレージ使用量読み込み中…</string>
<string name="settings_default_query">デフォルトキーワード</string>
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
<string name="settings_search_title">検索設定</string>
@@ -150,4 +151,5 @@
<string name="settings_user_id_toast">ユーザーIDをクリップボードにコピーしました</string>
<string name="reader_error_retry">ダウンロードエラーが発生しました。リトライしますか?</string>
<string name="reader_fab_retry">リトライ</string>
<string name="reader_fab_auto">自動スクロール</string>
</resources>

View File

@@ -8,7 +8,8 @@
<string name="settings_default_query">기본 검색어</string>
<string name="settings_clear_cache">캐시 정리하기</string>
<string name="settings_clear_cache_alert_message">캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?</string>
<string name="settings_clear_summary">사용량: %s</string>
<string name="settings_storage_usage">%s 사용중</string>
<string name="settings_storage_usage_loading">저장공간 사용량 계산 중…</string>
<string name="settings_galleries_per_page">한 번에 로드할 갤러리 수</string>
<string name="settings_search_title">검색 설정</string>
<string name="settings_title">설정</string>
@@ -150,4 +151,5 @@
<string name="settings_user_id_toast">유저 ID를 클립보드에 복사했습니다</string>
<string name="reader_error_retry">다운로드 에러가 발생했습니. 재시도 하시겠습니까?</string>
<string name="reader_fab_retry">재시도</string>
<string name="reader_fab_auto">자동 스크롤</string>
</resources>

View File

@@ -115,6 +115,7 @@
<string name="reader_go_to_page">Go to page</string>
<string name="reader_fab_fullscreen">Fullscreen</string>>
<string name="reader_fab_retry">Retry</string>
<string name="reader_fab_auto">Automatic scroll</string>
<string name="reader_fab_download">Background download</string>
<string name="reader_fab_download_cancel">Cancel background download</string>
<string name="reader_notification_text">Downloading&#8230;</string>
@@ -142,9 +143,10 @@
<!-- SETTINGS/STORAGE -->
<string name="settings_storage">Storage</string>
<string name="settings_storage_usage">Currently using %s</string>
<string name="settings_storage_usage_loading">Calculating storage usage…</string>
<string name="settings_clear_cache">Clear cache</string>
<string name="settings_clear_cache_alert_message">Deleting cache can affect image loading speed. Do you want to continue?</string>
<string name="settings_clear_summary">Currently using %s</string>
<string name="settings_clear_downloads">Clear downloads</string>
<string name="settings_clear_downloads_alert_message">Delete all downloaded galleries.\nDo you want to continue?</string>
<string name="settings_clear_history">Clear history</string>

View File

@@ -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"

View File

@@ -33,12 +33,11 @@ fun getGalleryInfo(galleryID: Int) =
//common.js
var adapose = false
const val numberOfFrontends = 3
const val domain = "ltn.hitomi.la"
const val galleryblockdir = "galleryblock"
const val nozomiextension = ".nozomi"
fun subdomainFromGalleryID(g: Int) : String {
fun subdomainFromGalleryID(g: Int, numberOfFrontends: Int) : String {
if (adapose)
return "0"
@@ -53,13 +52,20 @@ fun subdomainFromURL(url: String, base: String? = null) : String {
if (!base.isNullOrBlank())
retval = base
var numberOfFrontends = 3
val b = 16
val r = Regex("""/[0-9a-f]/([0-9a-f]{2})/""")
val m = r.find(url) ?: return retval
val g = m.groupValues[1].toIntOrNull(b) ?: return retval
var g = m.groupValues[1].toIntOrNull(b) ?: return retval
retval = subdomainFromGalleryID(g) + retval
when {
g < 0x30 -> numberOfFrontends = 2
g < 0x09 -> g = 1
}
retval = subdomainFromGalleryID(g, numberOfFrontends) + retval
return retval
}

View File

@@ -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() }

View File

@@ -80,6 +80,13 @@ class UnitTest {
print(reader)
}
@Test
fun test_getImages() {
val reader = getReader(1702206)
print(urlFromUrlFromHash(1702206, reader.galleryInfo.files.first(), "webp"))
}
@Test
fun test_hiyobi() {
val reader = xyz.quaver.hiyobi.getReader(1664762)