6.6.3 - Alpha5 - APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑

This commit is contained in:
SuperMonster003
2025-05-21 20:05:39 +08:00
parent ad34b03013
commit 3d8e3e28eb
7 changed files with 152 additions and 127 deletions

View File

@@ -43,6 +43,7 @@
"已忽略更新记录及客户端模式连接地址记录支持清空操作", "已忽略更新记录及客户端模式连接地址记录支持清空操作",
"版本更新信息支持多语言显示 (与当前显示语言同步)", "版本更新信息支持多语言显示 (与当前显示语言同步)",
"使用异步加载方式一定程度提升文件管理器列表滑动流畅性", "使用异步加载方式一定程度提升文件管理器列表滑动流畅性",
"APK 文件类型信息及媒体文件类型信息优化对话框显示效率及信息展示逻辑",
"Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_" "Gradle 构建脚本提升版本自适应能力 _[`discussion #369`](http://discussions.autojs6.com/369)_"
], ],
"dependency": [ "dependency": [

View File

@@ -3,6 +3,10 @@ package org.autojs.autojs.extension
import android.view.View import android.view.View
import android.widget.TextView import android.widget.TextView
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.autojs.autojs.theme.ThemeColorHelper import org.autojs.autojs.theme.ThemeColorHelper
import org.autojs.autojs.util.ClipboardUtils import org.autojs.autojs.util.ClipboardUtils
import org.autojs.autojs.util.IntentUtils import org.autojs.autojs.util.IntentUtils
@@ -36,16 +40,23 @@ object MaterialDialogExtensions {
} }
} }
fun MaterialDialog.setCopyableTextIfAbsent(textView: TextView, f: () -> String?) { fun MaterialDialog.setCopyableTextIfAbsent(textView: TextView, textValue: String?) {
val textValue = f.invoke()
if (textView.text == context.getString(R.string.ellipsis_six)) { if (textView.text == context.getString(R.string.ellipsis_six)) {
textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown) textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown)
} }
this.makeTextCopyable(textView, textValue) this.makeTextCopyable(textView, textValue)
} }
fun MaterialDialog.setCopyableText(textView: TextView, f: () -> String?) { fun MaterialDialog.setCopyableTextIfAbsent(textView: TextView, scope: CoroutineScope, f: () -> String?) {
val textValue = f.invoke() scope.launch(Dispatchers.IO) {
val textValue = f.invoke()
withContext(Dispatchers.Main) {
setCopyableTextIfAbsent(textView, textValue)
}
}
}
fun MaterialDialog.setCopyableText(textView: TextView, textValue: String?) {
textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown) textView.text = textValue.takeUnless { it.isNullOrBlank() } ?: context.getString(R.string.text_unknown)
this.makeTextCopyable(textView, textValue) this.makeTextCopyable(textView, textValue)
} }

View File

@@ -109,7 +109,7 @@ object ColorInfoDialogManager {
private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) { private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
dialog.setCopyableText(this@bindWith) { text } dialog.setCopyableText(this@bindWith, text)
} }
} }

View File

