This commit is contained in:
Horis
2025-12-22 14:13:45 +08:00
parent a310c6d510
commit 46a70d6d3a
18 changed files with 123 additions and 39 deletions
@@ -10,13 +10,12 @@ import io.legado.app.data.entities.BookGroup
import io.legado.app.databinding.DialogBookGroupEditBinding
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.utils.FileUtils
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.externalFiles
import io.legado.app.utils.gone
import io.legado.app.utils.inputStream
import io.legado.app.utils.launch
import io.legado.app.utils.readUri
import io.legado.app.utils.setLayout
import io.legado.app.utils.toastOnUi
@@ -37,7 +36,7 @@ class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
private val binding by viewBinding(DialogBookGroupEditBinding::bind)
private val viewModel by viewModels<GroupViewModel>()
private var bookGroup: BookGroup? = null
private val selectImage = registerForActivityResult(SelectImageContract()) {
private val selectImage = registerForActivityResult(HandleFileContract()) {
it.uri ?: return@registerForActivityResult
readUri(it.uri) { fileDoc, inputStream ->
try {
@@ -82,7 +81,9 @@ class GroupEditDialog() : BaseDialogFragment(R.layout.dialog_book_group_edit) {
}
binding.run {
ivCover.onClick {
selectImage.launch()
selectImage.launch {
mode = HandleFileContract.IMAGE
}
}
btnCancel.onClick {
dismiss()
@@ -18,12 +18,11 @@ import io.legado.app.help.book.isImage
import io.legado.app.help.book.isLocal
import io.legado.app.help.book.removeType
import io.legado.app.ui.book.changecover.ChangeCoverDialog
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.utils.FileUtils
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.externalFiles
import io.legado.app.utils.inputStream
import io.legado.app.utils.launch
import io.legado.app.utils.readUri
import io.legado.app.utils.setOnApplyWindowInsetsListenerCompat
import io.legado.app.utils.showDialogFragment
@@ -37,7 +36,7 @@ class BookInfoEditActivity :
VMBaseActivity<ActivityBookInfoEditBinding, BookInfoEditViewModel>(),
ChangeCoverDialog.CallBack {
private val selectCover = registerForActivityResult(SelectImageContract()) {
private val selectCover = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
coverChangeTo(uri)
}
@@ -87,7 +86,9 @@ class BookInfoEditActivity :
}
}
tvSelectCover.setOnClickListener {
selectCover.launch()
selectCover.launch {
mode = HandleFileContract.IMAGE
}
}
tvRefreshCover.setOnClickListener {
viewModel.book?.customCoverUrl = tieCoverUrl.text?.toString()
@@ -2,7 +2,6 @@ package io.legado.app.ui.book.read.config
import android.annotation.SuppressLint
import android.content.DialogInterface
import android.graphics.Color
import android.graphics.PorterDuff
import android.net.Uri
import android.os.Bundle
@@ -12,6 +11,7 @@ import android.view.ViewGroup
import android.view.WindowManager
import android.widget.SeekBar
import androidx.appcompat.widget.TooltipCompat
import androidx.core.graphics.toColorInt
import androidx.core.view.isGone
import com.jaredrummler.android.colorpicker.ColorPickerDialog
import io.legado.app.R
@@ -41,7 +41,6 @@ import io.legado.app.utils.FileDoc
import io.legado.app.utils.FileUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.compress.ZipUtils
import io.legado.app.utils.createFileIfNotExist
import io.legado.app.utils.createFileReplace
@@ -52,7 +51,6 @@ import io.legado.app.utils.externalFiles
import io.legado.app.utils.find
import io.legado.app.utils.getFile
import io.legado.app.utils.inputStream
import io.legado.app.utils.launch
import io.legado.app.utils.longToast
import io.legado.app.utils.openInputStream
import io.legado.app.utils.openOutputStream
@@ -81,7 +79,7 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
private var primaryTextColor = 0
private var secondaryTextColor = 0
private val importFormNet = "网络导入"
private val selectBgImage = registerForActivityResult(SelectImageContract()) {
private val selectBgImage = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
setBgFromUri(uri)
}
@@ -154,7 +152,9 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
ivBg.setImageResource(R.drawable.ic_image)
ivBg.setColorFilter(primaryTextColor, PorterDuff.Mode.SRC_IN)
root.setOnClickListener {
selectBgImage.launch()
selectBgImage.launch {
mode = HandleFileContract.IMAGE
}
}
}
}
@@ -218,8 +218,8 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) {
}
binding.tvBgColor.setOnClickListener {
val bgColor =
if (curBgType() == 0) Color.parseColor(curBgStr())
else Color.parseColor("#015A86")
if (curBgType() == 0) curBgStr().toColorInt()
else "#015A86".toColorInt()
ColorPickerDialog.newBuilder()
.setColor(bgColor)
.setShowAlphaSlider(false)
@@ -13,7 +13,19 @@ import io.legado.app.lib.prefs.SwitchPreference
import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.BookCover
import io.legado.app.utils.*
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.utils.FileUtils
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.externalFiles
import io.legado.app.utils.getPrefBoolean
import io.legado.app.utils.getPrefString
import io.legado.app.utils.inputStream
import io.legado.app.utils.putPrefString
import io.legado.app.utils.readUri
import io.legado.app.utils.removePref
import io.legado.app.utils.setEdgeEffectColor
import io.legado.app.utils.showDialogFragment
import io.legado.app.utils.toastOnUi
import splitties.init.appCtx
import java.io.FileOutputStream
@@ -22,7 +34,7 @@ class CoverConfigFragment : PreferenceFragment(),
private val requestCodeCover = 111
private val requestCodeCoverDark = 112
private val selectImage = registerForActivityResult(SelectImageContract()) {
private val selectImage = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
when (it.requestCode) {
requestCodeCover -> setCoverFromUri(PreferKey.defaultCover, uri)
@@ -64,16 +76,19 @@ class CoverConfigFragment : PreferenceFragment(),
PreferKey.defaultCoverDark -> {
upPreferenceSummary(key, getPrefString(key))
}
PreferKey.coverShowName -> {
findPreference<SwitchPreference>(PreferKey.coverShowAuthor)
?.isEnabled = getPrefBoolean(key)
BookCover.upDefaultCover()
}
PreferKey.coverShowNameN -> {
findPreference<SwitchPreference>(PreferKey.coverShowAuthorN)
?.isEnabled = getPrefBoolean(key)
BookCover.upDefaultCover()
}
PreferKey.coverShowAuthor,
PreferKey.coverShowAuthorN -> {
BookCover.upDefaultCover()
@@ -87,7 +102,10 @@ class CoverConfigFragment : PreferenceFragment(),
"coverRule" -> showDialogFragment(CoverRuleConfigDialog())
PreferKey.defaultCover ->
if (getPrefString(preference.key).isNullOrEmpty()) {
selectImage.launch(requestCodeCover)
selectImage.launch {
requestCode = requestCodeCover
mode = HandleFileContract.IMAGE
}
} else {
context?.selector(
items = arrayListOf(
@@ -99,13 +117,20 @@ class CoverConfigFragment : PreferenceFragment(),
removePref(preference.key)
BookCover.upDefaultCover()
} else {
selectImage.launch(requestCodeCover)
selectImage.launch {
requestCode = requestCodeCover
mode = HandleFileContract.IMAGE
}
}
}
}
PreferKey.defaultCoverDark ->
if (getPrefString(preference.key).isNullOrEmpty()) {
selectImage.launch(requestCodeCoverDark)
selectImage.launch {
requestCode = requestCodeCoverDark
mode = HandleFileContract.IMAGE
}
} else {
context?.selector(
items = arrayListOf(
@@ -117,7 +142,10 @@ class CoverConfigFragment : PreferenceFragment(),
removePref(preference.key)
BookCover.upDefaultCover()
} else {
selectImage.launch(requestCodeCoverDark)
selectImage.launch {
requestCode = requestCodeCoverDark
mode = HandleFileContract.IMAGE
}
}
}
}
@@ -134,6 +162,7 @@ class CoverConfigFragment : PreferenceFragment(),
} else {
value
}
else -> preference.summary = value
}
}
@@ -27,12 +27,12 @@ import io.legado.app.lib.dialogs.selector
import io.legado.app.lib.prefs.ColorPreference
import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.ui.widget.number.NumberPickerDialog
import io.legado.app.ui.widget.seekbar.SeekBarChangeListener
import io.legado.app.utils.ColorUtils
import io.legado.app.utils.FileUtils
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.applyTint
import io.legado.app.utils.externalFiles
import io.legado.app.utils.getPrefInt
@@ -57,7 +57,7 @@ class ThemeConfigFragment : PreferenceFragment(),
private val requestCodeBgLight = 121
private val requestCodeBgDark = 122
private val selectImage = registerForActivityResult(SelectImageContract()) {
private val selectImage = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
when (it.requestCode) {
requestCodeBgLight -> setBgFromUri(uri, PreferKey.bgImage) {
@@ -253,9 +253,15 @@ class ThemeConfigFragment : PreferenceFragment(),
1 -> {
if (isNight) {
selectImage.launch(requestCodeBgDark)
selectImage.launch {
requestCode = requestCodeBgDark
mode = HandleFileContract.IMAGE
}
} else {
selectImage.launch(requestCodeBgLight)
selectImage.launch {
requestCode = requestCodeBgLight
mode = HandleFileContract.IMAGE
}
}
}
@@ -14,9 +14,9 @@ import io.legado.app.lib.prefs.SwitchPreference
import io.legado.app.lib.prefs.fragment.PreferenceFragment
import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.BookCover
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.utils.FileUtils
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.externalFiles
import io.legado.app.utils.getPrefString
import io.legado.app.utils.inputStream
@@ -33,7 +33,7 @@ class WelcomeConfigFragment : PreferenceFragment(),
private val requestWelcomeImage = 221
private val requestWelcomeImageDark = 222
private val selectImage = registerForActivityResult(SelectImageContract()) {
private val selectImage = registerForActivityResult(HandleFileContract()) {
it.uri?.let { uri ->
when (it.requestCode) {
requestWelcomeImage -> setCoverFromUri(PreferKey.welcomeImage, uri)
@@ -110,7 +110,10 @@ class WelcomeConfigFragment : PreferenceFragment(),
when (preference.key) {
PreferKey.welcomeImage ->
if (getPrefString(preference.key).isNullOrEmpty()) {
selectImage.launch(requestWelcomeImage)
selectImage.launch {
requestCode = requestWelcomeImage
mode = HandleFileContract.IMAGE
}
} else {
context?.selector(
items = arrayListOf(
@@ -130,14 +133,20 @@ class WelcomeConfigFragment : PreferenceFragment(),
}
BookCover.upDefaultCover()
} else {
selectImage.launch(requestWelcomeImage)
selectImage.launch {
requestCode = requestWelcomeImage
mode = HandleFileContract.IMAGE
}
}
}
}
PreferKey.welcomeImageDark ->
if (getPrefString(preference.key).isNullOrEmpty()) {
selectImage.launch(requestWelcomeImageDark)
selectImage.launch {
requestCode = requestWelcomeImageDark
mode = HandleFileContract.IMAGE
}
} else {
context?.selector(
items = arrayListOf(
@@ -157,7 +166,10 @@ class WelcomeConfigFragment : PreferenceFragment(),
}
BookCover.upDefaultCover()
} else {
selectImage.launch(requestWelcomeImageDark)
selectImage.launch {
requestCode = requestWelcomeImageDark
mode = HandleFileContract.IMAGE
}
}
}
}
@@ -7,6 +7,7 @@ import android.os.Environment
import android.webkit.MimeTypeMap
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.net.toUri
import androidx.lifecycle.lifecycleScope
import io.legado.app.R
import io.legado.app.base.VMBaseActivity
@@ -18,6 +19,7 @@ import io.legado.app.lib.dialogs.SelectItem
import io.legado.app.lib.dialogs.alert
import io.legado.app.lib.permission.Permissions
import io.legado.app.lib.permission.PermissionsCompat
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.checkWrite
import io.legado.app.utils.externalFiles
import io.legado.app.utils.getJsonArray
@@ -59,6 +61,12 @@ class HandleFileActivity :
} ?: finish()
}
private val selectImage = registerForActivityResult(SelectImageContract()) {
it.uri?.let { uri ->
onResult(Intent().setData(uri))
} ?: finish()
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
mode = intent.getIntExtra("mode", 0)
viewModel.errorLiveData.observe(this) {
@@ -76,6 +84,7 @@ class HandleFileActivity :
addAll(getDirActions())
}
HandleFileContract.IMAGE -> getImageActions()
else -> arrayListOf()
}
intent.getJsonArray<SelectItem<Int>>("otherActions")?.let {
@@ -85,6 +94,7 @@ class HandleFileActivity :
when (mode) {
HandleFileContract.EXPORT -> return@let getString(R.string.export)
HandleFileContract.DIR -> return@let getString(R.string.select_folder)
HandleFileContract.IMAGE -> return@let getString(R.string.select_image)
else -> return@let getString(R.string.select_file)
}
}
@@ -116,6 +126,10 @@ class HandleFileActivity :
}
}
HandleFileContract.IMAGE -> {
selectImage.launch()
}
10 -> checkPermissions {
@Suppress("DEPRECATION")
lifecycleScope.launchWhenResumed {
@@ -139,7 +153,7 @@ class HandleFileActivity :
111 -> getFileData()?.let {
viewModel.upload(it.first, it.second, it.third) { url ->
val uri = Uri.parse(url)
val uri = url.toUri()
setResult(RESULT_OK, Intent().setData(uri))
finish()
}
@@ -152,7 +166,7 @@ class HandleFileActivity :
else -> {
val path = item.title
val uri = if (path.isContentScheme()) {
Uri.parse(path)
path.toUri()
} else {
Uri.fromFile(File(path))
}
@@ -250,6 +264,14 @@ class HandleFileActivity :
)
}
private fun getImageActions(): ArrayList<SelectItem<Int>> {
return arrayListOf(
SelectItem(getString(R.string.sys_image_picker), HandleFileContract.IMAGE)
).apply {
addAll(getFileActions())
}
}
private fun checkPermissions(success: (() -> Unit)? = null) {
PermissionsCompat.Builder()
.addPermissions(*Permissions.Group.STORAGE)
@@ -24,6 +24,9 @@ class HandleFileContract :
input?.let {
handleFileParam.apply(input)
}
if (handleFileParam.mode == IMAGE) {
handleFileParam.allowExtensions = arrayOf("jpg", "png", "bmp", "webp")
}
handleFileParam.let {
requestCode = it.requestCode
intent.putExtra("mode", it.mode)
@@ -57,6 +60,7 @@ class HandleFileContract :
const val FILE = 1
const val DIR_SYS = 2
const val EXPORT = 3
const val IMAGE = 4
}
@Suppress("ArrayInDataClass")
@@ -9,9 +9,8 @@ import com.google.zxing.Result
import io.legado.app.R
import io.legado.app.base.BaseActivity
import io.legado.app.databinding.ActivityQrcodeCaptureBinding
import io.legado.app.ui.file.HandleFileContract
import io.legado.app.utils.QRCodeUtils
import io.legado.app.utils.SelectImageContract
import io.legado.app.utils.launch
import io.legado.app.utils.readBytes
import io.legado.app.utils.viewbindingdelegate.viewBinding
@@ -19,7 +18,7 @@ class QrCodeActivity : BaseActivity<ActivityQrcodeCaptureBinding>(), ScanResultC
override val binding by viewBinding(ActivityQrcodeCaptureBinding::inflate)
private val selectQrImage = registerForActivityResult(SelectImageContract()) {
private val selectQrImage = registerForActivityResult(HandleFileContract()) {
it.uri?.readBytes(this)?.let { bytes ->
val bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.size)
onScanResultCallback(QRCodeUtils.parseCodeResult(bitmap))
@@ -41,7 +40,9 @@ class QrCodeActivity : BaseActivity<ActivityQrcodeCaptureBinding>(), ScanResultC
override fun onCompatOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_choose_from_gallery -> selectQrImage.launch()
R.id.action_choose_from_gallery -> selectQrImage.launch {
mode = HandleFileContract.IMAGE
}
}
return super.onCompatOptionsItemSelected(item)
}
@@ -62,7 +62,7 @@ fun AppCompatActivity.readUri(
}
} catch (e: Exception) {
e.printOnDebug()
AppLog.put("读取Uri出错\n$e", e, true)
AppLog.put("读取Uri出错\n$uri\n$e", e, true)
if (e is SecurityException) {
throw e
}
@@ -99,7 +99,7 @@ fun Fragment.readUri(uri: Uri?, success: (fileDoc: FileDoc, inputStream: InputSt
}
} catch (e: Exception) {
e.printOnDebug()
AppLog.put("读取Uri出错\n$e", e, true)
AppLog.put("读取Uri出错\n$uri\n$e", e, true)
}
}
@@ -1224,4 +1224,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
@@ -1227,4 +1227,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
@@ -1227,4 +1227,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
+1
View File
@@ -1218,4 +1218,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
@@ -1222,4 +1222,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
@@ -1223,4 +1223,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
+1
View File
@@ -1229,4 +1229,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>
+1
View File
@@ -1231,4 +1231,5 @@
<string name="sure_cache_book">是否确认开始缓存?</string>
<string name="auto_check_new_backup_t">自动检查新备份</string>
<string name="auto_check_new_backup_s">打开软件时检查是否有新备份,有新备份时提示是否更新</string>
<string name="sys_image_picker">系统图片选择器</string>
</resources>