Added History

This commit is contained in:
tom5079
2021-02-21 10:34:26 +09:00
parent 80b7293879
commit a1c6d87c54
14 changed files with 95 additions and 130 deletions

View File

@@ -134,9 +134,9 @@ dependencies {
implementation "ru.noties.markwon:core:3.1.0"
implementation "xyz.quaver:libpupil:1.9.7-SNAPSHOT"
implementation "xyz.quaver:libpupil:1.9.7"
implementation "xyz.quaver:documentfilex:0.4-alpha02"
implementation "xyz.quaver:floatingsearchview:1.1.1"
implementation "xyz.quaver:floatingsearchview:1.1.3-SNAPSHOT"
implementation "com.orhanobut:logger:2.2.0"

View File

@@ -55,7 +55,7 @@ class MirrorAdapter(context: Context) : RecyclerView.Adapter<MirrorAdapter.ViewH
val list = mirrors.keys.toMutableList().apply {
Preferences.get<String>("mirrors")
.split(">")
.reversed()
.asReversed()
.forEach {
if (this.contains(it)) {
this.remove(it)

View File

@@ -18,15 +18,12 @@
package xyz.quaver.pupil.sources
import android.util.Log
import com.orhanobut.logger.Logger
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.launch
import org.kodein.di.DI
import org.kodein.di.DIAware
import org.kodein.di.android.di
import org.kodein.di.instance
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
import xyz.quaver.pupil.util.SavedSourceSet
@@ -47,9 +44,11 @@ class History(override val di: DI, source: String) : Source<DefaultSortMode, Sea
val channel = Channel<ItemInfo>()
CoroutineScope(Dispatchers.IO).launch {
histories.map[source.name]?.forEach {
histories[source.name]?.asReversed()?.forEach {
channel.send(source.info(it))
}
channel.close()
}
return Pair(channel, histories.map.size)

View File

@@ -148,6 +148,7 @@ class MainActivity :
} else {
binding.contents.progressbar.hide()
if (it.isEmpty()) {
binding.contents.recyclerview.adapter?.notifyDataSetChanged()
binding.contents.noresult.show()
} else {
binding.contents.recyclerview.adapter?.notifyItemInserted(it.size-1)
@@ -396,7 +397,7 @@ class MainActivity :
onActionMenuItemSelected(it)
}
onQueryChangeListener = lambda@{ _, query ->
onQueryChangeListener = { _, query ->
model.query.value = query
model.suggestion()
@@ -404,9 +405,7 @@ class MainActivity :
swapSuggestions(listOf(LoadingSuggestion(getText(R.string.reader_loading).toString())))
}
onSuggestionBinding = { binding, item ->
model.source.value!!.onSuggestionBind(binding, item)
}
onSuggestionBinding = model.source.value!!::onSuggestionBind
onFocusChangeListener = object: FloatingSearchView.OnFocusChangeListener {
override fun onFocus() {
@@ -450,24 +449,13 @@ class MainActivity :
binding.drawer.closeDrawers()
when(item.itemId) {
R.id.main_drawer_history -> {
//model.setSourceAndReset(direct.instance<String, History>(arg = source.name))
}
R.id.main_drawer_help -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help))))
}
R.id.main_drawer_github -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github))))
}
R.id.main_drawer_homepage -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
}
R.id.main_drawer_email -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.email))))
}
R.id.main_drawer_kakaotalk -> {
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.discord))))
}
R.id.main_drawer_home -> model.setModeAndReset(MainViewModel.MainMode.SEARCH)
R.id.main_drawer_history -> model.setModeAndReset(MainViewModel.MainMode.HISTORY)
R.id.main_drawer_help -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.help))))
R.id.main_drawer_github -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.github))))
R.id.main_drawer_homepage -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.home_page))))
R.id.main_drawer_email -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.email))))
R.id.main_drawer_kakaotalk -> startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(getString(R.string.discord))))
}
}

View File