@@ -2,6 +2,8 @@ package org.autojs.autojs.ui.main.scripts
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.content.pm.PackageManager.GET_META_DATA import android.content.pm.PackageManager.GET_META_DATA
import android.os.Build import android.os.Build
import android.view.LayoutInflater import android.view.LayoutInflater
@@ -14,7 +16,11 @@ import com.afollestad.materialdialogs.MaterialDialog
import com.android.apksig.ApkVerifier import com.android.apksig.ApkVerifier
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.selects.select
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.dongliu.apk.parser.ApkFile import net.dongliu.apk.parser.ApkFile
import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable import org.autojs.autojs.extension.MaterialDialogExtensions.makeSettingsLaunchable
@@ -38,6 +44,10 @@ object ApkInfoDialogManager {
fun showApkInfoDialog(context: Context, apkFile: File) { fun showApkInfoDialog(context: Context, apkFile: File) {
val binding = ApkFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context)) val binding = ApkFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context))
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
// zh-CN: 针对 Dialog 独立创建一个 Scope, 生命周期与 Dialog 绑定.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
val apkFilePath = apkFile.absolutePath val apkFilePath = apkFile.absolutePath
val packageManager = context.packageManager val packageManager = context.packageManager
@@ -63,101 +73,118 @@ object ApkInfoDialogManager {
.neutralColorRes(R.color.dialog_button_hint) .neutralColorRes(R.color.dialog_button_hint)
.onNegative { materialDialog, _ -> materialDialog.dismiss() } .onNegative { materialDialog, _ -> materialDialog.dismiss() }
.show() .show()
.apply {
CoroutineScope(Dispatchers.Main).launch { setOnDismissListener { scope.cancel() }
val packageInfo = withContext(Dispatchers.IO) { makeTextCopyable { it.titleView }
runCatching { packageManager.getPackageArchiveInfo(apkFilePath, GET_META_DATA) }.getOrNull()
} }
val applicationInfo = packageInfo?.applicationInfo
val packageName = packageInfo?.packageName scope.launch {
val versionName = packageInfo?.versionName val apkInfoDeferred = async(Dispatchers.IO) { getApkInfo(apkFile) }
val versionCode = packageInfo?.let { val packageInfoDeferred = async(Dispatchers.IO) { getPackageInfo(packageManager, apkFilePath) }
when {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> it.longVersionCode val firstPackageName: String? = select {
else -> @Suppress("DEPRECATION") it.versionCode.toLong() apkInfoDeferred.onAwait { it?.packageName }
packageInfoDeferred.onAwait { it?.packageName }
}
val packageName: String? = firstPackageName ?: when {
apkInfoDeferred.isCompleted -> packageInfoDeferred.await()?.packageName
else -> apkInfoDeferred.await()?.packageName
}
// @Hint by SuperMonster003 on Nov 27, 2024.
// ! Prioritize handling "installed version" to determine whether to display its content view.
// ! This is the only content view that needs to be considered before displaying the dialog.
// ! It is now safe to display the dialog immediately as all content views have placeholders.
// ! zh-CN:
// ! 优先处理 "已安装版本", 决定是否显示其内容视图.
// ! 这是唯一一个在显示对话框之前需要考虑的内容视图.
// ! 此时可立即安全显示对话框, 因所有内容视图均已完成占位.
val installedPackageName: String? = packageName?.also { pkg ->
AppUtils.getInstalledVersionInfo(pkg)?.let { versionInfo ->
binding.installedVersionParent.isVisible = true
dialog.setCopyableTextIfAbsent(
binding.installedVersionValue,
context.getString(R.string.text_full_version_info, versionInfo.versionName, versionInfo.versionCode),
)
} }
} }
val fileSize = withContext(Dispatchers.IO) { PFiles.getHumanReadableSize(apkFile.length()) } restoreEssentialViews(binding, context)
updateGuidelines(binding)
val signatureScheme = withContext(Dispatchers.IO) { getApkSignatureInfo(apkFile) } dialog.setCopyableTextIfAbsent(binding.packageNameValue, packageName)
dialog.setCopyableTextIfAbsent(binding.deviceSdkValue, "${Build.VERSION.SDK_INT}")
dialog.setCopyableTextIfAbsent(binding.fileSizeValue, this) { PFiles.getHumanReadableSize(apkFile.length()) }
dialog.setCopyableTextIfAbsent(binding.signatureSchemeValue, this) { getApkSignatureInfo(apkFile) }
withContext(Dispatchers.Main) { launch(Dispatchers.IO) {
// @Hint by SuperMonster003 on Nov 27, 2024. val apkInfo = apkInfoDeferred.await()
// ! Prioritize handling "installed version" to determine whether to display its content view.
// ! This is the only content view that needs to be considered before displaying the dialog. withContext(Dispatchers.Main) {
// ! It is now safe to display the dialog immediately as all content views have placeholders. dialog.setCopyableTextIfAbsent(binding.labelNameValue, apkInfo?.label)
// ! zh-CN: dialog.setCopyableTextIfAbsent(binding.minSdkValue, apkInfo?.minSdkVersion?.toString())
// ! 优先处理 "已安装版本", 决定是否显示其内容视图. dialog.setCopyableTextIfAbsent(binding.targetSdkValue, apkInfo?.targetSdkVersion?.toString())
// ! 这是唯一一个在显示对话框之前需要考虑的内容视图.
// ! 此时可立即安全显示对话框, 因所有内容视图均已完成占位. if (apkInfo != null) dialog.getActionButton(DialogAction.NEUTRAL).let { neutralButton ->
val installedPackageName: String? = packageName?.let { pkg -> neutralButton.isVisible = true
AppUtils.getInstalledVersionInfo(pkg)?.let { versionInfo -> neutralButton.text = "Manifest"
binding.installedVersionParent.isVisible = true neutralButton.setOnClickListener { DisplayManifestActivity.launch(context, apkInfo.manifestXml, apkInfo.usesPermissions) }
dialog.setCopyableTextIfAbsent(binding.installedVersionValue) { context.getString(R.string.text_full_version_info, versionInfo.versionName, versionInfo.versionCode) }
pkg /* returns as installedPackageName */
} }
} }
}
restoreEssentialViews(binding, context) launch(Dispatchers.IO) {
updateGuidelines(binding) val packageInfo = packageInfoDeferred.await()
val applicationInfo = packageInfo?.applicationInfo
when { val versionName = packageInfo?.versionName
versionName != null -> { val versionCode = packageInfo?.let {
binding.versionPlaceholderLabel.text = context.getString(R.string.text_version) when {
dialog.setCopyableTextIfAbsent(binding.versionPlaceholderValue) { context.getString(R.string.text_full_version_info, versionName, versionCode) } Build.VERSION.SDK_INT >= Build.VERSION_CODES.P -> it.longVersionCode
else -> @Suppress("DEPRECATION") it.versionCode.toLong()
} }
versionCode != null -> {
binding.versionPlaceholderLabel.text = context.getString(R.string.text_version_code)
dialog.setCopyableTextIfAbsent(binding.versionPlaceholderValue) { "$versionCode" }
}
else -> dialog.setCopyableTextIfAbsent(binding.versionPlaceholderValue) { null }
} }
withContext(Dispatchers.Main) {
when {
versionName != null -> {
binding.versionPlaceholderLabel.text = context.getString(R.string.text_version)
dialog.setCopyableTextIfAbsent(
binding.versionPlaceholderValue,
context.getString(R.string.text_full_version_info, versionName, versionCode),
)
}
versionCode != null -> {
binding.versionPlaceholderLabel.text = context.getString(R.string.text_version_code)
dialog.setCopyableTextIfAbsent(binding.versionPlaceholderValue, "$versionCode")
}
else -> dialog.setCopyableTextIfAbsent(binding.versionPlaceholderValue, null)
}
dialog.setCopyableTextIfAbsent(binding.packageNameValue) { packageName } dialog.setIcon(applicationInfo?.apply {
dialog.setCopyableTextIfAbsent(binding.deviceSdkValue) { "${Build.VERSION.SDK_INT}" } sourceDir = apkFilePath
dialog.setCopyableTextIfAbsent(binding.fileSizeValue) { fileSize } publicSourceDir = apkFilePath
dialog.setCopyableTextIfAbsent(binding.signatureSchemeValue) { signatureScheme } }?.loadIcon(packageManager) ?: AppCompatResources.getDrawable(context, R.drawable.ic_packaging))
dialog.makeSettingsLaunchable({ it.iconView }, installedPackageName)
dialog.setIcon(applicationInfo?.apply {
sourceDir = apkFilePath
publicSourceDir = apkFilePath
}?.loadIcon(packageManager) ?: AppCompatResources.getDrawable(context, R.drawable.ic_packaging))
dialog.makeSettingsLaunchable({ it.iconView }, installedPackageName)
dialog.makeTextCopyable { it.titleView }
val apkInfo = getApkInfo(apkFile)
dialog.setCopyableTextIfAbsent(binding.labelNameValue) { apkInfo?.label }
dialog.setCopyableTextIfAbsent(binding.packageNameValue) { apkInfo?.packageName }
dialog.setCopyableTextIfAbsent(binding.minSdkValue) { apkInfo?.minSdkVersion?.toString() }
dialog.setCopyableTextIfAbsent(binding.targetSdkValue) { apkInfo?.targetSdkVersion?.toString() }
if (apkInfo != null) dialog.getActionButton(DialogAction.NEUTRAL).let { neutralButton ->
neutralButton.isVisible = true
neutralButton.text = "Manifest"
neutralButton.setOnClickListener { DisplayManifestActivity.launch(context, apkInfo.manifestXml, apkInfo.usesPermissions) }
} }
} }
} }
} }
private suspend fun getApkInfo(apkFile: File): ApkInfo? = withContext(Dispatchers.IO) { private fun getApkInfo(apkFile: File): ApkInfo? = runCatching {
runCatching { ApkFile(apkFile).use { parser ->
ApkFile(apkFile).use { parser -> val meta = runCatching { parser.apkMeta }.getOrNull()
val meta = runCatching { parser.apkMeta }.getOrNull() val label = meta?.label
val label = meta?.label val packageName = meta?.packageName
val packageName = meta?.packageName val minSdkVersion = meta?.minSdkVersion?.toIntOrNull()
val minSdkVersion = meta?.minSdkVersion?.toIntOrNull() val targetSdkVersion = meta?.targetSdkVersion?.toIntOrNull()
val targetSdkVersion = meta?.targetSdkVersion?.toIntOrNull() val usesPermissions = meta?.usesPermissions ?: emptyList()
val usesPermissions = meta?.usesPermissions ?: emptyList() val manifestXml = parser.manifestXml
val manifestXml = parser.manifestXml ApkInfo(label, packageName, minSdkVersion, targetSdkVersion, usesPermissions, manifestXml)
ApkInfo(label, packageName, minSdkVersion, targetSdkVersion, usesPermissions, manifestXml) }
} }.getOrNull()
}.getOrNull()
} private fun getPackageInfo(packageManager: PackageManager, apkFilePath: String): PackageInfo? = runCatching {
packageManager.getPackageArchiveInfo(apkFilePath, GET_META_DATA)
}.getOrNull()
private fun restoreEssentialViews(binding: ApkFileInfoDialogListItemBinding, context: Context) { private fun restoreEssentialViews(binding: ApkFileInfoDialogListItemBinding, context: Context) {
listOf( listOf(

View File

@@ -100,7 +100,6 @@ abstract class BaseDisplayContentActivity : BaseActivity() {
// ! zh-CN: 事实上, 此处依然存疑. // ! zh-CN: 事实上, 此处依然存疑.
// ! Reference: https://stackoverflow.com/questions/3866499/two-directional-scroll-view // ! Reference: https://stackoverflow.com/questions/3866499/two-directional-scroll-view
// ! // !
super.onTouchEvent(event) or view.onTouchEvent(event) super.onTouchEvent(event) or view.onTouchEvent(event)
} }
else -> super.onTouchEvent(event) else -> super.onTouchEvent(event)

View File

@@ -11,8 +11,9 @@ import com.afollestad.materialdialogs.DialogAction
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable import org.autojs.autojs.extension.MaterialDialogExtensions.makeTextCopyable
@@ -35,6 +36,10 @@ object MediaInfoDialogManager {
fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) { fun showMediaInfoDialog(context: Context, explorerItem: ExplorerItem) {
val binding = MediaFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context)) val binding = MediaFileInfoDialogListItemBinding.inflate(LayoutInflater.from(context))
// Create an independent Scope for the Dialog, bind its lifecycle with the Dialog.
// zh-CN: 针对 Dialog 独立创建一个 Scope, 生命周期与 Dialog 绑定.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
val dialog = MaterialDialog.Builder(context) val dialog = MaterialDialog.Builder(context)
.title(explorerItem.name) .title(explorerItem.name)
.customView(binding.root, false) .customView(binding.root, false)
@@ -48,60 +53,42 @@ object MediaInfoDialogManager {
.neutralText(R.string.ellipsis_six) .neutralText(R.string.ellipsis_six)
.neutralColorRes(R.color.dialog_button_unavailable) .neutralColorRes(R.color.dialog_button_unavailable)
.show() .show()
.apply { setOnDismissListener { scope.cancel() } }
CoroutineScope(Dispatchers.Main).launch { scope.launch {
val mediaInfo = MediaInfo() val mediaInfo = MediaInfo()
val filePath = explorerItem.path val filePath = explorerItem.path
val deferredVideoFormat = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Format") } val videoFormatDeferred = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Format") }
val deferredAudioFormat = async(Dispatchers.IO) { mediaInfo(filePath, AUDIO, "Format") } val audioFormatDeferred = async(Dispatchers.IO) { mediaInfo(filePath, AUDIO, "Format") }
val deferredContainerFormat = async(Dispatchers.IO) { mediaInfo(filePath, GENERAL, "Format") } val containerFormatDeferred = async(Dispatchers.IO) { mediaInfo(filePath, GENERAL, "Format") }
val deferredMediaInfoTrimmed = async(Dispatchers.IO) { mediaInfo.getMediaInfoTrimmed(explorerItem.path) } val mediaInfoTrimmedDeferred = async(Dispatchers.IO) { mediaInfo.getMediaInfoTrimmed(explorerItem.path) }
launch(Dispatchers.IO) { launch(Dispatchers.IO) {
mediaInfo(filePath, GENERAL, "FileSize/String").let { mediaInfo(filePath, GENERAL, "FileSize/String").let { binding.fileSizeValue.bindWith(dialog, it) }
binding.fileSizeValue.bindWith(dialog, it)
}
}
launch(Dispatchers.IO) {
mediaInfo(filePath, GENERAL, "Duration/String").let { binding.durationValue.bindWith(dialog, it) } mediaInfo(filePath, GENERAL, "Duration/String").let { binding.durationValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, GENERAL, "Album").let { binding.albumValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, GENERAL, "Track").let { binding.trackNameValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, GENERAL, "Performer").let { binding.performerValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, AUDIO, "BitRate/String").let { binding.bitRateForAudioValue.bindWith(dialog, it) } mediaInfo(filePath, AUDIO, "BitRate/String").let { binding.bitRateForAudioValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, VIDEO, "BitRate/String").let { binding.bitRateForVideoValue.bindWith(dialog, it) } mediaInfo(filePath, VIDEO, "BitRate/String").let { binding.bitRateForVideoValue.bindWith(dialog, it) }
} mediaInfo(filePath, GENERAL, "Track").let { binding.trackNameValue.bindWith(dialog, it) }
launch(Dispatchers.IO) { mediaInfo(filePath, GENERAL, "Performer").let { binding.performerValue.bindWith(dialog, it) }
mediaInfo(filePath, GENERAL, "Album").let { binding.albumValue.bindWith(dialog, it) }
run {
val width = mediaInfo(filePath, VIDEO, "Width")
val height = mediaInfo(filePath, VIDEO, "Height")
binding.resolutionValue.bindWith(dialog, if (width.isNotEmpty() && height.isNotEmpty()) "$width × $height" else "")
}
mediaInfo(filePath, VIDEO, "DisplayAspectRatio/String").let { binding.aspectRatioValue.bindWith(dialog, it) } mediaInfo(filePath, VIDEO, "DisplayAspectRatio/String").let { binding.aspectRatioValue.bindWith(dialog, it) }
}
launch(Dispatchers.IO) {
mediaInfo(filePath, VIDEO, "FrameRate").let { binding.frameRateValue.bindWith(dialog, it) } mediaInfo(filePath, VIDEO, "FrameRate").let { binding.frameRateValue.bindWith(dialog, it) }
} }
launch(Dispatchers.IO) {
val deferredVideoWidth = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Width") }
val deferredVideoHeight = async(Dispatchers.IO) { mediaInfo(filePath, VIDEO, "Height") }
val (width, height) = awaitAll(deferredVideoWidth, deferredVideoHeight)
binding.resolutionValue.bindWith(dialog, if (width.isNotEmpty() && height.isNotEmpty()) "$width × $height" else "")
}
when { when {
deferredVideoFormat.await().isNotEmpty() -> { videoFormatDeferred.await().isNotEmpty() -> {
setViewsAsVideoPlaceholder(binding) setViewsAsVideoPlaceholder(binding)
dialog.setIcon(R.drawable.ic_movie) dialog.setIcon(R.drawable.ic_movie)
dialog.getActionButton(DialogAction.POSITIVE) dialog.getActionButton(DialogAction.POSITIVE)
setDialogPlayable(dialog, context, explorerItem) setDialogPlayable(dialog, context, explorerItem)
} }
deferredAudioFormat.await().isNotEmpty() -> { audioFormatDeferred.await().isNotEmpty() -> {
setViewsAsMediaPlaceholder(binding) setViewsAsMediaPlaceholder(binding)
dialog.setIcon(R.drawable.ic_voice_note) dialog.setIcon(R.drawable.ic_voice_note)
setDialogPlayable(dialog, context, explorerItem) setDialogPlayable(dialog, context, explorerItem)
@@ -126,7 +113,7 @@ object MediaInfoDialogManager {
dialog.makeTextCopyable { it.titleView } dialog.makeTextCopyable { it.titleView }
} }
when (val containerFormat = deferredContainerFormat.await()) { when (val containerFormat = containerFormatDeferred.await()) {
MEDIA_INFO_ERROR_OPENING_FILE -> { MEDIA_INFO_ERROR_OPENING_FILE -> {
dialog.setContent(MEDIA_INFO_ERROR_OPENING_FILE) dialog.setContent(MEDIA_INFO_ERROR_OPENING_FILE)
dialog.getActionButton(DialogAction.NEUTRAL).let { dialog.getActionButton(DialogAction.NEUTRAL).let {
@@ -136,12 +123,12 @@ object MediaInfoDialogManager {
} }
else -> { else -> {
containerFormat.let { binding.containerFormatValue.bindWith(dialog, it) } containerFormat.let { binding.containerFormatValue.bindWith(dialog, it) }
deferredAudioFormat.await().let { binding.audioFormatValue.bindWith(dialog, it) } audioFormatDeferred.await().let { binding.audioFormatValue.bindWith(dialog, it) }
deferredVideoFormat.await().let { binding.videoFormatValue.bindWith(dialog, it) } videoFormatDeferred.await().let { binding.videoFormatValue.bindWith(dialog, it) }
} }
} }
updateDialogNeutralButton(dialog, context, deferredMediaInfoTrimmed.await()) updateDialogNeutralButton(dialog, context, mediaInfoTrimmedDeferred.await())
} }
} }
@@ -255,7 +242,7 @@ object MediaInfoDialogManager {
private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) { private suspend fun TextView.bindWith(dialog: MaterialDialog, text: String) {
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
dialog.setCopyableText(this@bindWith) { text } dialog.setCopyableText(this@bindWith, text)
} }
} }

View File

@@ -1,5 +1,5 @@
#Wed May 21 13:21:19 CST 2025 #Wed May 21 19:59:17 CST 2025
BUILD_TIME=1747804879230 BUILD_TIME=1747828757164
COMPILE_SDK_VERSION=35 COMPILE_SDK_VERSION=35
IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_CMAKE_VERSION=3.22.1
IMAGE_QUANT_NDK_VERSION=26.1.10909125 IMAGE_QUANT_NDK_VERSION=26.1.10909125
@@ -19,6 +19,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13
RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3
TARGET_SDK_VERSION=35 TARGET_SDK_VERSION=35
TARGET_SDK_VERSION_INRT=29 TARGET_SDK_VERSION_INRT=29
VERSION_BUILD=3240 VERSION_BUILD=3241
VERSION_NAME=6.6.3 Alpha5 VERSION_NAME=6.6.3 Alpha5
VSCODE_EXT_REQUIRED_VERSION=1.0.8 VSCODE_EXT_REQUIRED_VERSION=1.0.8