Dependency update, tag suggestion
This commit is contained in:
@@ -22,7 +22,7 @@ android {
|
||||
compileSdk 34
|
||||
targetSdkVersion 34
|
||||
versionCode 69
|
||||
versionName "5.3.10"
|
||||
versionName "6.0.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
@@ -87,7 +87,7 @@ dependencies {
|
||||
implementation 'androidx.compose.ui:ui'
|
||||
implementation 'androidx.compose.ui:ui-tooling-preview'
|
||||
debugImplementation 'androidx.compose.ui:ui-tooling'
|
||||
androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.6.1'
|
||||
androidTestImplementation 'androidx.compose.ui:ui-test-junit4:1.6.2'
|
||||
debugImplementation 'androidx.compose.ui:ui-test-manifest'
|
||||
implementation 'androidx.compose.material:material-icons-extended'
|
||||
implementation 'androidx.activity:activity-compose:1.8.2'
|
||||
@@ -103,8 +103,6 @@ dependencies {
|
||||
implementation "io.ktor:ktor-client-core:2.3.8"
|
||||
implementation "io.ktor:ktor-client-okhttp:2.3.8"
|
||||
|
||||
implementation "com.daimajia.swipelayout:library:1.2.0@aar"
|
||||
|
||||
implementation "com.google.android.material:material:1.11.0"
|
||||
|
||||
implementation platform('com.google.firebase:firebase-bom:32.7.0')
|
||||
@@ -117,8 +115,6 @@ dependencies {
|
||||
|
||||
implementation "com.github.clans:fab:1.6.4"
|
||||
|
||||
//implementation "com.quiph.ui:recyclerviewfastscroller:0.2.1"
|
||||
|
||||
implementation 'com.github.piasy:BigImageViewer:1.8.1'
|
||||
implementation 'com.github.piasy:FrescoImageLoader:1.8.1'
|
||||
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.1'
|
||||
@@ -127,18 +123,10 @@ dependencies {
|
||||
//noinspection GradleDependency
|
||||
implementation "com.squareup.okhttp3:okhttp:4.12.0"
|
||||
|
||||
implementation "com.tbuonomo.andrui:viewpagerdotsindicator:4.1.2"
|
||||
|
||||
implementation "net.rdrei.android.dirchooser:library:3.2@aar"
|
||||
implementation "com.gu:option:1.3"
|
||||
|
||||
implementation "com.andrognito.patternlockview:patternlockview:1.0.0"
|
||||
//implementation "com.andrognito.pinlockview:pinlockview:2.1.0"
|
||||
|
||||
implementation "ru.noties.markwon:core:3.1.0"
|
||||
|
||||
implementation "org.jsoup:jsoup:1.14.3"
|
||||
|
||||
implementation "xyz.quaver:documentfilex:0.7.2"
|
||||
implementation "xyz.quaver:floatingsearchview:1.1.7"
|
||||
|
||||
|
||||
@@ -17,13 +17,11 @@
|
||||
package xyz.quaver.pupil.hitomi
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
import org.jsoup.Jsoup
|
||||
import java.net.URL
|
||||
import java.net.URLDecoder
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
import javax.net.ssl.HttpsURLConnection
|
||||
import kotlin.io.readText
|
||||
|
||||
//galleryblock.js
|
||||
fun fetchNozomi(area: String? = null, tag: String = "index", language: String = "all", start: Int = -1, count: Int = -1) : Pair<List<Int>, Int> {
|
||||
|
||||
@@ -45,7 +45,7 @@ fun IntBuffer.toSet(): Set<Int> {
|
||||
return result
|
||||
}
|
||||
|
||||
class HitomiHttpClient {
|
||||
object HitomiHttpClient {
|
||||
private val httpClient = HttpClient(OkHttp)
|
||||
|
||||
private var _tagIndexVersion: String? = null
|
||||
@@ -186,7 +186,7 @@ class HitomiHttpClient {
|
||||
|
||||
suspend fun getSuggestionsForQuery(query: SearchQuery.Tag): Result<List<Suggestion>> = runCatching {
|
||||
val field = query.namespace ?: "global"
|
||||
val key = Node.Key(field)
|
||||
val key = Node.Key(query.tag)
|
||||
val node = getNodeAtAddress(field, 0)
|
||||
val data = bSearch(field, key, node)
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ data class Node(
|
||||
val isLeaf: Boolean = subNodeAddresses.all { it == 0L }
|
||||
|
||||
fun locateKey(target: Key): Pair<Boolean, Int> {
|
||||
val index = keys.indexOfFirst { key -> key <= target }
|
||||
val index = keys.indexOfFirst { key -> target <= key }
|
||||
|
||||
if (index == -1) {
|
||||
return Pair(false, keys.size)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package xyz.quaver.pupil.ui.composable
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedContent
|
||||
import androidx.compose.animation.animateColorAsState
|
||||
import androidx.compose.animation.core.Spring
|
||||
@@ -9,6 +10,7 @@ import androidx.compose.foundation.gestures.animateScrollBy
|
||||
import androidx.compose.foundation.horizontalScroll
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.RowScope
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
@@ -69,7 +71,9 @@ import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import xyz.quaver.pupil.R
|
||||
import xyz.quaver.pupil.networking.HitomiHttpClient
|
||||
import xyz.quaver.pupil.networking.SearchQuery
|
||||
import xyz.quaver.pupil.networking.Suggestion
|
||||
import xyz.quaver.pupil.networking.validNamespace
|
||||
import xyz.quaver.pupil.ui.theme.Blue300
|
||||
import xyz.quaver.pupil.ui.theme.Blue600
|
||||
@@ -146,6 +150,45 @@ sealed interface EditableSearchQueryState {
|
||||
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun TagSuggestionList(
|
||||
state: EditableSearchQueryState.Tag
|
||||
) {
|
||||
var suggestionList: List<Suggestion>? by remember { mutableStateOf(null) }
|
||||
|
||||
var namespace by state.namespace
|
||||
var tag by state.tag
|
||||
var expanded by state.expanded
|
||||
|
||||
LaunchedEffect(namespace, tag) {
|
||||
suggestionList = null
|
||||
suggestionList = HitomiHttpClient.getSuggestionsForQuery(SearchQuery.Tag(namespace, tag))
|
||||
.getOrDefault(emptyList())
|
||||
.filterNot { it.tag == SearchQuery.Tag(namespace, tag) }
|
||||
}
|
||||
|
||||
val suggestionListSnapshot = suggestionList
|
||||
if (suggestionListSnapshot == null) {
|
||||
Text("Loading")
|
||||
} else if (suggestionListSnapshot.isNotEmpty()) {
|
||||
Column(
|
||||
modifier = Modifier.padding(8.dp),
|
||||
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||
) {
|
||||
suggestionListSnapshot.forEach { suggestion ->
|
||||
TagChip(
|
||||
tag = suggestion.tag,
|
||||
onClick = {
|
||||
namespace = it.namespace
|
||||
tag = it.tag
|
||||
expanded = false
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun EditableTagChip(
|
||||
state: EditableSearchQueryState.Tag,
|
||||
@@ -244,7 +287,7 @@ fun EditableTagChip(
|
||||
)
|
||||
}
|
||||
|
||||
var selection by remember { mutableStateOf(TextRange(tag.length)) }
|
||||
var selection by remember(tag) { mutableStateOf(TextRange(tag.length)) }
|
||||
var composition by remember { mutableStateOf<TextRange?>(null) }
|
||||
|
||||
val focusRequester = remember { FocusRequester() }
|
||||
@@ -311,6 +354,8 @@ fun EditableTagChip(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
TagSuggestionList(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,8 +29,6 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.core.net.toUri
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import net.rdrei.android.dirchooser.DirectoryChooserActivity
|
||||
import net.rdrei.android.dirchooser.DirectoryChooserConfig
|
||||
import xyz.quaver.io.FileX
|
||||
import xyz.quaver.io.util.toFile
|
||||
import xyz.quaver.pupil.R
|
||||
@@ -56,8 +54,7 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
||||
it.data?.data?.also { uri ->
|
||||
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
|
||||
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||
context.contentResolver.takePersistableUriPermission(uri, takeFlags)
|
||||
|
||||
if (kotlin.runCatching { FileX(context, uri).canWrite() }.getOrDefault(false)) {
|
||||
entries[null]?.locationAvailable?.text = uri.toFile(context)?.canonicalPath
|
||||
@@ -72,14 +69,14 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
||||
val downloadFolder = DownloadManager.getInstance(context).downloadFolder.canonicalPath
|
||||
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
|
||||
entries[key]!!.button.isChecked = true
|
||||
if (key == null) entries[key]!!.locationAvailable.text = downloadFolder
|
||||
if (key == null) entries[null]!!.locationAvailable.text = downloadFolder
|
||||
}
|
||||
}
|
||||
} else {
|
||||
val downloadFolder = DownloadManager.getInstance(context ?: return@registerForActivityResult).downloadFolder.canonicalPath
|
||||
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
|
||||
if (key == null)
|
||||
entries[key]!!.locationAvailable.text = downloadFolder
|
||||
entries[null]!!.locationAvailable.text = downloadFolder
|
||||
else {
|
||||
entries[null]!!.button.isChecked = false
|
||||
entries[key]!!.button.isChecked = true
|
||||
@@ -87,32 +84,6 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
||||
}
|
||||
}
|
||||
|
||||
private val requestDownloadFolderOldLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
|
||||
val context = context ?: return@registerForActivityResult
|
||||
val dialog = dialog ?: return@registerForActivityResult
|
||||
|
||||
if (it.resultCode == DirectoryChooserActivity.RESULT_CODE_DIR_SELECTED) {
|
||||
val directory = it.data?.getStringExtra(DirectoryChooserActivity.RESULT_SELECTED_DIR)!!
|
||||
|
||||
if (!File(directory).canWrite()) {
|
||||
Snackbar.make(
|
||||
dialog.window!!.decorView.rootView,
|
||||
R.string.settings_download_folder_not_writable,
|
||||
Snackbar.LENGTH_LONG
|
||||
).show()
|
||||
|
||||
val downloadFolder = DownloadManager.getInstance(context).downloadFolder.canonicalPath
|
||||
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
|
||||
entries[key]!!.button.isChecked = true
|
||||
if (key == null) entries[key]!!.locationAvailable.text = downloadFolder
|
||||
}
|
||||
else {
|
||||
entries[null]?.locationAvailable?.text = directory
|
||||
Preferences["download_folder"] = File(directory).toURI().toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initView() {
|
||||
val externalFilesDirs = ContextCompat.getExternalFilesDirs(requireContext(), null)
|
||||
|
||||
@@ -147,24 +118,11 @@ class DownloadLocationDialogFragment : DialogFragment() {
|
||||
}
|
||||
button.performClick()
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
}
|
||||
|
||||
requestDownloadFolderLauncher.launch(intent)
|
||||
} else { // Can't use SAF on old Androids!
|
||||
val config = DirectoryChooserConfig.builder()
|
||||
.newDirectoryName("Pupil")
|
||||
.allowNewDirectoryNameModification(true)
|
||||
.build()
|
||||
|
||||
val intent = Intent(context, DirectoryChooserActivity::class.java).apply {
|
||||
putExtra(DirectoryChooserActivity.EXTRA_CONFIG, config)
|
||||
}
|
||||
|
||||
requestDownloadFolderOldLauncher.launch(intent)
|
||||
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
|
||||
putExtra("android.content.extra.SHOW_ADVANCED", true)
|
||||
}
|
||||
|
||||
requestDownloadFolderLauncher.launch(intent)
|
||||
}
|
||||
entries[null] = this
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<merge
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:parentTag="androidx.cardview.widget.CardView">
|
||||
|
||||
<com.daimajia.swipe.SwipeLayout
|
||||
android:id="@+id/swipe_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:drag_edge="right"
|
||||
app:show_mode="pull_out">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/download"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="70dp"
|
||||
android:padding="8dp"
|
||||
android:gravity="center"
|
||||
android:background="@android:color/holo_blue_dark"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="@string/main_download"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/delete"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:minWidth="70dp"
|
||||
android:padding="8dp"
|
||||
android:gravity="center"
|
||||
android:background="@android:color/holo_red_dark"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="@string/main_delete"
|
||||
android:foreground="?android:attr/selectableItemBackground"
|
||||
android:focusable="true"
|
||||
android:clickable="true"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:orientation="vertical">
|
||||
|
||||
<androidx.core.widget.ContentLoadingProgressBar
|
||||
style="?android:attr/progressBarStyleHorizontal"
|
||||
android:id="@+id/progressbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="4dp"
|
||||
android:progress="50"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</com.daimajia.swipe.SwipeLayout>
|
||||
|
||||
</merge>
|
||||
@@ -1,32 +0,0 @@
|
||||
<?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/>.
|
||||
-->
|
||||
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end|center"
|
||||
android:layout_marginStart="@dimen/search_bar_search_input_left_margin"
|
||||
android:gravity="end|center"
|
||||
android:paddingBottom="4dp"
|
||||
android:paddingTop="4dp"
|
||||
android:textSize="@dimen/suggestion_body_text_size"
|
||||
tools:text="body"
|
||||
android:layout_marginLeft="@dimen/search_bar_search_input_left_margin" />
|
||||
Reference in New Issue
Block a user