Compare commits

...

19 Commits

Author SHA1 Message Date
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
20 changed files with 451 additions and 51 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" applicationId "xyz.quaver.pupil"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 29 targetSdkVersion 29
versionCode 56 versionCode 57
versionName "4.18.3" versionName "4.20-hotfix2"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true multiDexEnabled true
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@@ -64,19 +64,22 @@ dependencies {
implementation "androidx.biometric:biometric:1.0.1" implementation "androidx.biometric:biometric:1.0.1"
implementation 'androidx.multidex:multidex:2.0.1' implementation 'androidx.multidex:multidex:2.0.1'
implementation "com.daimajia.swipelayout:library:1.2.0@aar" 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-core:17.4.4'
implementation 'com.google.firebase:firebase-analytics: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-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.arimorty:floatingsearchview:2.1.1'
implementation 'com.github.clans:fab:1.6.4' implementation 'com.github.clans:fab:1.6.4'
implementation 'com.github.bumptech.glide:glide:4.11.0' 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' annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'
kapt '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") { implementation ("com.github.bumptech.glide:recyclerview-integration:4.11.0") {
transitive = false transitive = false
} }
implementation 'com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2'
implementation 'net.rdrei.android.dirchooser:library:3.2@aar' implementation 'net.rdrei.android.dirchooser:library:3.2@aar'
implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'com.andrognito.patternlockview:patternlockview:1.0.0' implementation 'com.andrognito.patternlockview:patternlockview:1.0.0'

View File

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

View File

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

