Implemented Source Selector
This commit is contained in:
@@ -124,7 +124,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation "xyz.quaver:libpupil:1.9.7"
|
implementation "xyz.quaver:libpupil:1.9.7"
|
||||||
implementation "xyz.quaver:documentfilex:0.4-alpha02"
|
implementation "xyz.quaver:documentfilex:0.4-alpha02"
|
||||||
implementation "xyz.quaver:floatingsearchview:1.0.7"
|
implementation "xyz.quaver:floatingsearchview:1.0.9"
|
||||||
|
|
||||||
testImplementation "junit:junit:4.13.1"
|
testImplementation "junit:junit:4.13.1"
|
||||||
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
androidTestImplementation "androidx.test.ext:junit:1.1.2"
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import okhttp3.Interceptor
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import xyz.quaver.io.FileX
|
import xyz.quaver.io.FileX
|
||||||
|
import xyz.quaver.pupil.sources.initSources
|
||||||
import xyz.quaver.pupil.types.Tag
|
import xyz.quaver.pupil.types.Tag
|
||||||
import xyz.quaver.pupil.util.*
|
import xyz.quaver.pupil.util.*
|
||||||
import xyz.quaver.setClient
|
import xyz.quaver.setClient
|
||||||
@@ -89,6 +90,8 @@ class Pupil : Application() {
|
|||||||
firebaseAnalytics = Firebase.analytics
|
firebaseAnalytics = Firebase.analytics
|
||||||
FirebaseCrashlytics.getInstance().setUserId(userID)
|
FirebaseCrashlytics.getInstance().setUserId(userID)
|
||||||
|
|
||||||
|
initSources(this)
|
||||||
|
|
||||||
val proxyInfo = getProxyInfo()
|
val proxyInfo = getProxyInfo()
|
||||||
|
|
||||||
clientBuilder = OkHttpClient.Builder()
|
clientBuilder = OkHttpClient.Builder()
|
||||||
|
|||||||
59
app/src/main/java/xyz/quaver/pupil/adapters/SourceAdapter.kt
Normal file
59
app/src/main/java/xyz/quaver/pupil/adapters/SourceAdapter.kt
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.LayoutInflater
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.core.graphics.drawable.DrawableCompat
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import xyz.quaver.pupil.databinding.SourceSelectDialogItemBinding
|
||||||
|
import xyz.quaver.pupil.sources.Source
|
||||||
|
import xyz.quaver.pupil.sources.sourceIcons
|
||||||
|
|
||||||
|
class SourceAdapter(private val sources: List<Source<*>>) : RecyclerView.Adapter<SourceAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
var onSourceSelectedListener: ((Source<*>) -> Unit)? = null
|
||||||
|
|
||||||
|
inner class ViewHolder(private val binding: SourceSelectDialogItemBinding) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
lateinit var source: Source<*>
|
||||||
|
|
||||||
|
init {
|
||||||
|
binding.go.setOnClickListener {
|
||||||
|
onSourceSelectedListener?.invoke(source)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun bind(source: Source<*>) {
|
||||||
|
this.source = source
|
||||||
|
|
||||||
|
binding.icon.setImageDrawable(sourceIcons[source.name])
|
||||||
|
binding.name.text = source.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
|
return ViewHolder(SourceSelectDialogItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
|
||||||
|
holder.bind(sources[position])
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getItemCount(): Int = sources.size
|
||||||
|
}
|
||||||
@@ -18,9 +18,13 @@
|
|||||||
|
|
||||||
package xyz.quaver.pupil.sources
|
package xyz.quaver.pupil.sources
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import xyz.quaver.pupil.R
|
import xyz.quaver.pupil.R
|
||||||
import kotlin.reflect.KClass
|
import xyz.quaver.pupil.sources.hitomi.Hitomi
|
||||||
|
import xyz.quaver.pupil.sources.hitomi.Hiyobi
|
||||||
|
|
||||||
data class SearchResult(
|
data class SearchResult(
|
||||||
val id: String,
|
val id: String,
|
||||||
@@ -49,8 +53,28 @@ data class SearchResult(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Source<Query_SortMode: Enum<*>> {
|
enum class DefaultSortMode {
|
||||||
val querySortModeClass: KClass<Query_SortMode>?
|
DEFAULT
|
||||||
|
}
|
||||||
|
interface Source<Query_SortMode : Enum<Query_SortMode>> {
|
||||||
|
val name: String
|
||||||
|
val iconResID: Int
|
||||||
|
val availableSortMode: Array<Query_SortMode>
|
||||||
|
|
||||||
suspend fun query(query: String, range: IntRange, sortMode: Query_SortMode? = null) : Pair<Channel<SearchResult>, Int>
|
suspend fun query(query: String, range: IntRange, sortMode: Enum<*>) : Pair<Channel<SearchResult>, Int>
|
||||||
|
}
|
||||||
|
|
||||||
|
val sources = mutableMapOf<String, Source<*>>()
|
||||||
|
val sourceIcons = mutableMapOf<String, Drawable?>()
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun initSources(context: Context) {
|
||||||
|
// Add Default Sources
|
||||||
|
listOf(
|
||||||
|
Hitomi(),
|
||||||
|
Hiyobi()
|
||||||
|
).forEach {
|
||||||
|
sources[it.name] = it
|
||||||
|
sourceIcons[it.name] = ContextCompat.getDrawable(context, it.iconResID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ package xyz.quaver.pupil.sources.hitomi
|
|||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import xyz.quaver.hitomi.*
|
import xyz.quaver.hitomi.*
|
||||||
|
import xyz.quaver.pupil.R
|
||||||
import xyz.quaver.pupil.sources.SearchResult
|
import xyz.quaver.pupil.sources.SearchResult
|
||||||
import xyz.quaver.pupil.sources.SearchResult.ExtraType
|
import xyz.quaver.pupil.sources.SearchResult.ExtraType
|
||||||
import xyz.quaver.pupil.sources.Source
|
import xyz.quaver.pupil.sources.Source
|
||||||
@@ -30,18 +31,20 @@ import kotlin.math.min
|
|||||||
|
|
||||||
class Hitomi : Source<Hitomi.SortMode> {
|
class Hitomi : Source<Hitomi.SortMode> {
|
||||||
|
|
||||||
override val querySortModeClass = SortMode::class
|
|
||||||
|
|
||||||
enum class SortMode {
|
enum class SortMode {
|
||||||
NEWEST,
|
NEWEST,
|
||||||
POPULAR
|
POPULAR
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val name: String = "hitomi.la"
|
||||||
|
override val iconResID: Int = R.drawable.hitomi
|
||||||
|
override val availableSortMode: Array<SortMode> = SortMode.values()
|
||||||
|
|
||||||
var cachedQuery: String? = null
|
var cachedQuery: String? = null
|
||||||
var cachedSortMode: SortMode? = null
|
var cachedSortMode: SortMode? = null
|
||||||
val cache = mutableListOf<Int>()
|
val cache = mutableListOf<Int>()
|
||||||
|
|
||||||
override suspend fun query(query: String, range: IntRange, sortMode: SortMode?): Pair<Channel<SearchResult>, Int> {
|
override suspend fun query(query: String, range: IntRange, sortMode: Enum<*>): Pair<Channel<SearchResult>, Int> {
|
||||||
if (cachedQuery != query || cachedSortMode != sortMode || cache.isEmpty()) {
|
if (cachedQuery != query || cachedSortMode != sortMode || cache.isEmpty()) {
|
||||||
cachedQuery = null
|
cachedQuery = null
|
||||||
cache.clear()
|
cache.clear()
|
||||||
|
|||||||
@@ -23,14 +23,19 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import xyz.quaver.hiyobi.*
|
import xyz.quaver.hiyobi.*
|
||||||
|
import xyz.quaver.pupil.R
|
||||||
|
import xyz.quaver.pupil.sources.DefaultSortMode
|
||||||
import xyz.quaver.pupil.sources.SearchResult
|
import xyz.quaver.pupil.sources.SearchResult
|
||||||
import xyz.quaver.pupil.sources.Source
|
import xyz.quaver.pupil.sources.Source
|
||||||
import xyz.quaver.pupil.util.wordCapitalize
|
import xyz.quaver.pupil.util.wordCapitalize
|
||||||
|
|
||||||
class Hiyobi : Source<Enum<*>> {
|
class Hiyobi : Source<DefaultSortMode> {
|
||||||
override val querySortModeClass = null
|
|
||||||
|
|
||||||
override suspend fun query(query: String, range: IntRange, sortMode: Enum<*>?): Pair<Channel<SearchResult>, Int> {
|
override val name: String = "hiyobi.me"
|
||||||
|
override val iconResID: Int = R.drawable.ic_hiyobi
|
||||||
|
override val availableSortMode: Array<DefaultSortMode> = DefaultSortMode.values()
|
||||||
|
|
||||||
|
override suspend fun query(query: String, range: IntRange, sortMode: Enum<*>): Pair<Channel<SearchResult>, Int> {
|
||||||
val channel = Channel<SearchResult>()
|
val channel = Channel<SearchResult>()
|
||||||
|
|
||||||
val (results, total) = if (query.isEmpty())
|
val (results, total) = if (query.isEmpty())
|
||||||
@@ -59,7 +64,7 @@ class Hiyobi : Source<Enum<*>> {
|
|||||||
mapOf(
|
mapOf(
|
||||||
SearchResult.ExtraType.CHARACTER to { galleryBlock.characters.joinToString { it.value.wordCapitalize() } },
|
SearchResult.ExtraType.CHARACTER to { galleryBlock.characters.joinToString { it.value.wordCapitalize() } },
|
||||||
SearchResult.ExtraType.SERIES to { galleryBlock.parodys.joinToString { it.value.wordCapitalize() } },
|
SearchResult.ExtraType.SERIES to { galleryBlock.parodys.joinToString { it.value.wordCapitalize() } },
|
||||||
SearchResult.ExtraType.TYPE to { galleryBlock.type.name.wordCapitalize() },
|
SearchResult.ExtraType.TYPE to { galleryBlock.type.name.replace('_', ' ').wordCapitalize() },
|
||||||
SearchResult.ExtraType.PAGECOUNT to { getGalleryInfo(galleryBlock.id).files.size.toString() }
|
SearchResult.ExtraType.PAGECOUNT to { getGalleryInfo(galleryBlock.id).files.size.toString() }
|
||||||
),
|
),
|
||||||
galleryBlock.tags.map { it.value }
|
galleryBlock.tags.map { it.value }
|
||||||
|
|||||||
@@ -25,23 +25,27 @@ import android.os.Bundle
|
|||||||
import android.text.InputType
|
import android.text.InputType
|
||||||
import android.text.util.Linkify
|
import android.text.util.Linkify
|
||||||
import android.view.KeyEvent
|
import android.view.KeyEvent
|
||||||
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.DecelerateInterpolator
|
import android.view.animation.DecelerateInterpolator
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.cardview.widget.CardView
|
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.ViewCompat
|
import androidx.core.view.ViewCompat
|
||||||
|
import androidx.core.view.children
|
||||||
|
import androidx.core.widget.ImageViewCompat
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import androidx.swiperefreshlayout.widget.CircularProgressDrawable
|
||||||
|
import com.daimajia.swipe.adapters.RecyclerSwipeAdapter
|
||||||
import com.google.android.material.navigation.NavigationView
|
import com.google.android.material.navigation.NavigationView
|
||||||
import com.google.android.material.snackbar.Snackbar
|
import com.google.android.material.snackbar.Snackbar
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.channels.Channel
|
import kotlinx.coroutines.channels.Channel
|
||||||
import xyz.quaver.floatingsearchview.FloatingSearchView
|
import xyz.quaver.floatingsearchview.FloatingSearchView
|
||||||
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
|
import xyz.quaver.floatingsearchview.suggestions.model.SearchSuggestion
|
||||||
import xyz.quaver.floatingsearchview.util.view.MenuView
|
|
||||||
import xyz.quaver.floatingsearchview.util.view.SearchInputView
|
import xyz.quaver.floatingsearchview.util.view.SearchInputView
|
||||||
import xyz.quaver.hitomi.getSuggestionsForQuery
|
import xyz.quaver.hitomi.getSuggestionsForQuery
|
||||||
import xyz.quaver.pupil.*
|
import xyz.quaver.pupil.*
|
||||||
@@ -50,18 +54,16 @@ import xyz.quaver.pupil.databinding.MainActivityBinding
|
|||||||
import xyz.quaver.pupil.services.DownloadService
|
import xyz.quaver.pupil.services.DownloadService
|
||||||
import xyz.quaver.pupil.sources.SearchResult
|
import xyz.quaver.pupil.sources.SearchResult
|
||||||
import xyz.quaver.pupil.sources.Source
|
import xyz.quaver.pupil.sources.Source
|
||||||
import xyz.quaver.pupil.sources.hitomi.Hitomi
|
import xyz.quaver.pupil.sources.sourceIcons
|
||||||
import xyz.quaver.pupil.sources.hitomi.Hiyobi
|
import xyz.quaver.pupil.sources.sources
|
||||||
import xyz.quaver.pupil.types.*
|
import xyz.quaver.pupil.types.*
|
||||||
import xyz.quaver.pupil.ui.dialog.DownloadLocationDialogFragment
|
import xyz.quaver.pupil.ui.dialog.DownloadLocationDialogFragment
|
||||||
import xyz.quaver.pupil.ui.dialog.GalleryDialog
|
import xyz.quaver.pupil.ui.dialog.GalleryDialog
|
||||||
|
import xyz.quaver.pupil.ui.dialog.SourceSelectDialog
|
||||||
import xyz.quaver.pupil.ui.view.ProgressCardView
|
import xyz.quaver.pupil.ui.view.ProgressCardView
|
||||||
import xyz.quaver.pupil.ui.view.SwipePageTurnView
|
import xyz.quaver.pupil.ui.view.SwipePageTurnView
|
||||||
import xyz.quaver.pupil.util.ItemClickSupport
|
import xyz.quaver.pupil.util.*
|
||||||
import xyz.quaver.pupil.util.Preferences
|
|
||||||
import xyz.quaver.pupil.util.checkUpdate
|
|
||||||
import xyz.quaver.pupil.util.downloader.DownloadManager
|
import xyz.quaver.pupil.util.downloader.DownloadManager
|
||||||
import xyz.quaver.pupil.util.restore
|
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.math.*
|
import kotlin.math.*
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@@ -82,9 +84,8 @@ class MainActivity :
|
|||||||
}
|
}
|
||||||
private var queryStack = mutableListOf<String>()
|
private var queryStack = mutableListOf<String>()
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
private lateinit var source: Source<*>
|
||||||
private var source: Source<Enum<*>> = Hiyobi() as Source<Enum<*>>
|
private lateinit var sortMode: Enum<*>
|
||||||
private var sortMode = Hitomi.SortMode.NEWEST
|
|
||||||
|
|
||||||
private var searchJob: Deferred<Pair<Channel<SearchResult>, Int>>? = null
|
private var searchJob: Deferred<Pair<Channel<SearchResult>, Int>>? = null
|
||||||
private var totalItems = 0
|
private var totalItems = 0
|
||||||
@@ -97,6 +98,8 @@ class MainActivity :
|
|||||||
binding = MainActivityBinding.inflate(layoutInflater)
|
binding = MainActivityBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
setSource(sources.values.first())
|
||||||
|
|
||||||
if (intent.action == Intent.ACTION_VIEW) {
|
if (intent.action == Intent.ACTION_VIEW) {
|
||||||
intent.dataString?.let { url ->
|
intent.dataString?.let { url ->
|
||||||
restore(url,
|
restore(url,
|
||||||
@@ -167,6 +170,34 @@ class MainActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun setSource(source: Source<*>) {
|
||||||
|
this.source = source
|
||||||
|
sortMode = source.availableSortMode.first()
|
||||||
|
|
||||||
|
query = ""
|
||||||
|
currentPage = 1
|
||||||
|
|
||||||
|
with (binding.contents.searchview.binding.querySection.menuView) {
|
||||||
|
post {
|
||||||
|
menuItems.findMenu(R.id.sort).subMenu.apply {
|
||||||
|
clear()
|
||||||
|
|
||||||
|
source.availableSortMode.forEach {
|
||||||
|
add(R.id.sort_mode_group_id, it.ordinal, Menu.NONE, it.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
setGroupCheckable(R.id.sort_mode_group_id, true, true)
|
||||||
|
|
||||||
|
children.first().isChecked = true
|
||||||
|
}
|
||||||
|
with (getChildAt(1) as ImageView) {
|
||||||
|
ImageViewCompat.setImageTintList(this, null)
|
||||||
|
setImageDrawable(sourceIcons[source.name])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun initView() {
|
private fun initView() {
|
||||||
binding.contents.recyclerview.addOnScrollListener(object: RecyclerView.OnScrollListener() {
|
binding.contents.recyclerview.addOnScrollListener(object: RecyclerView.OnScrollListener() {
|
||||||
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) {
|
||||||
@@ -175,7 +206,7 @@ class MainActivity :
|
|||||||
min(
|
min(
|
||||||
max(
|
max(
|
||||||
binding.contents.searchview.translationY - dy,
|
binding.contents.searchview.translationY - dy,
|
||||||
-binding.contents.searchview.findViewById<CardView>(R.id.search_query_section).height.toFloat()
|
-binding.contents.searchview.binding.querySection.root.height.toFloat()
|
||||||
), 0F)
|
), 0F)
|
||||||
|
|
||||||
if (dy > 0)
|
if (dy > 0)
|
||||||
@@ -224,6 +255,7 @@ class MainActivity :
|
|||||||
with(binding.contents.randomFab) {
|
with(binding.contents.randomFab) {
|
||||||
setImageResource(R.drawable.shuffle_variant)
|
setImageResource(R.drawable.shuffle_variant)
|
||||||
setOnClickListener {
|
setOnClickListener {
|
||||||
|
setImageDrawable(CircularProgressDrawable(context))
|
||||||
if (totalItems > 0)
|
if (totalItems > 0)
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
val random = Random.Default.nextInt(totalItems)
|
val random = Random.Default.nextInt(totalItems)
|
||||||
@@ -236,6 +268,7 @@ class MainActivity :
|
|||||||
).first.receive()
|
).first.receive()
|
||||||
|
|
||||||
launch(Dispatchers.Main) {
|
launch(Dispatchers.Main) {
|
||||||
|
setImageResource(R.drawable.shuffle_variant)
|
||||||
GalleryDialog(this@MainActivity, randomResult.id).apply {
|
GalleryDialog(this@MainActivity, randomResult.id).apply {
|
||||||
onChipClickedHandler.add {
|
onChipClickedHandler.add {
|
||||||
query = it.toQuery()
|
query = it.toQuery()
|
||||||
@@ -394,7 +427,7 @@ class MainActivity :
|
|||||||
with(binding.contents.searchview) {
|
with(binding.contents.searchview) {
|
||||||
onMenuStatusChangeListener = object: FloatingSearchView.OnMenuStatusChangeListener {
|
onMenuStatusChangeListener = object: FloatingSearchView.OnMenuStatusChangeListener {
|
||||||
override fun onMenuOpened() {
|
override fun onMenuOpened() {
|
||||||
(binding.contents.recyclerview.adapter as SearchResultsAdapter).closeAllItems()
|
(this@MainActivity.binding.contents.recyclerview.adapter as SearchResultsAdapter).closeAllItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onMenuClosed() {
|
override fun onMenuClosed() {
|
||||||
@@ -402,14 +435,6 @@ class MainActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
post {
|
|
||||||
findViewById<MenuView>(R.id.menu_view).menuItems.firstOrNull {
|
|
||||||
(it as MenuItem).itemId == R.id.main_menu_thin
|
|
||||||
}?.let {
|
|
||||||
(it as MenuItem).isChecked = Preferences["thin"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onHistoryDeleteClickedListener = {
|
onHistoryDeleteClickedListener = {
|
||||||
searchHistory.remove(it)
|
searchHistory.remove(it)
|
||||||
swapSuggestions(defaultSuggestions)
|
swapSuggestions(defaultSuggestions)
|
||||||
@@ -473,37 +498,32 @@ class MainActivity :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
attachNavigationDrawerToMenuButton(binding.drawer)
|
attachNavigationDrawerToMenuButton(this@MainActivity.binding.drawer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onActionMenuItemSelected(item: MenuItem?) {
|
private fun onActionMenuItemSelected(item: MenuItem?) {
|
||||||
when(item?.itemId) {
|
if (item?.groupId == R.id.sort_mode_group_id) {
|
||||||
R.id.main_menu_settings -> startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
|
currentPage = 1
|
||||||
R.id.main_menu_thin -> {
|
sortMode = source.availableSortMode.let { availableSortMode ->
|
||||||
// TODO
|
availableSortMode.getOrElse(item.itemId) { availableSortMode.first() }
|
||||||
}
|
}
|
||||||
R.id.main_menu_sort_newest -> {
|
|
||||||
sortMode = Hitomi.SortMode.NEWEST
|
|
||||||
item.isChecked = true
|
|
||||||
|
|
||||||
runOnUiThread {
|
query()
|
||||||
currentPage = 1
|
|
||||||
|
|
||||||
query()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
R.id.main_menu_sort_popular -> {
|
|
||||||
sortMode = Hitomi.SortMode.POPULAR
|
|
||||||
item.isChecked = true
|
|
||||||
|
|
||||||
runOnUiThread {
|
|
||||||
currentPage = 1
|
|
||||||
|
|
||||||
query()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
when(item?.itemId) {
|
||||||
|
R.id.main_menu_settings -> startActivity(Intent(this@MainActivity, SettingsActivity::class.java))
|
||||||
|
R.id.source -> SourceSelectDialog().apply {
|
||||||
|
onSourceSelectedListener = {
|
||||||
|
setSource(it)
|
||||||
|
|
||||||
|
query()
|
||||||
|
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}.show(supportFragmentManager, null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
override fun onNavigationItemSelected(item: MenuItem): Boolean {
|
||||||
@@ -539,6 +559,7 @@ class MainActivity :
|
|||||||
private fun clearGalleries() = CoroutineScope(Dispatchers.Main).launch {
|
private fun clearGalleries() = CoroutineScope(Dispatchers.Main).launch {
|
||||||
searchResults.clear()
|
searchResults.clear()
|
||||||
|
|
||||||
|
(binding.contents.recyclerview.adapter as RecyclerSwipeAdapter).mItemManger.closeAllItems()
|
||||||
binding.contents.recyclerview.adapter?.notifyDataSetChanged()
|
binding.contents.recyclerview.adapter?.notifyDataSetChanged()
|
||||||
|
|
||||||
binding.contents.noresult.visibility = View.INVISIBLE
|
binding.contents.noresult.visibility = View.INVISIBLE
|
||||||
|
|||||||
@@ -64,12 +64,7 @@ class GalleryDialog(context: Context, private val galleryID: String) : AlertDial
|
|||||||
binding = GalleryDialogBinding.inflate(layoutInflater)
|
binding = GalleryDialogBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
window?.attributes.apply {
|
window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
|
||||||
this ?: return@apply
|
|
||||||
|
|
||||||
width = LayoutParams.MATCH_PARENT
|
|
||||||
height = LayoutParams.MATCH_PARENT
|
|
||||||
}
|
|
||||||
|
|
||||||
with(binding.fab) {
|
with(binding.fab) {
|
||||||
setImageDrawable(ContextCompat.getDrawable(context, R.drawable.arrow_right))
|
setImageDrawable(ContextCompat.getDrawable(context, R.drawable.arrow_right))
|
||||||
|
|||||||
@@ -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.ui.dialog
|
||||||
|
|
||||||
|
import android.app.Dialog
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.view.ViewGroup.LayoutParams
|
||||||
|
import android.view.Window
|
||||||
|
import androidx.fragment.app.DialogFragment
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
|
import xyz.quaver.pupil.adapters.SourceAdapter
|
||||||
|
import xyz.quaver.pupil.sources.Source
|
||||||
|
import xyz.quaver.pupil.sources.sources
|
||||||
|
|
||||||
|
class SourceSelectDialog : DialogFragment() {
|
||||||
|
|
||||||
|
var onSourceSelectedListener: ((Source<*>) -> Unit)? = null
|
||||||
|
|
||||||
|
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||||
|
return Dialog(requireContext()).apply {
|
||||||
|
window?.requestFeature(Window.FEATURE_NO_TITLE)
|
||||||
|
window?.setLayout(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)
|
||||||
|
|
||||||
|
setContentView(RecyclerView(context).apply {
|
||||||
|
layoutManager = LinearLayoutManager(context)
|
||||||
|
adapter = SourceAdapter(sources.values.toList()).apply {
|
||||||
|
onSourceSelectedListener = this@SourceSelectDialog.onSourceSelectedListener
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -407,6 +407,16 @@ public class SwipePageTurnView extends ViewGroup implements NestedScrollingChild
|
|||||||
stopNestedScroll();
|
stopNestedScroll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onNestedPreFling(View target, float velocityX, float velocityY) {
|
||||||
|
return dispatchNestedPreFling(velocityX, velocityY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed) {
|
||||||
|
return dispatchNestedFling(velocityX, velocityY, consumed);
|
||||||
|
}
|
||||||
|
|
||||||
// NestedScrollingChild
|
// NestedScrollingChild
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.view.MenuItem
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import kotlinx.serialization.json.*
|
import kotlinx.serialization.json.*
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
@@ -142,4 +143,8 @@ operator fun JsonElement.get(tag: String) =
|
|||||||
this.jsonObject[tag]
|
this.jsonObject[tag]
|
||||||
|
|
||||||
val JsonElement.content
|
val JsonElement.content
|
||||||
get() = this.jsonPrimitive.contentOrNull
|
get() = this.jsonPrimitive.contentOrNull
|
||||||
|
|
||||||
|
fun List<MenuItem>.findMenu(itemID: Int): MenuItem {
|
||||||
|
return first { it.itemId == itemID }
|
||||||
|
}
|
||||||
70
app/src/main/res/layout/source_select_dialog_item.xml
Normal file
70
app/src/main/res/layout/source_select_dialog_item.xml
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?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/>.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_margin="8dp"
|
||||||
|
app:layout_constraintLeft_toLeftOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/name"
|
||||||
|
style="@style/TextAppearance.AppCompat.Button"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/icon"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/settings"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/settings"
|
||||||
|
style="@style/Widget.AppCompat.Button.Borderless"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:adjustViewBounds="true"
|
||||||
|
app:srcCompat="@drawable/ic_settings"
|
||||||
|
app:tint="?attr/colorControlNormal"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintLeft_toRightOf="@id/name"
|
||||||
|
app:layout_constraintRight_toLeftOf="@id/go"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/go"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="GO!"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintRight_toRightOf="parent"/>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@@ -20,19 +20,17 @@
|
|||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/source"
|
||||||
|
android:icon="@drawable/cancel"
|
||||||
|
android:title="Source"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
<item android:id="@+id/sort"
|
<item android:id="@+id/sort"
|
||||||
android:title="@string/main_menu_sort"
|
android:title="@string/main_menu_sort"
|
||||||
android:icon="@drawable/sort_variant"
|
android:icon="@drawable/sort_variant"
|
||||||
app:showAsAction="ifRoom">
|
app:showAsAction="ifRoom">
|
||||||
<menu>
|
<menu/>
|
||||||
<group android:checkableBehavior="single">
|
|
||||||
<item android:id="@+id/main_menu_sort_newest"
|
|
||||||
android:title="@string/main_menu_sort_newest"
|
|
||||||
android:checked="true"/>
|
|
||||||
<item android:id="@+id/main_menu_sort_popular"
|
|
||||||
android:title="@string/main_menu_sort_popular"/>
|
|
||||||
</group>
|
|
||||||
</menu>
|
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item
|
<item
|
||||||
@@ -41,9 +39,4 @@
|
|||||||
android:title="@string/main_settings"
|
android:title="@string/main_settings"
|
||||||
app:showAsAction="always"/>
|
app:showAsAction="always"/>
|
||||||
|
|
||||||
<item android:id="@+id/main_menu_thin"
|
|
||||||
android:title="@string/main_menu_thin"
|
|
||||||
app:showAsAction="never"
|
|
||||||
android:checkable="true"/>
|
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -114,7 +114,6 @@
|
|||||||
<string name="proxy_dialog_error">エラー</string>
|
<string name="proxy_dialog_error">エラー</string>
|
||||||
<string name="proxy_dialog_addr_hint">サーバーアドレス</string>
|
<string name="proxy_dialog_addr_hint">サーバーアドレス</string>
|
||||||
<string name="proxy_dialog_server">サーバー</string>
|
<string name="proxy_dialog_server">サーバー</string>
|
||||||
<string name="main_menu_thin">簡単モード</string>
|
|
||||||
<string name="main_fab_cancel">すべてのダウンロードキャンセル</string>
|
<string name="main_fab_cancel">すべてのダウンロードキャンセル</string>
|
||||||
<string name="channel_update">アップデート</string>
|
<string name="channel_update">アップデート</string>
|
||||||
<string name="channel_update_description">アップデートの進行状態を表示</string>
|
<string name="channel_update_description">アップデートの進行状態を表示</string>
|
||||||
|
|||||||
@@ -114,7 +114,6 @@
|
|||||||
<string name="proxy_dialog_error">잘못된 값</string>
|
<string name="proxy_dialog_error">잘못된 값</string>
|
||||||
<string name="proxy_dialog_addr_hint">서버 주소</string>
|
<string name="proxy_dialog_addr_hint">서버 주소</string>
|
||||||
<string name="proxy_dialog_server">서버</string>
|
<string name="proxy_dialog_server">서버</string>
|
||||||
<string name="main_menu_thin">간단히 보기</string>
|
|
||||||
<string name="main_fab_cancel">다운로드 모두 취소</string>
|
<string name="main_fab_cancel">다운로드 모두 취소</string>
|
||||||
<string name="channel_update">업데이트</string>
|
<string name="channel_update">업데이트</string>
|
||||||
<string name="channel_update_description">업데이트 진행상황 표시</string>
|
<string name="channel_update_description">업데이트 진행상황 표시</string>
|
||||||
|
|||||||
@@ -10,4 +10,6 @@
|
|||||||
|
|
||||||
<item name="notification_download_cancel_action" type="id" />
|
<item name="notification_download_cancel_action" type="id" />
|
||||||
<item name="notification_import_cancel_action" type="id" />
|
<item name="notification_import_cancel_action" type="id" />
|
||||||
|
|
||||||
|
<item name="sort_mode_group_id" type="id"/>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -58,8 +58,6 @@
|
|||||||
<string name="main_drawer_group_contact_email">Email me!</string>
|
<string name="main_drawer_group_contact_email">Email me!</string>
|
||||||
<string name="main_drawer_grouop_contact_discord">Discord</string>
|
<string name="main_drawer_grouop_contact_discord">Discord</string>
|
||||||
|
|
||||||
<string name="main_menu_thin">Thin Mode</string>
|
|
||||||
|
|
||||||
<string name="main_menu_sort">Sort</string>
|
<string name="main_menu_sort">Sort</string>
|
||||||
<string name="main_menu_sort_newest">Newest</string>
|
<string name="main_menu_sort_newest">Newest</string>
|
||||||
<string name="main_menu_sort_popular">Popular</string>
|
<string name="main_menu_sort_popular">Popular</string>
|
||||||
|
|||||||
Reference in New Issue
Block a user