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 66bcddaa..405be41f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -19,6 +19,9 @@ android {
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
+ kotlinOptions {
+ freeCompilerArgs += '-Xuse-experimental=kotlin.Experimental'
+ }
}
dependencies {
diff --git a/app/src/main/java/xyz/quaver/pupil/GalleryActivity.kt b/app/src/main/java/xyz/quaver/pupil/GalleryActivity.kt
index 92dfe9c5..00cbf6e8 100644
--- a/app/src/main/java/xyz/quaver/pupil/GalleryActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/GalleryActivity.kt
@@ -11,11 +11,9 @@ import kotlinx.coroutines.*
import xyz.quaver.hitomi.Reader
import xyz.quaver.hitomi.getReader
import xyz.quaver.hitomi.getReferer
-import xyz.quaver.hiyobi.hiyobi
import xyz.quaver.pupil.adapters.GalleryAdapter
import java.io.File
import java.io.FileOutputStream
-import java.lang.Exception
import java.net.URL
import javax.net.ssl.HttpsURLConnection
diff --git a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt b/app/src/main/java/xyz/quaver/pupil/MainActivity.kt
index d24131e3..5e4042b2 100644
--- a/app/src/main/java/xyz/quaver/pupil/MainActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/MainActivity.kt
@@ -15,7 +15,6 @@ import android.os.Environment
import android.preference.PreferenceManager
import android.text.*
import android.text.style.AlignmentSpan
-import android.util.Log
import android.view.View
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
@@ -37,6 +36,7 @@ import kotlinx.coroutines.*
import xyz.quaver.hitomi.*
import xyz.quaver.pupil.adapters.GalleryBlockAdapter
import xyz.quaver.pupil.types.TagSuggestion
+import xyz.quaver.pupil.util.Histories
import xyz.quaver.pupil.util.SetLineOverlap
import xyz.quaver.pupil.util.checkUpdate
import xyz.quaver.pupil.util.getApkUrl
@@ -45,13 +45,16 @@ import javax.net.ssl.HttpsURLConnection
class MainActivity : AppCompatActivity() {
- private val PERMISSION_REQUEST_CODE = 4585
+ private val permissionRequestCode = 4585
private val galleries = ArrayList>()
- private var isLoading = false
private var query = ""
+ private var galleryIDs: Deferred>? = null
+ private var loadingJob: Job? = null
+
override fun onCreate(savedInstanceState: Bundle?) {
+ Histories.default = Histories(File(cacheDir, "histories.json"))
super.onCreate(savedInstanceState)
window.setFlags(
@@ -75,15 +78,33 @@ class MainActivity : AppCompatActivity() {
setProgressViewOffset(false, 0, resources.getDimensionPixelSize(R.dimen.progress_view_offset))
setOnRefreshListener {
- runBlocking {
- cleanJob?.join()
+ CoroutineScope(Dispatchers.Main).launch {
+ cancelFetch()
+ clearGalleries()
+ fetchGalleries(query)
+ loadBlocks()
}
- fetchGalleries(query, true)
}
}
main_nav_view.setNavigationItemSelectedListener {
- Log.d("Pupil", it.itemId.toString())
+ CoroutineScope(Dispatchers.Main).launch {
+ main_drawer_layout.closeDrawers()
+
+ cancelFetch()
+ clearGalleries()
+ when(it.itemId) {
+ R.id.main_drawer_home -> {
+ query = query.replace("HISTORY", "")
+ fetchGalleries(query)
+ }
+ R.id.main_drawer_history -> {
+ query += "HISTORY"
+ fetchGalleries(query)
+ }
+ }
+ loadBlocks()
+ }
true
}
@@ -91,6 +112,7 @@ class MainActivity : AppCompatActivity() {
setupRecyclerView()
setupSearchBar()
fetchGalleries(query)
+ loadBlocks()
}
override fun onBackPressed() {
@@ -113,7 +135,7 @@ class MainActivity : AppCompatActivity() {
setPositiveButton(android.R.string.ok) { _, _ -> }
}.show()
else
- ActivityCompat.requestPermissions(this, permissions, PERMISSION_REQUEST_CODE)
+ ActivityCompat.requestPermissions(this, permissions, permissionRequestCode)
}
}
@@ -183,6 +205,8 @@ class MainActivity : AppCompatActivity() {
//TODO: Maybe sprinke some transitions will be nice :D
startActivity(intent)
+
+ Histories.default.add(galleryID)
}
}
addOnScrollListener(
@@ -192,9 +216,9 @@ class MainActivity : AppCompatActivity() {
val layoutManager = recyclerView.layoutManager as LinearLayoutManager
- if (!isLoading)
+ if (loadingJob?.isActive != true)
if (layoutManager.findLastCompletelyVisibleItemPosition() == galleries.size)
- fetchGalleries(query)
+ loadBlocks()
}
}
)
@@ -311,7 +335,9 @@ class MainActivity : AppCompatActivity() {
if (query != this@MainActivity.query) {
this@MainActivity.query = query
- fetchGalleries(query, true)
+ cancelFetch()
+ clearGalleries()
+ fetchGalleries(query)
}
}
})
@@ -320,94 +346,96 @@ class MainActivity : AppCompatActivity() {
}
}
- private val cache = ArrayList()
- private var currentFetchingJob: Job? = null
- private var cleanJob: Job? = null
-
private fun cancelFetch() {
- isLoading = false
-
runBlocking {
- cleanJob?.join()
- currentFetchingJob?.cancelAndJoin()
+ galleryIDs?.cancelAndJoin()
+ loadingJob?.cancelAndJoin()
}
}
- private fun fetchGalleries(query: String, clear: Boolean = false) {
+ private fun clearGalleries() {
+ galleries.clear()
+
+ main_recyclerview.adapter?.notifyDataSetChanged()
+
+ main_noresult.visibility = View.INVISIBLE
+ main_progressbar.show()
+ main_swipe_layout.isRefreshing = false
+ }
+
+ private fun fetchGalleries(query: String, from: Int = 0) {
val preference = PreferenceManager.getDefaultSharedPreferences(this)
val perPage = preference.getString("per_page", "25")?.toInt() ?: 25
val defaultQuery = preference.getString("default_query", "")!!
- if (clear) {
- cancelFetch()
- cleanJob = CoroutineScope(Dispatchers.Main).launch {
- cache.clear()
- galleries.clear()
+ galleryIDs = null
- main_recyclerview.adapter?.notifyDataSetChanged()
-
- main_noresult.visibility = View.INVISIBLE
- main_progressbar.show()
- main_swipe_layout.isRefreshing = false
- }
- }
-
- if (isLoading)
+ if (galleryIDs?.isActive == true)
return
- isLoading = true
+ galleryIDs = CoroutineScope(Dispatchers.IO).async {
+ when {
+ query.contains("HISTORY") ->
+ Histories.default.toList()
+ query.isEmpty() and defaultQuery.isEmpty() ->
+ fetchNozomi(start = from, count = perPage)
+ else ->
+ doSearch("$defaultQuery $query")
+ }
+ }
+ }
- currentFetchingJob = CoroutineScope(Dispatchers.IO).launch {
- try {
- val galleryIDs: List
+ private fun loadBlocks() {
+ val preference = PreferenceManager.getDefaultSharedPreferences(this)
+ val perPage = preference.getString("per_page", "25")?.toInt() ?: 25
+ val defaultQuery = preference.getString("default_query", "")!!
- cleanJob?.join()
+ loadingJob = CoroutineScope(Dispatchers.IO).launch {
+ val galleryIDs = galleryIDs?.await()
- if (query.isEmpty() && defaultQuery.isEmpty())
- galleryIDs = fetchNozomi(start = galleries.size, count = perPage)
- else {
- if (cache.isEmpty())
- cache.addAll(doSearch("$defaultQuery $query"))
-
- galleryIDs = cache.slice(galleries.size until Math.min(galleries.size + perPage, cache.size))
-
- with(main_recyclerview.adapter as GalleryBlockAdapter) {
- noMore = galleries.size + perPage >= cache.size
- }
+ if (galleryIDs.isNullOrEmpty()) { //No result
+ withContext(Dispatchers.Main) {
+ main_noresult.visibility = View.VISIBLE
+ main_progressbar.hide()
}
- if (query.isNotEmpty() and defaultQuery.isNotEmpty() and cache.isNullOrEmpty()) {
+ return@launch
+ }
+
+ if (query.isEmpty() and defaultQuery.isEmpty())
+ fetchGalleries("", galleries.size+perPage)
+ else
+ with(main_recyclerview.adapter as GalleryBlockAdapter) {
+ noMore = galleries.size + perPage >= galleryIDs.size
+ }
+
+ when {
+ query.isEmpty() and defaultQuery.isEmpty() ->
+ galleryIDs
+ else ->
+ galleryIDs.slice(galleries.size until Math.min(galleries.size+perPage, galleryIDs.size))
+ }.chunked(4).forEach { chunked ->
+ chunked.map {
+ async {
+ val galleryBlock = getGalleryBlock(it)
+ val thumbnail: Bitmap
+
+ with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
+ thumbnail = BitmapFactory.decodeStream(inputStream)
+ }
+
+ Pair(galleryBlock, thumbnail)
+ }
+ }.forEach {
+ val galleryBlock = it.await()
+
withContext(Dispatchers.Main) {
- main_noresult.visibility = View.VISIBLE
main_progressbar.hide()
+
+ galleries.add(galleryBlock)
+ main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
}
}
-
- galleryIDs.chunked(4).forEach { chunked ->
- chunked.map {
- async {
- val galleryBlock = getGalleryBlock(it)
- val thumbnail: Bitmap
-
- with(galleryBlock.thumbnails[0].openConnection() as HttpsURLConnection) {
- thumbnail = BitmapFactory.decodeStream(inputStream)
- }
-
- Pair(galleryBlock, thumbnail)
- }
- }.forEach {
- val galleryBlock = it.await()
-
- withContext(Dispatchers.Main) {
- main_progressbar.hide()
-
- galleries.add(galleryBlock)
- main_recyclerview.adapter?.notifyItemInserted(galleries.size - 1)
- }
- }
- }
- } finally {
- isLoading = false
}
}
}
diff --git a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt b/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
index 40624e27..b9d95dda 100644
--- a/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
+++ b/app/src/main/java/xyz/quaver/pupil/SettingsActivity.kt
@@ -7,6 +7,8 @@ import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.Preference
import androidx.preference.PreferenceFragmentCompat
+import xyz.quaver.pupil.util.Histories
+import java.io.File
class SettingsActivity : AppCompatActivity() {
@@ -35,8 +37,8 @@ class SettingsActivity : AppCompatActivity() {
"TB" //really?
)
- private fun getCacheSize() : String {
- var size = context!!.cacheDir.walk().map { it.length() }.sum()
+ private fun getCacheSize(dir: File) : String {
+ var size = dir.walk().map { it.length() }.sum()
var suffixIndex = 0
while (size >= 1024) {
@@ -50,22 +52,43 @@ class SettingsActivity : AppCompatActivity() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.root_preferences, rootKey)
- with(findPreference("delete_cache")) {
+ with(findPreference("delete_image_cache")) {
this ?: return@with
- summary = getCacheSize()
+ val dir = File(context.cacheDir, "imageCache")
+
+ summary = getCacheSize(dir)
setOnPreferenceClickListener {
AlertDialog.Builder(context).apply {
setTitle(R.string.warning)
setMessage(R.string.settings_clear_cache_alert_message)
setPositiveButton(android.R.string.yes) { _, _ ->
- with(context.cacheDir) {
- if (exists())
- deleteRecursively()
- }
+ if (dir.exists())
+ dir.deleteRecursively()
- summary = getCacheSize()
+ summary = getCacheSize(dir)
+ }
+ setNegativeButton(android.R.string.no) { _, _ -> }
+ }.show()
+
+ true
+ }
+ }
+ with(findPreference("clear_history")) {
+ this ?: return@with
+
+ val histories = Histories.default
+
+ summary = getString(R.string.settings_clear_history_summary, histories.size)
+
+ setOnPreferenceClickListener {
+ AlertDialog.Builder(context).apply {
+ setTitle(R.string.warning)
+ setMessage(R.string.settings_clear_history_alert_message)
+ setPositiveButton(android.R.string.yes) { _, _ ->
+ histories.clear()
+ summary = getString(R.string.settings_clear_history_summary, histories.size)
}
setNegativeButton(android.R.string.no) { _, _ -> }
}.show()
diff --git a/app/src/main/java/xyz/quaver/pupil/util/history.kt b/app/src/main/java/xyz/quaver/pupil/util/history.kt
new file mode 100644
index 00000000..8ebfaad1
--- /dev/null
+++ b/app/src/main/java/xyz/quaver/pupil/util/history.kt
@@ -0,0 +1,74 @@
+package xyz.quaver.pupil.util
+
+import kotlinx.serialization.ImplicitReflectionSerializer
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonConfiguration
+import kotlinx.serialization.parseList
+import kotlinx.serialization.stringify
+import java.io.File
+
+
+class Histories(private val file: File) : ArrayList() {
+
+ init {
+ if (!file.exists())
+ file.parentFile.mkdirs()
+
+ try {
+ load()
+ } catch (e: Exception) {
+ save()
+ }
+ }
+
+ companion object {
+ lateinit var default: Histories
+
+ fun load(file: File) : Histories {
+ return Histories(file).load()
+ }
+ }
+
+ @UseExperimental(ImplicitReflectionSerializer::class)
+ fun load() : Histories {
+ return apply {
+ super.clear()
+ addAll(
+ Json(JsonConfiguration.Stable).parseList(
+ file.bufferedReader().use { it.readText() }
+ )
+ )
+ }
+ }
+
+ @UseExperimental(ImplicitReflectionSerializer::class)
+ fun save() {
+ file.writeText(Json(JsonConfiguration.Stable).stringify(this))
+ }
+
+ override fun add(element: Int): Boolean {
+ load()
+
+ if (contains(element))
+ super.remove(element)
+
+ super.add(0, element)
+
+ save()
+
+ return true
+ }
+
+ override fun remove(element: Int): Boolean {
+ load()
+ val retval = super.remove(element)
+ save()
+
+ return retval
+ }
+
+ override fun clear() {
+ super.clear()
+ save()
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-anydpi/ic_history.xml b/app/src/main/res/drawable-anydpi/ic_history.xml
new file mode 100644
index 00000000..e5e6c6c8
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_history.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable-anydpi/ic_home.xml b/app/src/main/res/drawable-anydpi/ic_home.xml
new file mode 100644
index 00000000..08ebbdf2
--- /dev/null
+++ b/app/src/main/res/drawable-anydpi/ic_home.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/app/src/main/res/drawable-hdpi/ic_history.png b/app/src/main/res/drawable-hdpi/ic_history.png
new file mode 100644
index 00000000..8610919f
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_history.png differ
diff --git a/app/src/main/res/drawable-hdpi/ic_home.png b/app/src/main/res/drawable-hdpi/ic_home.png
new file mode 100644
index 00000000..caccfac0
Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_home.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_history.png b/app/src/main/res/drawable-mdpi/ic_history.png
new file mode 100644
index 00000000..e64059c8
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_history.png differ
diff --git a/app/src/main/res/drawable-mdpi/ic_home.png b/app/src/main/res/drawable-mdpi/ic_home.png
new file mode 100644
index 00000000..1eccf9f3
Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_home.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_history.png b/app/src/main/res/drawable-xhdpi/ic_history.png
new file mode 100644
index 00000000..4a9622d2
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_history.png differ
diff --git a/app/src/main/res/drawable-xhdpi/ic_home.png b/app/src/main/res/drawable-xhdpi/ic_home.png
new file mode 100644
index 00000000..cea7b6c5
Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_home.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_history.png b/app/src/main/res/drawable-xxhdpi/ic_history.png
new file mode 100644
index 00000000..c22644eb
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_history.png differ
diff --git a/app/src/main/res/drawable-xxhdpi/ic_home.png b/app/src/main/res/drawable-xxhdpi/ic_home.png
new file mode 100644
index 00000000..a576a1a4
Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_home.png differ
diff --git a/app/src/main/res/menu/activity_main_drawer.xml b/app/src/main/res/menu/activity_main_drawer.xml
index 71a9e813..1877c34f 100644
--- a/app/src/main/res/menu/activity_main_drawer.xml
+++ b/app/src/main/res/menu/activity_main_drawer.xml
@@ -1,7 +1,15 @@
\ 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 63576ee9..eacd6842 100644
--- a/app/src/main/res/values-ja/strings.xml
+++ b/app/src/main/res/values-ja/strings.xml
@@ -7,7 +7,7 @@
検索
ギャラリー検索
キャッシュ
- キャッシュクリア
+ イメージキャッシュクリア
キャッシュをクリアするとイメージのロード速度に影響を与えます。実行しますか?
キャッシュサイズ: %1$d%2$s
デフォルト検索キーワード
@@ -22,4 +22,9 @@
イメージロード
ロード速度を向上させるためhiyobi.meからイメージロード
hiyobi.meからロード
+ 履歴の削除
+ 履歴を削除しますか?
+ 履歴数: %1$d
+ 履歴
+ トップ
\ 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 85b179fd..e4872bb0 100644
--- a/app/src/main/res/values-ko/strings.xml
+++ b/app/src/main/res/values-ko/strings.xml
@@ -6,7 +6,7 @@
권한을 거부하면 일부 기능이 작동하지 않을 수 있습니다
갤러리 검색
기본 검색어
- 캐시 정리하기
+ 이미지 캐시 정리하기
캐시를 정리하면 이미지 로딩속도가 느려질 수 있습니다. 계속하시겠습니까?
현재 캐시 사용량: %1$d%2$s
한 번에 로드할 갤러리 수
@@ -22,4 +22,9 @@
이미지 로딩
속도 향상을 위해 가능하면 hiyobi.me에서 이미지 로드
hiyobi.me 사용
+ 히스토리 삭제
+ 히스토리를 삭제하시겠습니까?
+ 히스토리 %1$d개 저장됨
+ 히스토리
+ 홈
\ 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 473541df..1d165044 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -18,6 +18,9 @@
Search
No result
+ Home
+ History
+
Update available
Version %1$s is available!\n(current version is %2$s)\nDo you want to update?
Downloading apk…
@@ -33,9 +36,12 @@
Galleries per page
Default query
Cache
- Clear cache
+ Clear image cache
Currently using %1$d%2$s of cache
Deleting cache can affect image loading speed. Do you want to continue?
+ Clear history
+ Do you want to clear histories?
+ %1$d histories saved
Image Loading
Use hiyobi.me
Load images from hiyobi.me to improve loading speed (if available)
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index a967b6bd..5dbfcadf 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -25,8 +25,12 @@
app:title="@string/settings_cache_title">
+ app:title="@string/settings_clear_image_cache"
+ app:key="delete_image_cache"/>
+
+
diff --git a/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt b/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
index 763e19e4..fec18cac 100644
--- a/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
+++ b/app/src/test/java/xyz/quaver/pupil/ExampleUnitTest.kt
@@ -1,7 +1,7 @@
package xyz.quaver.pupil
+import kotlinx.serialization.ImplicitReflectionSerializer
import org.junit.Test
-import xyz.quaver.pupil.util.checkUpdate
/**
* Example local unit test, which will execute on the development machine (host).
@@ -12,8 +12,9 @@ import xyz.quaver.pupil.util.checkUpdate
class ExampleUnitTest {
@Test
+ @ImplicitReflectionSerializer
fun test() {
- print(checkUpdate("https://api.github.com/repos/tom5079/Pupil-issue/releases", "0.0.1"))
+
}
}