@@ -22,9 +22,10 @@ import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.RequestManager import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.engine.DiskCacheStrategy
import xyz.quaver.pupil.BuildConfig 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) 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) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
glide glide
.load(thumbnails[position]) .load(thumbnails[position])
.diskCacheStrategy(DiskCacheStrategy.NONE)
.apply { .apply {
if (BuildConfig.CENSOR) if (BuildConfig.CENSOR)
override(5, 8) 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) setText(query, TextView.BufferType.EDITABLE)
} }
} }
private var queryStack = mutableListOf<String>()
private var mode = Mode.SEARCH private var mode = Mode.SEARCH
private var sortMode = SortMode.NEWEST private var sortMode = SortMode.NEWEST
@@ -159,11 +160,12 @@ class MainActivity : AppCompatActivity() {
initView() initView()
} }
@OptIn(ExperimentalStdlibApi::class)
override fun onBackPressed() { override fun onBackPressed() {
when { when {
main_drawer_layout.isDrawerOpen(GravityCompat.START) -> main_drawer_layout.closeDrawer(GravityCompat.START) main_drawer_layout.isDrawerOpen(GravityCompat.START) -> main_drawer_layout.closeDrawer(GravityCompat.START)
query.isNotEmpty() -> runOnUiThread { queryStack.removeLastOrNull() != null && queryStack.isNotEmpty() -> runOnUiThread {
query = "" query = queryStack.last()
cancelFetch() cancelFetch()
clearGalleries() clearGalleries()
@@ -278,6 +280,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries() clearGalleries()
currentPage = 0 currentPage = 0
query = "" query = ""
queryStack.clear()
mode = Mode.SEARCH mode = Mode.SEARCH
fetchGalleries(query, sortMode) fetchGalleries(query, sortMode)
loadBlocks() loadBlocks()
@@ -287,6 +290,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries() clearGalleries()
currentPage = 0 currentPage = 0
query = "" query = ""
queryStack.clear()
mode = Mode.HISTORY mode = Mode.HISTORY
fetchGalleries(query, sortMode) fetchGalleries(query, sortMode)
loadBlocks() loadBlocks()
@@ -296,6 +300,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries() clearGalleries()
currentPage = 0 currentPage = 0
query = "" query = ""
queryStack.clear()
mode = Mode.DOWNLOAD mode = Mode.DOWNLOAD
fetchGalleries(query, sortMode) fetchGalleries(query, sortMode)
loadBlocks() loadBlocks()
@@ -305,6 +310,7 @@ class MainActivity : AppCompatActivity() {
clearGalleries() clearGalleries()
currentPage = 0 currentPage = 0
query = "" query = ""
queryStack.clear()
mode = Mode.FAVORITE mode = Mode.FAVORITE
fetchGalleries(query, sortMode) fetchGalleries(query, sortMode)
loadBlocks() loadBlocks()
@@ -377,13 +383,24 @@ class MainActivity : AppCompatActivity() {
if (it?.isEmpty() == false) { if (it?.isEmpty() == false) {
val galleryID = it.random() val galleryID = it.random()
val intent = Intent(this@MainActivity, ReaderActivity::class.java).apply { GalleryDialog(
putExtra("galleryID", galleryID) this@MainActivity,
Glide.with(this@MainActivity),
galleryID
).apply {
onChipClickedHandler.add {
runOnUiThread {
query = it.toQuery()
currentPage = 0
cancelFetch()
clearGalleries()
fetchGalleries(query, sortMode)
loadBlocks()
} }
dismiss()
startActivity(intent) }
}.show()
histories.add(galleryID)
} }
} }
} }
@@ -979,6 +996,11 @@ class MainActivity : AppCompatActivity() {
val preference = PreferenceManager.getDefaultSharedPreferences(this) val preference = PreferenceManager.getDefaultSharedPreferences(this)
val defaultQuery = preference.getString("default_query", "")!! val defaultQuery = preference.getString("default_query", "")!!
if (query != queryStack.lastOrNull()) {
queryStack.remove(query)
queryStack.add(query)
}
galleryIDs = null galleryIDs = null
if (galleryIDs?.isActive == true) if (galleryIDs?.isActive == true)

View File

@@ -26,14 +26,15 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.widget.LinearLayout.LayoutParams import android.widget.LinearLayout.LayoutParams
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2
import com.bumptech.glide.RequestManager import com.bumptech.glide.RequestManager
import com.google.android.material.chip.Chip import com.google.android.material.chip.Chip
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.dialog_gallery.* 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.android.synthetic.main.item_gallery_details.view.*
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -46,7 +47,7 @@ import xyz.quaver.pupil.BuildConfig
import xyz.quaver.pupil.Pupil import xyz.quaver.pupil.Pupil
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.adapters.GalleryBlockAdapter 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.types.Tag
import xyz.quaver.pupil.ui.ReaderActivity import xyz.quaver.pupil.ui.ReaderActivity
import xyz.quaver.pupil.util.ItemClickSupport import xyz.quaver.pupil.util.ItemClickSupport
@@ -130,7 +131,7 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
private fun addDetails(gallery: Gallery) { private fun addDetails(gallery: Gallery) {
val inflater = LayoutInflater.from(context) 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) gallery_details.setText(R.string.gallery_details)
listOf( listOf(
@@ -206,15 +207,21 @@ class GalleryDialog(context: Context, private val glide: RequestManager, private
private fun addThumbnails(gallery: Gallery) { private fun addThumbnails(gallery: Gallery) {
val inflater = LayoutInflater.from(context) 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) gallery_details.setText(R.string.gallery_thumbnails)
RecyclerView(context).apply { val pager = ViewPager2(context).apply {
layoutManager = GridLayoutManager(context, 3) adapter = ThumbnailPageAdapter(glide, gallery.thumbnails)
adapter = ThumbnailAdapter(glide, gallery.thumbnails)
}.let {
gallery_details_contents.addView(it, LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT))
} }
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 { }.let {
gallery_contents.addView(it) 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) gallery_details.setText(R.string.gallery_related)
RecyclerView(context).apply { RecyclerView(context).apply {

View File

@@ -33,6 +33,9 @@ import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceFragmentCompat import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import com.google.android.material.snackbar.Snackbar 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.DirectoryChooserActivity
import net.rdrei.android.dirchooser.DirectoryChooserConfig import net.rdrei.android.dirchooser.DirectoryChooserConfig
import xyz.quaver.pupil.Pupil 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.MirrorDialog
import xyz.quaver.pupil.ui.dialog.ProxyDialog import xyz.quaver.pupil.ui.dialog.ProxyDialog
import xyz.quaver.pupil.util.* import xyz.quaver.pupil.util.*
import java.io.BufferedReader
import java.io.File import java.io.File
import java.io.InputStreamReader
class SettingsFragment : class SettingsFragment :
@@ -74,9 +79,13 @@ class SettingsFragment :
} }
private fun getDirSize(dir: File) : String { private fun getDirSize(dir: File) : String {
val size = dir.walk().map { it.length() }.sum() return getString(R.string.settings_storage_usage,
Runtime.getRuntime().exec("du -hs " + dir.absolutePath).let {
return getString(R.string.settings_clear_summary, byteToString(size)) BufferedReader(InputStreamReader(it.inputStream)).use { reader ->
reader.readLine()?.split('\t')?.firstOrNull() ?: "0"
}
}
)
} }
override fun onPreferenceClick(preference: Preference?): Boolean { override fun onPreferenceClick(preference: Preference?): Boolean {
@@ -97,7 +106,15 @@ class SettingsFragment :
if (dir.exists()) if (dir.exists())
dir.deleteRecursively() 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) { _, _ -> } setNegativeButton(android.R.string.no) { _, _ -> }
}.show() }.show()
@@ -112,7 +129,15 @@ class SettingsFragment :
if (dir.exists()) if (dir.exists())
dir.deleteRecursively() 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) { _, _ -> } setNegativeButton(android.R.string.no) { _, _ -> }
}.show() }.show()
@@ -276,13 +301,29 @@ class SettingsFragment :
} }
"delete_cache" -> { "delete_cache" -> {
val dir = File(requireContext().cacheDir, "imageCache") 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 onPreferenceClickListener = this@SettingsFragment
} }
"delete_downloads" -> { "delete_downloads" -> {
val dir = getDownloadDirectory(requireContext()) 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 onPreferenceClickListener = this@SettingsFragment
} }

View File

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

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:id="@+id/main_searchview"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="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_suggestionRightIconColor="@color/material_orange_500"
app:floatingSearch_searchBarMarginLeft="8dp" app:floatingSearch_searchBarMarginLeft="8dp"
app:floatingSearch_searchBarMarginRight="8dp" app:floatingSearch_searchBarMarginRight="8dp"

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="search_hint_with_page">ギャラリー検索</string>
<string name="settings_clear_cache">キャッシュクリア</string> <string name="settings_clear_cache">キャッシュクリア</string>
<string name="settings_clear_cache_alert_message">キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?</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_default_query">デフォルトキーワード</string>
<string name="settings_galleries_per_page">一回にロードするギャラリー数</string> <string name="settings_galleries_per_page">一回にロードするギャラリー数</string>
<string name="settings_search_title">検索設定</string> <string name="settings_search_title">検索設定</string>

View File

@@ -8,7 +8,8 @@
<string name="settings_default_query">기본 검색어</string> <string name="settings_default_query">기본 검색어</string>
<string name="settings_clear_cache">캐시 정리하기</string> <string name="settings_clear_cache">캐시 정리하기</string>
<string name="settings_clear_cache_alert_message">캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?</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_galleries_per_page">한 번에 로드할 갤러리 수</string>
<string name="settings_search_title">검색 설정</string> <string name="settings_search_title">검색 설정</string>
<string name="settings_title">설정</string> <string name="settings_title">설정</string>

View File

@@ -142,9 +142,10 @@
<!-- SETTINGS/STORAGE --> <!-- SETTINGS/STORAGE -->
<string name="settings_storage">Storage</string> <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">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_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">Clear downloads</string>
<string name="settings_clear_downloads_alert_message">Delete all downloaded galleries.\nDo you want to continue?</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> <string name="settings_clear_history">Clear history</string>

View File

@@ -7,7 +7,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { 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-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-android-extensions:$kotlin_version"
classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version"

View File

@@ -83,7 +83,7 @@ fun getGalleryBlock(galleryID: Int) : GalleryBlock? {
val galleryUrl = doc.selectFirst(".lillie").attr("href") 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 title = doc.selectFirst("h1.lillie > a").text()
val artists = doc.select("div.artist-list a").map{ it.text() } val artists = doc.select("div.artist-list a").map{ it.text() }