Compare commits

...
8 Commits
Author SHA1 Message Date
FooIbar 7e1b3abcf6 Prepare for release 1.11.7
Releases / build (push) Has been cancelled
2024-07-10 22:12:56 +08:00
FooIbar 97bb65aa35 Fix search bar title flickering 2024-07-10 22:11:46 +08:00
FooIbar 98c1a377ca Fix main thread disk IO 2024-07-10 20:25:52 +08:00
FooIbar 2d2ce3281e Fix Path -> Uri conversion for paths contain '%'
This reverts commit ab2e4a8e2d.
2024-07-10 19:44:13 +08:00
renovate[bot] a28d3ba840 Update dependency org.jsoup:jsoup to v1.18.1 2024-07-10 08:41:55 +00:00
FooIbar ab2e4a8e2d Fix Path -> Uri conversion
No need to do it for '?' as that's not allowed in filename.
2024-07-10 12:59:29 +08:00
FooIbar 67ddba87b5 Fix workflow config
[no ci]
2024-07-09 22:29:28 +08:00
FooIbar 8164847fcb Prepare for next iteration 2024-07-09 22:03:40 +08:00
10 changed files with 49 additions and 40 deletions

No files matched your search

+2
View File
@@ -5,6 +5,8 @@ on:
- cron: '30 0 * * 0'
workflow_dispatch:
push:
branches:
- '**'
paths:
- 'benchmark/**'
- '.github/workflows/baseline-profile.yml'
+10 -1
View File
@@ -1,6 +1,15 @@
# 变更日志
## [1.11.6] - 2024-06-24
## [1.11.7] - 2024-07-10
### Bug 修复
* 无法下载标题包含 # 或 % 的画廊
* 下载页数较多的画廊时应用无响应
* 退出搜索栏时文本闪烁
## [1.11.6] - 2024-07-09 [YANKED]
### 改进
+2 -2
View File
@@ -71,8 +71,8 @@ android {
applicationId = "moe.tarsin.ehviewer"
minSdk = 26
targetSdk = 35
versionCode = 180057
versionName = "1.11.6"
versionCode = 180058
versionName = "1.11.7"
// versionNameSuffix = "-SNAPSHOT"
resourceConfigurations.addAll(
listOf(
@@ -76,13 +76,11 @@ fun SearchBarInputField(
singleLine = true,
visualTransformation = VisualTransformation.None,
interactionSource = interactionSource,
label = label,
placeholder = placeholder,
leadingIcon = leadingIcon?.let { leading -> { Box(Modifier.offset(x = SearchBarIconOffsetX)) { leading() } } },
trailingIcon = trailingIcon?.let { trailing -> { Box(Modifier.offset(x = -SearchBarIconOffsetX)) { trailing() } } },
shape = SearchBarDefaults.inputFieldShape,
colors = colors,
contentPadding = TextFieldDefaults.contentPaddingWithLabel(),
container = {},
)
},
@@ -540,16 +540,16 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
private fun doLaunchDownloadJob(index: Int, force: Boolean, orgImg: Boolean = false) {
val state = mPageStateArray[index]
if (!force) {
if (state == STATE_FINISHED) return
if (index in mSpiderDen) return updatePageState(index, STATE_FINISHED)
}
if (!force && state == STATE_FINISHED) return
val currentJob = mFetcherJobMap[index]
val skipHath = force && !orgImg && currentJob?.isActive == true
if (force) currentJob?.cancel(CancellationException(FORCE_RETRY))
if (currentJob?.isActive != true) {
mFetcherJobMap[index] = launch {
runCatching {
if (!force && index in mSpiderDen) {
return@runCatching updatePageState(index, STATE_FINISHED)
}
delayLock.withLock {
delay(mDownloadDelay - lastRequestTime.elapsedNow())
lastRequestTime = TimeSource.Monotonic.markNow()
@@ -546,8 +546,8 @@ fun GalleryListScreen(lub: ListUrlBuilder, navigator: DestinationsNavigator) = c
fabHidden = it
},
title = suitableTitle,
searchFieldState = searchFieldState,
searchFieldHint = searchBarHint,
searchFieldState = searchFieldState,
suggestionProvider = {
GalleryDetailUrlParser.parse(it, false)?.run {
GalleryDetailUrlSuggestion(gid, token)
@@ -100,9 +100,9 @@ fun SearchBarScreen(
onApplySearch: (String) -> Unit,
expanded: Boolean,
onExpandedChange: (Boolean) -> Unit,
title: String? = null,
title: String?,
searchFieldHint: String,
searchFieldState: TextFieldState = rememberTextFieldState(),
searchFieldHint: String? = null,
suggestionProvider: SuggestionProvider? = null,
tagNamespace: Boolean = false,
searchBarOffsetY: () -> Int = { 0 },
@@ -226,14 +226,10 @@ fun SearchBarScreen(
expanded = expanded,
onExpandedChange = onExpandedChange,
modifier = Modifier.widthIn(max = maxWidth - SearchBarHorizontalPadding * 2),
label = title.ifNotNullThen {
Text(title!!, overflow = TextOverflow.Ellipsis, maxLines = 1)
}.takeUnless {
placeholder = {
val contentActive by activeState.state
expanded || contentActive || searchFieldState.text.isNotEmpty()
},
placeholder = searchFieldHint.ifNotNullThen {
Text(searchFieldHint!!, overflow = TextOverflow.Ellipsis, maxLines = 1)
val text = title.takeUnless { expanded || contentActive } ?: searchFieldHint
Text(text, overflow = TextOverflow.Ellipsis, maxLines = 1)
},
leadingIcon = {
if (expanded) {
@@ -103,14 +103,14 @@ class AndroidFileSystem(context: Context) : FileSystem() {
}
}
val uri = dir.toUri()
var documentId = DocumentsContract.getDocumentId(uri)
if (uri.isCifsDocument()) {
documentId += '/'
}
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, documentId)
return runCatching {
val uri = dir.toUri()
var documentId = DocumentsContract.getDocumentId(uri)
if (uri.isCifsDocument()) {
documentId += '/'
}
val childrenUri = DocumentsContract.buildChildDocumentsUriUsingTree(uri, documentId)
contentResolver.query(childrenUri, arrayOf(Document.COLUMN_DISPLAY_NAME), null, null, null)?.use { c ->
List(c.count) {
c.moveToNext()
@@ -126,15 +126,15 @@ class AndroidFileSystem(context: Context) : FileSystem() {
return physicalFileSystem.metadataOrNull(path)
}
val uri = path.toUri()
val isMediaUri = uri.authority == MediaStore.AUTHORITY
val projection = if (isMediaUri) {
arrayOf(MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.DATE_MODIFIED)
} else {
arrayOf(Document.COLUMN_MIME_TYPE, Document.COLUMN_LAST_MODIFIED)
}
return runCatching {
val uri = path.toUri()
val isMediaUri = uri.authority == MediaStore.AUTHORITY
val projection = if (isMediaUri) {
arrayOf(MediaStore.MediaColumns.MIME_TYPE, MediaStore.MediaColumns.DATE_MODIFIED)
} else {
arrayOf(Document.COLUMN_MIME_TYPE, Document.COLUMN_LAST_MODIFIED)
}
contentResolver.query(uri, projection, null, null, null)?.use { c ->
if (!c.moveToNext()) return null
+9 -5
View File
@@ -38,14 +38,18 @@ fun Path.toUri(): Uri {
}
val uri = str.replaceFirst("content:/", "content://").toUri()
val paths = uri.pathSegments
return if (paths.size > 3 && paths[0] == "tree") {
val path = requireNotNull(uri.encodedPath) { "Invalid path: $str" }
val paths = path.split('/').dropWhile { it.isEmpty() }
return if (paths.size > 4 && paths[0] == "tree") {
uri.buildUpon().apply {
path(null)
repeat(3) { i ->
appendPath(paths[i])
appendEncodedPath(paths[i])
}
appendPath(paths.subList(3, paths.size).joinToString("/").replaceFirst(":/", ":"))
val root = Uri.decode(paths[3])
val prefix = if (root.endsWith(':')) root else "$root/"
val suffix = uri.encodedFragment?.let { "#$it" }.orEmpty()
appendPath(paths.subList(4, paths.size).joinToString("/", prefix, suffix))
}.build()
} else {
uri
@@ -53,7 +57,7 @@ fun Path.toUri(): Uri {
}
fun Uri.toOkioPath() = if (scheme == ContentResolver.SCHEME_FILE) {
path!!
requireNotNull(path) { "Invalid URI: $this" }
} else {
toString()
}.toPath()
+1 -1
View File
@@ -93,7 +93,7 @@ desugar = "com.android.tools:desugar_jdk_libs_nio:2.0.4"
diff = "io.github.petertrr:kotlin-multiplatform-diff:0.7.0"
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
jsoup = "org.jsoup:jsoup:1.17.2"
jsoup = "org.jsoup:jsoup:1.18.1"
kotlinx-coroutines-android = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-android", version.ref = "kotlinx-coroutines" }
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinx-datetime" }