Dependency update, tag suggestion

This commit is contained in:
tom5079
2024-03-04 19:22:22 -08:00
parent ab3e6466d5
commit 48752a323f
8 changed files with 58 additions and 176 deletions

View File

@@ -22,7 +22,7 @@ android {
compileSdk 34 compileSdk 34
targetSdkVersion 34 targetSdkVersion 34
versionCode 69 versionCode 69
versionName "5.3.10" versionName "6.0.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }
@@ -87,7 +87,7 @@ dependencies {
implementation 'androidx.compose.ui:ui' implementation 'androidx.compose.ui:ui'
implementation 'androidx.compose.ui:ui-tooling-preview' implementation 'androidx.compose.ui:ui-tooling-preview'
debugImplementation 'androidx.compose.ui:ui-tooling' 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' debugImplementation 'androidx.compose.ui:ui-test-manifest'
implementation 'androidx.compose.material:material-icons-extended' implementation 'androidx.compose.material:material-icons-extended'
implementation 'androidx.activity:activity-compose:1.8.2' 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-core:2.3.8"
implementation "io.ktor:ktor-client-okhttp: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 "com.google.android.material:material:1.11.0"
implementation platform('com.google.firebase:firebase-bom:32.7.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.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:BigImageViewer:1.8.1'
implementation 'com.github.piasy:FrescoImageLoader:1.8.1' implementation 'com.github.piasy:FrescoImageLoader:1.8.1'
implementation 'com.github.piasy:FrescoImageViewFactory:1.8.1' implementation 'com.github.piasy:FrescoImageViewFactory:1.8.1'
@@ -127,18 +123,10 @@ dependencies {
//noinspection GradleDependency //noinspection GradleDependency
implementation "com.squareup.okhttp3:okhttp:4.12.0" 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.patternlockview:patternlockview:1.0.0"
//implementation "com.andrognito.pinlockview:pinlockview:2.1.0"
implementation "ru.noties.markwon:core:3.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:documentfilex:0.7.2"
implementation "xyz.quaver:floatingsearchview:1.1.7" implementation "xyz.quaver:floatingsearchview:1.1.7"

View File

@@ -17,13 +17,11 @@
package xyz.quaver.pupil.hitomi package xyz.quaver.pupil.hitomi
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import org.jsoup.Jsoup
import java.net.URL import java.net.URL
import java.net.URLDecoder import java.net.URLDecoder
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
import javax.net.ssl.HttpsURLConnection import javax.net.ssl.HttpsURLConnection
import kotlin.io.readText
//galleryblock.js //galleryblock.js
fun fetchNozomi(area: String? = null, tag: String = "index", language: String = "all", start: Int = -1, count: Int = -1) : Pair<List<Int>, Int> { fun fetchNozomi(area: String? = null, tag: String = "index", language: String = "all", start: Int = -1, count: Int = -1) : Pair<List<Int>, Int> {

View File

@@ -45,7 +45,7 @@ fun IntBuffer.toSet(): Set<Int> {
return result return result
} }
class HitomiHttpClient { object HitomiHttpClient {
private val httpClient = HttpClient(OkHttp) private val httpClient = HttpClient(OkHttp)
private var _tagIndexVersion: String? = null private var _tagIndexVersion: String? = null
@@ -186,7 +186,7 @@ class HitomiHttpClient {
suspend fun getSuggestionsForQuery(query: SearchQuery.Tag): Result<List<Suggestion>> = runCatching { suspend fun getSuggestionsForQuery(query: SearchQuery.Tag): Result<List<Suggestion>> = runCatching {
val field = query.namespace ?: "global" val field = query.namespace ?: "global"
val key = Node.Key(field) val key = Node.Key(query.tag)
val node = getNodeAtAddress(field, 0) val node = getNodeAtAddress(field, 0)
val data = bSearch(field, key, node) val data = bSearch(field, key, node)

View File

@@ -95,7 +95,7 @@ data class Node(
val isLeaf: Boolean = subNodeAddresses.all { it == 0L } val isLeaf: Boolean = subNodeAddresses.all { it == 0L }
fun locateKey(target: Key): Pair<Boolean, Int> { fun locateKey(target: Key): Pair<Boolean, Int> {
val index = keys.indexOfFirst { key -> key <= target } val index = keys.indexOfFirst { key -> target <= key }
if (index == -1) { if (index == -1) {
return Pair(false, keys.size) return Pair(false, keys.size)

View File

@@ -1,5 +1,6 @@
package xyz.quaver.pupil.ui.composable package xyz.quaver.pupil.ui.composable
import android.util.Log
import androidx.compose.animation.AnimatedContent import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.animateColorAsState import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.core.Spring 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.horizontalScroll
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@@ -69,7 +71,9 @@ import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
import xyz.quaver.pupil.networking.HitomiHttpClient
import xyz.quaver.pupil.networking.SearchQuery import xyz.quaver.pupil.networking.SearchQuery
import xyz.quaver.pupil.networking.Suggestion
import xyz.quaver.pupil.networking.validNamespace import xyz.quaver.pupil.networking.validNamespace
import xyz.quaver.pupil.ui.theme.Blue300 import xyz.quaver.pupil.ui.theme.Blue300
import xyz.quaver.pupil.ui.theme.Blue600 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 @Composable
fun EditableTagChip( fun EditableTagChip(
state: EditableSearchQueryState.Tag, 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) } var composition by remember { mutableStateOf<TextRange?>(null) }
val focusRequester = remember { FocusRequester() } val focusRequester = remember { FocusRequester() }
@@ -311,6 +354,8 @@ fun EditableTagChip(
} }
) )
} }
TagSuggestionList(state)
} }
} }
} }

View File

@@ -29,8 +29,6 @@ import androidx.core.content.ContextCompat
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import com.google.android.material.snackbar.Snackbar 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.FileX
import xyz.quaver.io.util.toFile import xyz.quaver.io.util.toFile
import xyz.quaver.pupil.R import xyz.quaver.pupil.R
@@ -56,7 +54,6 @@ class DownloadLocationDialogFragment : DialogFragment() {
it.data?.data?.also { uri -> it.data?.data?.also { uri ->
val takeFlags: Int = Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION 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)) { if (kotlin.runCatching { FileX(context, uri).canWrite() }.getOrDefault(false)) {
@@ -72,14 +69,14 @@ class DownloadLocationDialogFragment : DialogFragment() {
val downloadFolder = DownloadManager.getInstance(context).downloadFolder.canonicalPath val downloadFolder = DownloadManager.getInstance(context).downloadFolder.canonicalPath
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder } val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
entries[key]!!.button.isChecked = true entries[key]!!.button.isChecked = true
if (key == null) entries[key]!!.locationAvailable.text = downloadFolder if (key == null) entries[null]!!.locationAvailable.text = downloadFolder
} }
} }
} else { } else {
val downloadFolder = DownloadManager.getInstance(context ?: return@registerForActivityResult).downloadFolder.canonicalPath val downloadFolder = DownloadManager.getInstance(context ?: return@registerForActivityResult).downloadFolder.canonicalPath
val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder } val key = entries.keys.firstOrNull { it?.canonicalPath == downloadFolder }
if (key == null) if (key == null)
entries[key]!!.locationAvailable.text = downloadFolder entries[null]!!.locationAvailable.text = downloadFolder
else { else {
entries[null]!!.button.isChecked = false entries[null]!!.button.isChecked = false
entries[key]!!.button.isChecked = true 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() { private fun initView() {
val externalFilesDirs = ContextCompat.getExternalFilesDirs(requireContext(), null) val externalFilesDirs = ContextCompat.getExternalFilesDirs(requireContext(), null)
@@ -147,24 +118,11 @@ class DownloadLocationDialogFragment : DialogFragment() {
} }
button.performClick() button.performClick()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply { val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE).apply {
putExtra("android.content.extra.SHOW_ADVANCED", true) putExtra("android.content.extra.SHOW_ADVANCED", true)
} }
requestDownloadFolderLauncher.launch(intent) 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)
}
} }
entries[null] = this entries[null] = this
} }

View File

@@ -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>

View File

@@ -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" />