@@ -141,7 +141,7 @@ class ReaderActivity : BaseActivity(), DIAware {
menu?.forEach {
when (it.itemId) {
R.id.reader_menu_favorite -> {
if (favorites.map[source]?.contains(itemID) == true)
if (favorites[source]?.contains(itemID) == true)
(it.icon as Animatable).start()
}
R.id.source -> {
@@ -160,7 +160,7 @@ class ReaderActivity : BaseActivity(), DIAware {
val id = itemID
val favorite = menu?.findItem(R.id.reader_menu_favorite) ?: return true
if (favorites.map[source]?.contains(id) == true) {
if (favorites[source]?.contains(id) == true) {
favorites.remove(source, id)
favorite.icon = AnimatedVectorDrawableCompat.create(this, R.drawable.avd_star)
} else {

View File

@@ -75,7 +75,7 @@ class TagChip(context: Context, private val source: String, _tag: Tag) : Chip(co
)
setOnCloseIconClickListener {
if (favoriteTags.map[source]?.contains(tag.toString()) == true) {
if (favoriteTags[source]?.contains(tag.toString()) == true) {
favoriteTags.remove(source, tag.toString())
closeIcon = ContextCompat.getDrawable(context, R.drawable.ic_star_empty)

View File

@@ -25,8 +25,10 @@ import kotlinx.coroutines.*
import org.kodein.di.DIAware
import org.kodein.di.android.x.di
import org.kodein.di.direct
import org.kodein.di.instance
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
import xyz.quaver.pupil.sources.AnySource
import xyz.quaver.pupil.sources.History
import xyz.quaver.pupil.sources.ItemInfo
import xyz.quaver.pupil.util.Preferences
import xyz.quaver.pupil.util.notify
@@ -37,7 +39,6 @@ import kotlin.random.Random
@Suppress("UNCHECKED_CAST")
class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
override val di by di()
private val _searchResults = MutableLiveData<MutableList<ItemInfo>>()
@@ -51,6 +52,10 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
val query = MutableLiveData<String>()
private val queryStack = mutableListOf<String>()
private val defaultSourceFactory: (String) -> AnySource = {
direct.source(it)
}
private var sourceFactory: (String) -> AnySource = defaultSourceFactory
private val _source = MutableLiveData<AnySource>()
val source: LiveData<AnySource> = _source
@@ -82,7 +87,7 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
}
fun setSourceAndReset(sourceName: String) {
_source.value = direct.source(sourceName).also {
_source.value = sourceFactory(sourceName).also {
sortMode.value = it.availableSortMode.first()
}
@@ -97,6 +102,16 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
query()
}
fun setModeAndReset(mode: MainMode) {
sourceFactory = when (mode) {
MainMode.SEARCH -> defaultSourceFactory
MainMode.HISTORY -> { { direct.instance<String, History>(arg = it) } }
else -> return
}
setSourceAndReset(source.value!!.name)
}
fun query() {
val perPage = Preferences["per_page", "25"].toInt()
val source = _source.value ?: error("Source is null")
@@ -181,4 +196,11 @@ class MainViewModel(app: Application) : AndroidViewModel(app), DIAware {
return true
}
enum class MainMode {
SEARCH,
HISTORY,
DOWNLOADS,
FAVORITES
}
}

View File

@@ -21,81 +21,14 @@ package xyz.quaver.pupil.util
import androidx.annotation.RequiresApi
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.builtins.SetSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.Json.Default.decodeFromString
import kotlinx.serialization.serializer
import java.io.File
class SavedSet <T: Any> (private val file: File, any: T, private val set: MutableSet<T> = mutableSetOf()) : MutableSet<T> by set {
@Suppress("UNCHECKED_CAST")
@OptIn(ExperimentalSerializationApi::class)
val serializer: KSerializer<Set<T>> = SetSerializer(serializer(any::class.java) as KSerializer<T>)
init {
if (!file.exists()) {
save()
}
load()
}
@Synchronized
fun load() {
set.clear()
kotlin.runCatching {
decodeFromString(serializer, file.readText())
}.onSuccess {
set.addAll(it)
}
}
@Synchronized
fun save() {
file.parentFile?.mkdirs()
if (!file.exists())
file.createNewFile()
file.writeText(Json.encodeToString(serializer, set))
}
@Synchronized
override fun add(element: T): Boolean {
set.remove(element)
return set.add(element).also {
save()
}
}
@Synchronized
override fun addAll(elements: Collection<T>): Boolean {
set.removeAll(elements)
return set.addAll(elements).also {
save()
}
}
@Synchronized
override fun remove(element: T): Boolean {
load()
return set.remove(element).also {
save()
}
}
@Synchronized
override fun clear() {
set.clear()
save()
}
}
class SavedMap <K: Any, V: Any> (private val file: File, anyKey: K, anyValue: V, private val map: MutableMap<K, V> = mutableMapOf()) : MutableMap<K, V> by map {
@Suppress("UNCHECKED_CAST")
@@ -172,11 +105,10 @@ class SavedMap <K: Any, V: Any> (private val file: File, anyKey: K, anyValue: V,
}
class SavedSourceSet(private val file: File) {
private val _map = mutableMapOf<String, MutableList<String>>()
val map: Map<String, List<String>> = _map
private val _map = mutableMapOf<String, MutableSet<String>>()
val map: Map<String, Set<String>> = _map
private val serializer = MapSerializer(String.serializer(), SetSerializer(String.serializer()))
private val serializer = MapSerializer(String.serializer(), ListSerializer(String.serializer()))
@Synchronized
fun load() {
@@ -185,7 +117,7 @@ class SavedSourceSet(private val file: File) {
decodeFromString(serializer, file.readText())
}.onSuccess {
it.forEach { (k, v) ->
_map[k] = v.toMutableSet()
_map[k] = v.toMutableList()
}
}
}
@@ -199,6 +131,8 @@ class SavedSourceSet(private val file: File) {
file.writeText(Json.encodeToString(serializer, _map))
}
operator fun get(key: String) = _map[key]
@Synchronized
fun add(source: String, value: String) {
load()
@@ -206,7 +140,7 @@ class SavedSourceSet(private val file: File) {
_map[source]?.remove(value)
if (!_map.containsKey(source))
_map[source] = mutableSetOf()
_map[source] = mutableListOf()
else
_map[source]!!.add(value)
@@ -222,7 +156,7 @@ class SavedSourceSet(private val file: File) {
_map[source]!!.removeAll(from[source]!!)
_map[source]!!.addAll(from[source]!!)
} else {
_map[source] = from[source]!!.toMutableSet()
_map[source] = from[source]!!.toMutableList()
}
}

View File

@@ -1,3 +1,21 @@
<!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2021 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/>.
-->
<!--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 7 7c3.86 0 7-3.13 7-7 0-3.86-3.14-7-7-7m0 2.15c2.67 0 4.85 2.17 4.85 4.85 0 2.68-2.18 4.85-4.85 4.85A4.85 4.85 0 0 1 7.15 8 4.85 4.85 0 0 1 12 3.15M11 5v3.69l3.19 1.84 0.75-1.3-2.44-1.41V5M15 16v3H3v2h12v3l4-4m0 0v4h2v-8h-2"/>

View File

@@ -1,3 +1,21 @@
<!--
~ Pupil, Hitomi.la viewer for Android
~ Copyright (C) 2021 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/>.
-->
<!--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 7 7c3.86 0 7-3.13 7-7 0-3.86-3.14-7-7-7m0 2.15c2.67 0 4.85 2.17 4.85 4.85 0 2.68-2.18 4.85-4.85 4.85A4.85 4.85 0 0 1 7.15 8 4.85 4.85 0 0 1 12 3.15M11 5v3.69l3.19 1.84 0.75-1.3-2.44-1.41V5M4 16v8h2v-3h12v3l4-4-4-4v3H6v-3"/>

View File

@@ -19,24 +19,4 @@
<item>SOCKS</item>
</string-array>
<string-array name="cache_size">
<item>0</item>
<item>1</item>
<item>2</item>
<item>4</item>
<item>8</item>
<item>16</item>
<item>32</item>
</string-array>
<string-array name="cache_size_text">
<item>@string/settings_cache_unlimited</item>
<item>1G</item>
<item>2G</item>
<item>4G</item>
<item>8G</item>
<item>16G</item>
<item>32G</item>
</string-array>
</resources>