|
@@ -4,7 +4,6 @@ import android.content.Intent
|
|
|
import android.net.Uri
|
|
import android.net.Uri
|
|
|
import android.provider.OpenableColumns
|
|
import android.provider.OpenableColumns
|
|
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
import androidx.activity.compose.rememberLauncherForActivityResult
|
|
|
-import androidx.activity.result.PickVisualMediaRequest
|
|
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
|
import androidx.compose.foundation.Canvas
|
|
import androidx.compose.foundation.Canvas
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
@@ -44,6 +43,7 @@ import androidx.compose.ui.unit.sp
|
|
|
import androidx.core.net.toUri
|
|
import androidx.core.net.toUri
|
|
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
|
|
import io.legado.app.R
|
|
import io.legado.app.R
|
|
|
|
|
+import io.legado.app.constant.AppLog
|
|
|
import io.legado.app.data.entities.HighlightRule
|
|
import io.legado.app.data.entities.HighlightRule
|
|
|
import io.legado.app.data.repository.ReadSettingsRepository
|
|
import io.legado.app.data.repository.ReadSettingsRepository
|
|
|
import io.legado.app.data.repository.configNames
|
|
import io.legado.app.data.repository.configNames
|
|
@@ -63,8 +63,11 @@ import io.legado.app.ui.widget.components.settingItem.TinyDropdownSettingItem
|
|
|
import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
|
|
import io.legado.app.ui.widget.components.settingItem.TinySliderSettingItem
|
|
|
import io.legado.app.ui.widget.components.settingItem.TinySwitchSettingItem
|
|
import io.legado.app.ui.widget.components.settingItem.TinySwitchSettingItem
|
|
|
import io.legado.app.ui.widget.components.text.AppText
|
|
import io.legado.app.ui.widget.components.text.AppText
|
|
|
|
|
+import kotlinx.coroutines.Dispatchers
|
|
|
import kotlinx.coroutines.launch
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
+import kotlinx.coroutines.withContext
|
|
|
import splitties.init.appCtx
|
|
import splitties.init.appCtx
|
|
|
|
|
+import io.legado.app.utils.toastOnUi
|
|
|
import java.io.File
|
|
import java.io.File
|
|
|
|
|
|
|
|
@Composable
|
|
@Composable
|
|
@@ -77,6 +80,7 @@ fun HighlightRuleEditSheet(
|
|
|
val isNew = rule == null
|
|
val isNew = rule == null
|
|
|
val initial = remember(show, rule) { rule ?: HighlightRule() }
|
|
val initial = remember(show, rule) { rule ?: HighlightRule() }
|
|
|
val context = LocalContext.current
|
|
val context = LocalContext.current
|
|
|
|
|
+ val coroutineScope = rememberCoroutineScope()
|
|
|
|
|
|
|
|
// Rule info state
|
|
// Rule info state
|
|
|
var pattern by remember(show, rule) { mutableStateOf(initial.pattern) }
|
|
var pattern by remember(show, rule) { mutableStateOf(initial.pattern) }
|
|
@@ -139,38 +143,49 @@ fun HighlightRuleEditSheet(
|
|
|
|
|
|
|
|
// System photo picker, with the contract's built-in fallback on older devices.
|
|
// System photo picker, with the contract's built-in fallback on older devices.
|
|
|
val imagePicker = rememberLauncherForActivityResult(
|
|
val imagePicker = rememberLauncherForActivityResult(
|
|
|
- ActivityResultContracts.PickVisualMedia()
|
|
|
|
|
|
|
+ ActivityResultContracts.GetContent()
|
|
|
) { uri: Uri? ->
|
|
) { uri: Uri? ->
|
|
|
if (uri != null) {
|
|
if (uri != null) {
|
|
|
- val dir = File(appCtx.filesDir, "bg_images")
|
|
|
|
|
- if (!dir.exists()) dir.mkdirs()
|
|
|
|
|
- val displayName = context.contentResolver.query(
|
|
|
|
|
- uri,
|
|
|
|
|
- arrayOf(OpenableColumns.DISPLAY_NAME),
|
|
|
|
|
- null,
|
|
|
|
|
- null,
|
|
|
|
|
- null,
|
|
|
|
|
- )?.use { cursor ->
|
|
|
|
|
- if (cursor.moveToFirst()) {
|
|
|
|
|
- cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
|
|
|
|
- .takeIf { it >= 0 }
|
|
|
|
|
- ?.let(cursor::getString)
|
|
|
|
|
- } else {
|
|
|
|
|
- null
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- val suffix = when {
|
|
|
|
|
- displayName?.endsWith(".9.png", ignoreCase = true) == true -> ".9.png"
|
|
|
|
|
- displayName?.substringAfterLast('.', "").isNullOrBlank() -> ".img"
|
|
|
|
|
- else -> ".${displayName.substringAfterLast('.')}"
|
|
|
|
|
- }
|
|
|
|
|
- val target = File(dir, "bg_${System.currentTimeMillis()}$suffix")
|
|
|
|
|
- context.contentResolver.openInputStream(uri)?.use { input ->
|
|
|
|
|
- target.outputStream().use { output ->
|
|
|
|
|
- input.copyTo(output)
|
|
|
|
|
|
|
+ coroutineScope.launch {
|
|
|
|
|
+ runCatching {
|
|
|
|
|
+ withContext(Dispatchers.IO) {
|
|
|
|
|
+ val dir = File(appCtx.filesDir, "bg_images")
|
|
|
|
|
+ if (!dir.exists()) dir.mkdirs()
|
|
|
|
|
+ val displayName = context.contentResolver.query(
|
|
|
|
|
+ uri,
|
|
|
|
|
+ arrayOf(OpenableColumns.DISPLAY_NAME),
|
|
|
|
|
+ null,
|
|
|
|
|
+ null,
|
|
|
|
|
+ null,
|
|
|
|
|
+ )?.use { cursor ->
|
|
|
|
|
+ if (cursor.moveToFirst()) {
|
|
|
|
|
+ cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
|
|
|
|
|
+ .takeIf { it >= 0 }
|
|
|
|
|
+ ?.let(cursor::getString)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ null
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ val suffix = when {
|
|
|
|
|
+ displayName?.endsWith(".9.png", ignoreCase = true) == true -> ".9.png"
|
|
|
|
|
+ displayName?.substringAfterLast('.', "").isNullOrBlank() -> ".img"
|
|
|
|
|
+ else -> ".${displayName.substringAfterLast('.')}"
|
|
|
|
|
+ }
|
|
|
|
|
+ val target = File(dir, "bg_${System.currentTimeMillis()}$suffix")
|
|
|
|
|
+ context.contentResolver.openInputStream(uri)?.use { input ->
|
|
|
|
|
+ target.outputStream().use { output ->
|
|
|
|
|
+ input.copyTo(output)
|
|
|
|
|
+ }
|
|
|
|
|
+ } ?: throw java.io.FileNotFoundException("Open input stream failed")
|
|
|
|
|
+ target.absolutePath
|
|
|
|
|
+ }
|
|
|
|
|
+ }.onSuccess { path ->
|
|
|
|
|
+ bgImage = path
|
|
|
|
|
+ }.onFailure { throwable ->
|
|
|
|
|
+ context.toastOnUi(R.string.error)
|
|
|
|
|
+ AppLog.put("选择高亮背景图失败", throwable)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- bgImage = target.absolutePath
|
|
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -385,9 +400,7 @@ fun HighlightRuleEditSheet(
|
|
|
title = stringResource(R.string.highlight_bg_image),
|
|
title = stringResource(R.string.highlight_bg_image),
|
|
|
description = bgImage.ifBlank { null }?.let { File(it).name },
|
|
description = bgImage.ifBlank { null }?.let { File(it).name },
|
|
|
onClick = {
|
|
onClick = {
|
|
|
- imagePicker.launch(
|
|
|
|
|
- PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ imagePicker.launch("image/*")
|
|
|
},
|
|
},
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|