Просмотр исходного кода

fix:背景图片选择器用GetContent以支持浏览选项 (#1630)

fansan 4 месяцев назад
Родитель
Сommit
366d547bcd

+ 4 - 9
app/src/main/java/io/legado/app/ui/book/read/ReadBookRouteScreen.kt

@@ -6,7 +6,6 @@ import android.view.View
 import android.widget.FrameLayout
 import android.widget.ImageView
 import androidx.activity.compose.rememberLauncherForActivityResult
-import androidx.activity.result.PickVisualMediaRequest
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.compose.foundation.layout.Box
 import androidx.compose.foundation.layout.fillMaxSize
@@ -166,14 +165,14 @@ fun ReadBookRouteScreen(
     }
 
     val readStyleImagePicker = rememberLauncherForActivityResult(
-        ActivityResultContracts.PickVisualMedia()
+        ActivityResultContracts.GetContent()
     ) { uri ->
         uri?.let { viewModel.onIntent(ReadBookIntent.ReadStyleImageSelected(it)) }
     }
 
     var pendingReadStyleImageIsNight by remember { mutableStateOf(false) }
     val readStyleImagePickerForMode = rememberLauncherForActivityResult(
-        ActivityResultContracts.PickVisualMedia()
+        ActivityResultContracts.GetContent()
     ) { uri ->
         uri?.let {
             viewModel.onIntent(ReadBookIntent.ReadStyleImageSelectedForMode(it, pendingReadStyleImageIsNight))
@@ -368,15 +367,11 @@ fun ReadBookRouteScreen(
                                 booksDirPicker.launch(null)
                             }
                             is ReadBookEffect.OpenReadStyleImagePicker -> {
-                                readStyleImagePicker.launch(
-                                    PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
-                                )
+                                readStyleImagePicker.launch("image/*")
                             }
                             is ReadBookEffect.OpenReadStyleImagePickerForMode -> {
                                 pendingReadStyleImageIsNight = effect.isNight
-                                readStyleImagePickerForMode.launch(
-                                    PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
-                                )
+                                readStyleImagePickerForMode.launch("image/*")
                             }
                             is ReadBookEffect.OpenReadStyleImport -> {
                                 readStyleImportPicker.launch(

+ 45 - 32
app/src/main/java/io/legado/app/ui/book/read/sheet/HighlightRuleEditSheet.kt

@@ -4,7 +4,6 @@ import android.content.Intent
 import android.net.Uri
 import android.provider.OpenableColumns
 import androidx.activity.compose.rememberLauncherForActivityResult
-import androidx.activity.result.PickVisualMediaRequest
 import androidx.activity.result.contract.ActivityResultContracts
 import androidx.compose.foundation.Canvas
 import androidx.compose.foundation.layout.Arrangement
@@ -44,6 +43,7 @@ import androidx.compose.ui.unit.sp
 import androidx.core.net.toUri
 import androidx.lifecycle.compose.collectAsStateWithLifecycle
 import io.legado.app.R
+import io.legado.app.constant.AppLog
 import io.legado.app.data.entities.HighlightRule
 import io.legado.app.data.repository.ReadSettingsRepository
 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.TinySwitchSettingItem
 import io.legado.app.ui.widget.components.text.AppText
+import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
 import splitties.init.appCtx
+import io.legado.app.utils.toastOnUi
 import java.io.File
 
 @Composable
@@ -77,6 +80,7 @@ fun HighlightRuleEditSheet(
     val isNew = rule == null
     val initial = remember(show, rule) { rule ?: HighlightRule() }
     val context = LocalContext.current
+    val coroutineScope = rememberCoroutineScope()
 
     // Rule info state
     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.
     val imagePicker = rememberLauncherForActivityResult(
-        ActivityResultContracts.PickVisualMedia()
+        ActivityResultContracts.GetContent()
     ) { uri: Uri? ->
         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),
                     description = bgImage.ifBlank { null }?.let { File(it).name },
                     onClick = {
-                        imagePicker.launch(
-                            PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)
-                        )
+                        imagePicker.launch("image/*")
                     },
                 )
             }