diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/center/InstalledPluginRepository.kt b/app/src/main/java/org/autojs/autojs/core/plugin/center/InstalledPluginRepository.kt index e9c1616f..489ae061 100644 --- a/app/src/main/java/org/autojs/autojs/core/plugin/center/InstalledPluginRepository.kt +++ b/app/src/main/java/org/autojs/autojs/core/plugin/center/InstalledPluginRepository.kt @@ -1,6 +1,7 @@ package org.autojs.autojs.core.plugin.center import android.content.Context +import android.content.pm.ApplicationInfo import android.graphics.drawable.Drawable import androidx.core.content.pm.PackageInfoCompat import kotlinx.coroutines.Dispatchers @@ -14,6 +15,9 @@ import java.io.File * Local installed plugin discovery (based on existing PaddleOcrPluginHost.discover). * * zh-CN: 本地已安装插件发现 (基于现有的 PaddleOcrPluginHost.discover). + * + * Modified by JetBrains AI Assistant (GPT-5.2-Codex (xhigh)) as of Feb 13, 2026. + * Modified by SuperMonster003 as of Feb 13, 2026. */ class InstalledPluginRepository { @@ -29,6 +33,8 @@ class InstalledPluginRepository { val lastUpdateTime: Long?, val icon: Drawable?, val pluginInfo: PluginInfo?, + val bindError: Throwable?, + val isStopped: Boolean, ) suspend fun discoverInstalled(context: Context): List = withContext(Dispatchers.IO) { @@ -41,6 +47,7 @@ class InstalledPluginRepository { val appInfo = runCatching { pm.getApplicationInfo(packageName, 0) }.getOrNull() val appLabel = appInfo?.loadLabel(pm)?.toString() val icon = appInfo?.loadIcon(pm) + val isStopped = appInfo != null && (appInfo.flags and ApplicationInfo.FLAG_STOPPED) != 0 val pkgInfo = runCatching { pm.getPackageInfo(packageName, 0) }.getOrNull() val versionName = pkgInfo?.versionName ?: d.pluginInfo?.versionName ?: context.getString(R.string.text_unknown) @@ -70,6 +77,8 @@ class InstalledPluginRepository { lastUpdateTime = lastUpdateTime, icon = icon, pluginInfo = d.pluginInfo, + bindError = d.error, + isStopped = isStopped, ) } } diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterFragment.kt b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterFragment.kt index 18853b42..5a652466 100644 --- a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterFragment.kt +++ b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterFragment.kt @@ -14,10 +14,15 @@ import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL import androidx.recyclerview.widget.LinearLayoutManager import com.afollestad.materialdialogs.MaterialDialog +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Job import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch +import org.autojs.autojs.core.plugin.ocr.PaddleOcrPluginHost +import org.autojs.autojs.util.ClipboardUtils +import org.autojs.autojs.util.IntentUtils.startSafely +import org.autojs.autojs.util.ViewUtils import org.autojs.autojs.util.ViewUtils.excludePaddingClippableViewFromBottomNavigationBar import org.autojs.autojs6.R import org.autojs.autojs6.databinding.FragmentPluginCenterBinding @@ -62,8 +67,75 @@ class PluginCenterFragment : Fragment(R.layout.fragment_plugin_center) { adapter = PluginCenterItemAdapter(object : PluginCenterItemAdapter.Listener { override fun onToggleEnable(item: PluginCenterItem, enabled: Boolean) { - vm.setEnabled(contextRef, item.packageName, enabled) - item.isEnabled = enabled + if (!enabled) { + vm.setEnabled(contextRef, item.packageName, false) + item.isEnabled = false + return + } + + vm.setEnabled(contextRef, item.packageName, true) + item.isEnabled = true + + viewLifecycleOwner.lifecycleScope.launch { + val error = runCatching { + PaddleOcrPluginHost.probe(contextRef, item.packageName) + }.exceptionOrNull() + if (error != null && error !is CancellationException) { + if (isAdded) { + val pm = contextRef.packageManager + val launchIntent = pm.getLaunchIntentForPackage(item.packageName) + val wakeIntent = PluginWakeManager.buildWakeIntent(contextRef, item.packageName) + + val errorBody = error.message ?: error.toString() + val message = listOf( + contextRef.getString(R.string.text_exception_info) + contextRef.getString(R.string.symbol_colon_with_blank), + errorBody, + contextRef.getString(R.string.text_hint) + contextRef.getString(R.string.symbol_colon_with_blank), + getString(R.string.hint_try_clicking_the_activate_button_to_activate_the_plugin) + ).joinToString("\n\n") + + MaterialDialog.Builder(contextRef) + .title(R.string.error_failed_to_enable_the_plugin) + .content(message) + .neutralText(R.string.dialog_button_copy) + .neutralColorRes(R.color.dialog_button_hint) + .onNeutral { d, _ -> + ClipboardUtils.setClip(contextRef, errorBody) + ViewUtils.showSnack(d.view, R.string.text_already_copied_to_clip, false) + } + .negativeText(R.string.dialog_button_dismiss) + .negativeColorRes(R.color.dialog_button_default) + .onNegative { d, _ -> d.dismiss() } + .apply positive@{ + positiveText(R.string.dialog_button_activate) + + val openIntent = wakeIntent ?: launchIntent ?: run { + positiveColorRes(R.color.dialog_button_unavailable) + onPositive { d, _ -> + ViewUtils.showSnack(d.view, R.string.text_unavailable, false) + } + return@positive + } + + positiveColorRes(R.color.dialog_button_attraction) + onPositive { d, _ -> + val started = openIntent.startSafely(contextRef, true) + d.dismiss() + if (started) { + ViewUtils.showToast(contextRef, getString(R.string.text_activated_successfully), true) + tryEnableAfterWake(item) + } + } + } + .cancelable(false) + .autoDismiss(false) + .show() + } + vm.setEnabled(contextRef, item.packageName, false) + item.isEnabled = false + adapter.notifyDataSetChanged() + } + } } override fun onUninstall(item: PluginCenterItem) { @@ -292,6 +364,29 @@ class PluginCenterFragment : Fragment(R.layout.fragment_plugin_center) { } } + private fun tryEnableAfterWake(item: PluginCenterItem) { + viewLifecycleOwner.lifecycleScope.launch { + val delays = longArrayOf(300L, 800L, 1500L) + for (delayMs in delays) { + delay(delayMs) + val error = runCatching { + PaddleOcrPluginHost.probe(contextRef, item.packageName) + }.exceptionOrNull() + if (error == null) { + if (isAdded && _binding != null) { + vm.setEnabled(contextRef, item.packageName, true) + item.isEnabled = true + adapter.notifyDataSetChanged() + } + return@launch + } + if (error is CancellationException) { + return@launch + } + } + } + } + override fun onStart() { super.onStart() pkgReceiver ?: run registerPackageReceiver@{ @@ -324,6 +419,7 @@ class PluginCenterFragment : Fragment(R.layout.fragment_plugin_center) { // Package uninstallation (pre-update phase) does not record "Recently uninstalled" when replacing. // zh-CN: 替换卸载 (更新前阶段) 不记录 "最近卸载". if (!replacing) { + PluginWakeManager.clearAutoWakeAttempt(packageName) PluginRecentStore.setLastUninstalled(packageName) vm.load(context, forceRefreshIndex = false) return diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterViewModel.kt b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterViewModel.kt index 24e6da78..61d05e55 100644 --- a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterViewModel.kt +++ b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginCenterViewModel.kt @@ -32,6 +32,7 @@ import org.autojs.autojs6.R * * Created by JetBrains AI Assistant (GPT-5.2) on Nov 26, 2025. * Modified by SuperMonster003 as of Jan 17, 2026. + * Modified by JetBrains AI Assistant (GPT-5.2-Codex (xhigh)) as of Feb 13, 2026. */ class PluginCenterViewModel : ViewModel() { @@ -92,6 +93,15 @@ class PluginCenterViewModel : ViewModel() { return@launch } + installed.forEach { local -> + if (local.bindError != null) { + enableStore.setEnabled(context, local.packageName, false) + } + if (local.isStopped) { + PluginWakeManager.tryAutoWakeIfNeeded(context, local.packageName) + } + } + // Render list using "local only". // zh-CN: 使用 "仅本地" 渲染列表. val onlyLocalItems = installed.mapNotNull { local -> @@ -217,4 +227,4 @@ class PluginCenterViewModel : ViewModel() { private const val TAG = "PluginCenterViewModel" } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginWakeManager.kt b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginWakeManager.kt new file mode 100644 index 00000000..97a92df5 --- /dev/null +++ b/app/src/main/java/org/autojs/autojs/core/plugin/center/PluginWakeManager.kt @@ -0,0 +1,65 @@ +package org.autojs.autojs.core.plugin.center + +import android.content.ComponentName +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import androidx.core.content.edit +import org.autojs.autojs.app.GlobalAppContext +import org.autojs.autojs.util.IntentUtils.startSafely + +/** + * Created by JetBrains AI Assistant (GPT-5.2-Codex (xhigh)) on Feb 13, 2026. + */ +object PluginWakeManager { + + private const val SP = "plugin_center_wake" + private const val ACTION_OCR_WAKE = "org.autojs.plugin.PADDLE_OCR.WAKE" + private const val WAKE_ACTIVITY_META = "org.autojs.plugin.WAKE_ACTIVITY" + + private val storeContext by lazy { GlobalAppContext.get() } + + fun tryAutoWakeIfNeeded(context: Context, packageName: String): Boolean { + if (isAutoWakeAttempted(packageName)) return false + val intent = buildWakeIntent(context, packageName) ?: return false + val started = intent.startSafely(context, true) + markAutoWakeAttempted(packageName) + return started + } + + fun buildWakeIntent(context: Context, packageName: String): Intent? { + val pm = context.packageManager + val appInfo = runCatching { pm.getApplicationInfo(packageName, PackageManager.GET_META_DATA) }.getOrNull() + val metaWakeActivity = appInfo?.metaData?.getString(WAKE_ACTIVITY_META) + val metaComponent = metaWakeActivity?.let { className -> + val fullName = if (className.startsWith(".")) packageName + className else className + ComponentName(packageName, fullName) + } + val wakeComponent = metaComponent ?: run { + val implicitIntent = Intent(ACTION_OCR_WAKE).setPackage(packageName) + val info = pm.queryIntentActivities(implicitIntent, 0).firstOrNull() + info?.activityInfo?.let { ComponentName(it.packageName, it.name) } + } + return when { + wakeComponent != null -> Intent().setComponent(wakeComponent) + else -> Intent(ACTION_OCR_WAKE).setPackage(packageName).takeIf { it.resolveActivity(pm) != null } + } + } + + private fun isAutoWakeAttempted(packageName: String): Boolean { + val sp = storeContext.getSharedPreferences(SP, Context.MODE_PRIVATE) + return sp.getBoolean(key(packageName), false) + } + + private fun markAutoWakeAttempted(packageName: String) { + val sp = storeContext.getSharedPreferences(SP, Context.MODE_PRIVATE) + sp.edit { putBoolean(key(packageName), true) } + } + + fun clearAutoWakeAttempt(packageName: String) { + val sp = storeContext.getSharedPreferences(SP, Context.MODE_PRIVATE) + sp.edit { remove(key(packageName)) } + } + + private fun key(packageName: String) = "key_\$_auto_wake_attempted_\$_$packageName" +} diff --git a/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt b/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt index d288d087..ff7f5a15 100644 --- a/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt +++ b/app/src/main/java/org/autojs/autojs/core/plugin/ocr/PaddleOcrPluginHost.kt @@ -4,6 +4,7 @@ import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.ServiceConnection +import android.content.pm.ApplicationInfo import android.content.pm.PackageManager import android.content.pm.ServiceInfo import android.graphics.Bitmap @@ -28,6 +29,9 @@ import org.autojs.plugin.paddle.ocr.api.PluginInfo import java.io.File import java.io.FileOutputStream +/** + * Modified by JetBrains AI Assistant (GPT-5.2-Codex (xhigh)) as of Feb 13, 2026. + */ object PaddleOcrPluginHost { private const val TAG = "PaddleOcrPluginHost" @@ -37,29 +41,36 @@ object PaddleOcrPluginHost { private const val DEFAULT_BIND_TIMEOUT_MS = 60_000L private const val DEFAULT_CALL_TIMEOUT_MS = 60_000L + private val externalServiceFlag = runCatching { ServiceInfo::class.java.getField("FLAG_EXTERNAL_SERVICE").getInt(null) }.getOrNull() ?: 0 + private val bindExternalServiceFlag = runCatching { Context::class.java.getField("BIND_EXTERNAL_SERVICE").getInt(null) }.getOrNull() ?: 0 + data class Discovered( val serviceInfo: ServiceInfo, val pluginInfo: PluginInfo?, + val error: Throwable?, ) suspend fun discover(context: Context): List { - val pm = context.packageManager - val resolveList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - pm.queryIntentServices(Intent(ACTION_OCR), PackageManager.ResolveInfoFlags.of(0)) - } else { - pm.queryIntentServices(Intent(ACTION_OCR), 0) - } - val services = resolveList.mapNotNull { it.serviceInfo } + val services = queryOcrServices(context) Log.i(TAG, "discover: services=${services.size}") return services.map { svc -> Log.i(TAG, "discover: ${svc.packageName}/${svc.name}") - val info = runCatching { withService(context, svc, DEFAULT_BIND_TIMEOUT_MS) { it.getInfo() } } - .onFailure { e -> Log.w(TAG, "getInfo failed: ${e.message}") } - .getOrNull() - Discovered(svc, info) + val result = runCatching { withService(context, svc, DEFAULT_BIND_TIMEOUT_MS) { it.getInfo() } } + val info = result.getOrNull() + val error = result.exceptionOrNull() + if (error != null) { + Log.w(TAG, "getInfo failed: ${error.message}") + } + Discovered(svc, info, error) } } + suspend fun probe(context: Context, packageName: String): PluginInfo { + val serviceInfo = queryOcrServices(context, packageName).firstOrNull() + ?: error("No OCR service found for package: $packageName") + return withService(context, serviceInfo, DEFAULT_BIND_TIMEOUT_MS) { it.getInfo() } + } + suspend fun recognizeText( context: Context, target: Discovered, @@ -141,6 +152,40 @@ object PaddleOcrPluginHost { return ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY) } + private fun queryOcrServices(context: Context, packageName: String? = null): List { + val pm = context.packageManager + val intent = Intent(ACTION_OCR).apply { + if (!packageName.isNullOrBlank()) { + setPackage(packageName) + } + } + val resolveList = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { + pm.queryIntentServices(intent, PackageManager.ResolveInfoFlags.of(0)) + } else { + pm.queryIntentServices(intent, 0) + } + return resolveList.mapNotNull { it.serviceInfo } + } + + private fun buildBindFlags(serviceInfo: ServiceInfo): Int { + var flags = Context.BIND_AUTO_CREATE + if (externalServiceFlag != 0 && bindExternalServiceFlag != 0 && (serviceInfo.flags and externalServiceFlag) != 0) { + flags = flags or bindExternalServiceFlag + } + return flags + } + + private fun buildBindFailureMessage(context: Context, serviceInfo: ServiceInfo, cn: ComponentName, reason: String? = null): String { + val pm = context.packageManager + val perm = serviceInfo.permission + val hasPerm = perm.isNullOrBlank() || pm.checkPermission(perm, context.packageName) == PackageManager.PERMISSION_GRANTED + val appInfo = serviceInfo.applicationInfo + val appStopped = (appInfo.flags and ApplicationInfo.FLAG_STOPPED) != 0 + val isExternal = externalServiceFlag != 0 && (serviceInfo.flags and externalServiceFlag) != 0 + val reasonText = reason?.let { " | reason=$it" } ?: "" + return "bindService failed: $cn. exported=${serviceInfo.exported} enabled=${serviceInfo.enabled} appEnabled=${appInfo.enabled} stopped=$appStopped perm=$perm hasPerm=$hasPerm external=$isExternal flags=0x${Integer.toHexString(serviceInfo.flags)}$reasonText" + } + private suspend fun withService( context: Context, serviceInfo: ServiceInfo, @@ -180,9 +225,10 @@ object PaddleOcrPluginHost { } } - val ok = try { + val bindFlags = buildBindFlags(serviceInfo) + var ok = try { Log.i(TAG, "bindService: $cn") - appCtx.bindService(intent, conn, Context.BIND_AUTO_CREATE) + appCtx.bindService(intent, conn, bindFlags) } catch (se: SecurityException) { Log.e(TAG, "bindService SecurityException: $cn | ${se.message}") cont.resumeWith( @@ -194,9 +240,25 @@ object PaddleOcrPluginHost { ) return@suspendCancellableCoroutine } + if (!ok && bindFlags != Context.BIND_AUTO_CREATE) { + ok = try { + appCtx.bindService(intent, conn, Context.BIND_AUTO_CREATE) + } catch (se: SecurityException) { + Log.e(TAG, "bindService SecurityException: $cn | ${se.message}") + cont.resumeWith( + Result.failure( + IllegalStateException( + "bindService SecurityException: $cn. Please make sure the plugin declares and the Service uses this permission.", se + ) + ) + ) + return@suspendCancellableCoroutine + } + } if (!ok) { - Log.e(TAG, "bindService failed: $cn") - cont.resumeWith(Result.failure(IllegalStateException("bindService failed: $cn"))) + val msg = buildBindFailureMessage(appCtx, serviceInfo, cn) + Log.e(TAG, msg) + cont.resumeWith(Result.failure(IllegalStateException(msg))) return@suspendCancellableCoroutine } diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index da8856da..b1849ac6 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -1333,4 +1333,11 @@ لم يتم حفظ الاعدادات. هل تريد الخروج? فشل الحفظ جارٍ الحفظ... + ": " + فشل في تفعيل الاضافة + معلومات الاستثناء + تلميح + جرّب الضغط على زر \"تفعيل\" لتفعيل الاضافة مرة واحدة.\nاذا نجح التفعيل، فسيتم تشغيل الزر تلقائيا خلال فترة زمنية معينة. + تفعيل + تم التفعيل بنجاح \ No newline at end of file diff --git a/app/src/main/res/values-en/strings.xml b/app/src/main/res/values-en/strings.xml index 421b4afa..5c07fcaa 100644 --- a/app/src/main/res/values-en/strings.xml +++ b/app/src/main/res/values-en/strings.xml @@ -1328,4 +1328,11 @@ The settings has not been saved, are you sure to exit? Failed to save Saving... + ": " + Failed to enable the plugin + Exception info + Hint + Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. + Activate + Activated successfully \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 3f594c0d..31efcac7 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -1331,4 +1331,11 @@ La configuracion no se ha guardado. ¿Seguro que quieres salir? Error al guardar Guardando... + ": " + No se pudo activar el plugin + Info de la excepcion + Sugerencia + Prueba a pulsar el boton \"Activar\" para activar el plugin una vez.\nSi la activacion se realiza correctamente, el boton se activara automaticamente en un periodo de tiempo. + Activar + Activado correctamente \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 7521e825..1c00bcd4 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -1331,4 +1331,11 @@ Les parametres ne sont pas enregistres. Quitter? Echec de l\'enregistrement Enregistrement... + " : " + Echec de l\'activation du plugin + Infos de l\'exception + Astuce + Essayez d\'appuyer sur le bouton \"Activer\" pour activer le plugin une fois.\nSi l\'activation reussit, le bouton s\'activera automatiquement dans un certain delai. + Activer + Activation reussie \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 240de399..a6674186 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -1332,4 +1332,11 @@ 設定が保存されていません. 終了しますか? 保存に失敗しました 保存中... + ": " + プラグインの有効化に失敗しました + 例外情報 + ヒント + \"有効化\" ボタンをタップして, プラグインを一度有効化してみてください.\n有効化に成功すると, 一定時間内にボタンが自動的にオンになります. + 有効化 + 有効化しました \ No newline at end of file diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index c7892265..2688fb73 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -1333,4 +1333,11 @@ 설정이 저장되지 않았습니다. 종료할까요? 저장에 실패했습니다 저장 중... + ": " + 플러그인을 활성화하지 못했습니다 + 예외 정보 + 힌트 + \"활성화\" 버튼을 눌러 플러그인을 한 번 활성화해 보세요.\n활성화에 성공하면 일정 시간 내에 버튼이 자동으로 켜집니다. + 활성화 + 활성화되었습니다 \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index cc417a9a..0f4a7834 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -1331,4 +1331,11 @@ Настройки не сохранены. Выйти? Не удалось сохранить Сохранение... + ": " + Не удалось включить плагин + Сведения об исключении + Подсказка + Попробуйте нажать кнопку \"Активировать\", чтобы активировать плагин один раз.\nЕсли активация пройдет успешно, кнопка автоматически включится в течение некоторого времени. + Активировать + Активация выполнена \ No newline at end of file diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 44246469..d6b575ee 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -1327,4 +1327,11 @@ 設置尚未保存, 確定要退出嗎 保存失敗 正在保存... + ": " + 插件啓用失敗 + 異常信息 + 提示 + 可嘗試點擊 \"激活\" 按鈕激活一次插件.\n如激活成功, 按鈕將在一定時間內自動開啓. + 激活 + 激活成功 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index fbd5aab5..bbdc0b82 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -1327,4 +1327,11 @@ 設定尚未儲存, 確定要退出嗎 儲存失敗 正在儲存... + ": " + 外掛啟用失敗 + 異常資訊 + 提示 + 可嘗試點選 \"啟用\" 按鈕啟用一次外掛.\n如啟用成功, 按鈕將在一定時間內自動開啟. + 啟用 + 啟用成功 \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 71868fb9..214740e6 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -1328,4 +1328,11 @@ 设置尚未保存, 确定要退出吗 保存失败 正在保存... + ": " + 插件启用失败 + 异常信息 + 提示 + 可尝试点击 \"激活\" 按钮激活一次插件.\n如激活成功, 按钮将在一定时间内自动开启. + 激活 + 激活成功 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e94ae4b2..c0aa0df5 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1602,4 +1602,11 @@ The settings has not been saved, are you sure to exit? Failed to save Saving... + ": " + Failed to enable the plugin + Exception info + Hint + Try clicking the \"Activate\" button to activate the plugin once.\nIf activation is successful, the button will automatically turn on within a certain period of time. + Activate + Activated successfully \ No newline at end of file diff --git a/version.properties b/version.properties index d3268442..01582e72 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Thu Feb 12 21:05:03 CST 2026 -BUILD_TIME=1770901503083 +#Fri Feb 13 15:23:40 CST 2026 +BUILD_TIME=1770967420765 COMPILE_SDK_VERSION=36 IMAGE_QUANT_CMAKE_VERSION=3.22.1 IMAGE_QUANT_NDK_VERSION=26.1.10909125 @@ -27,6 +27,6 @@ RAPID_OCR_OPENCV_MOBILE_LABEL_VERSION=13 RAPID_OCR_OPENCV_MOBILE_VERSION=4.5.3 TARGET_SDK_VERSION=36 TARGET_SDK_VERSION_INRT=29 -VERSION_BUILD=3735 -VERSION_NAME=6.7.0 Alpha19 +VERSION_BUILD=3738 +VERSION_NAME=6.7.0 Alpha20 VSCODE_EXT_REQUIRED_VERSION=1.0.13