Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e1b3abcf6 | ||
|
|
97bb65aa35 | ||
|
|
98c1a377ca | ||
|
|
2d2ce3281e | ||
|
|
a28d3ba840 | ||
|
|
ab2e4a8e2d | ||
|
|
67ddba87b5 | ||
|
|
8164847fcb |
No files matched your search
@@ -5,6 +5,8 @@ on:
|
||||
- cron: '30 0 * * 0'
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
paths:
|
||||
- 'benchmark/**'
|
||||
- '.github/workflows/baseline-profile.yml'
|
||||
|
||||
+10
-1
@@ -1,6 +1,15 @@
|
||||
# 变更日志
|
||||
|
||||
## [1.11.6] - 2024-06-24
|
||||
## [1.11.7] - 2024-07-10
|
||||
|
||||
### Bug 修复
|
||||
|
||||
* 无法下载标题包含 # 或 % 的画廊
|
||||
* 下载页数较多的画廊时应用无响应
|
||||
* 退出搜索栏时文本闪烁
|
||||
|
||||
|
||||
## [1.11.6] - 2024-07-09 [YANKED]
|
||||
|
||||
### 改进
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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()
|
||||
@@ -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" }
|
||||
|
||||
Reference in new issue
Block a user