From 3e8f70de249efeecb38dc88f74aed5a9d16da3c3 Mon Sep 17 00:00:00 2001 From: SuperMonster003 Date: Wed, 25 Feb 2026 03:04:22 +0800 Subject: [PATCH] =?UTF-8?q?6.7.0=20-=20Alpha21=20-=20=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E7=BC=96=E8=BE=91=E5=99=A8=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=E6=9C=AA=E4=BF=9D=E5=AD=98=E5=86=85=E5=AE=B9?= =?UTF-8?q?=E8=A2=AB=E9=87=8D=E7=BD=AE=E7=9A=84=E9=97=AE=E9=A2=98=20(?= =?UTF-8?q?=E8=AF=95=E4=BF=AE)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/autojs/autojs/ui/edit/EditActivity.kt | 55 ++++++++----- .../org/autojs/autojs/ui/edit/EditorView.kt | 82 ++++++++++++++++++- version.properties | 6 +- 3 files changed, 118 insertions(+), 25 deletions(-) diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.kt b/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.kt index 9d64787b..1d39e7ad 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.kt +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditActivity.kt @@ -110,7 +110,32 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc EditorMenu(editorView, readOnly).also { mEditorMenu = it } - StableDraftFileHelper(this, editorView.uri?.path).also { + + // Restore draft as early as possible to avoid being overwritten by async file loading. + // We intentionally do this in onCreate(), not in onRestoreInstanceState(), + // because handleIntent() may start async loading and call setInitialText() later. + // + // zh-CN: + // 尽可能早地恢复草稿, 避免被异步文件加载覆盖. + // 我们刻意在 onCreate() 中恢复, 而不是在 onRestoreInstanceState() 中恢复, + // 因为 handleIntent() 可能启动异步加载并在稍后调用 setInitialText(). + savedInstanceState?.getString("text")?.let { draftText -> + mEditorView.restoreDraftTextForThisSession(draftText) + } ?: savedInstanceState?.getString("path")?.let { path -> + Observable.just(path) + .observeOn(Schedulers.io()) + .map { PFiles.read(it) } + .observeOn(AndroidSchedulers.mainThread()) + .subscribe({ draftText -> + mEditorView.restoreDraftTextForThisSession(draftText) + }, Throwable::printStackTrace) + } + + // Use a stable key from intent instead of editorView.uri (which is not set yet here). + // zh-CN: 使用 intent 中的稳定 key, 避免此处 editorView.uri 尚未赋值导致 key 为 null. + val draftKeyPath = intent.getStringExtra(EditorView.EXTRA_PATH) ?: intent.data?.path + + StableDraftFileHelper(this, draftKeyPath).also { draftFileHelper = it } (intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0).also { @@ -403,9 +428,15 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc } override fun onSaveInstanceState(outState: Bundle) { - // Save draft when UI indicates "needs save". - // zh-CN: 当 UI 表示 "需要保存" 时保存草稿. - if (!mEditorView.saveStickyDirty) { + + // Save draft when content actually differs from baseline OR UI indicates "needs save". + // This makes state restore robust against any sticky/menu state glitches. + // + // zh-CN: + // 当内容相对基线确实发生变化, 或 UI 表示 "需要保存" 时, 保存草稿. + // 这能使状态恢复不再受 sticky/menu 状态偶发异常的影响. + val needDraft = mEditorView.isTextChanged || mEditorView.saveStickyDirty + if (!needDraft) { super.onSaveInstanceState(outState) return } @@ -431,24 +462,10 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc override fun onResume() { super.onResume() + mEditorView.syncPrimaryMenuState() runCatching { mEditorView.refreshSymbolsBar() } } - override fun onRestoreInstanceState(savedInstanceState: Bundle) { - super.onRestoreInstanceState(savedInstanceState) - savedInstanceState.getString("text")?.let { - mEditorView.setRestoredText(it) - return - } - savedInstanceState.getString("path")?.let { path -> - Observable.just(path) - .observeOn(Schedulers.io()) - .map { PFiles.read(it) } - .observeOn(AndroidSchedulers.mainThread()) - .subscribe({ mEditorView.editor.text = it }, Throwable::printStackTrace) - } - } - override fun addRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) { mRequestPermissionCallbacks.addCallback(callback) } diff --git a/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt b/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt index 3821947b..fca0271b 100644 --- a/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt +++ b/app/src/main/java/org/autojs/autojs/ui/edit/EditorView.kt @@ -158,6 +158,15 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag @Volatile private var mHadDirectEditSinceSave: Boolean = false + // Whether a draft has been restored in this session. + // If true, subsequent async file-load setInitialText() must NOT overwrite the restored draft. + // + // zh-CN: + // 本次会话是否已恢复草稿. + // 若为 true, 则后续异步文件加载触发的 setInitialText() 不得覆盖已恢复的草稿. + @Volatile + private var mDraftRestoredInThisSession: Boolean = false + // Guard flag to mark text changes caused by undo/redo button actions. // This is used to distinguish direct edits from history navigation. // @@ -374,8 +383,20 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag // Initialize menu state early to avoid "first render" flicker. // zh-CN: 尽早初始化菜单状态, 避免首次渲染闪烁. mEditorLoading = true - saveStickyDirty = false - mHadDirectEditSinceSave = false + + // Do NOT reset dirty flags if we already restored a draft in this session. + // Otherwise, the editor will keep the draft text but lose "needs save" state, + // causing Save button to turn off and exit-confirm not to show. + // + // zh-CN: + // 若本会话已恢复草稿, 则不要重置脏标记. + // 否则会出现草稿文本仍在但 "需要保存" 状态丢失, + // 导致保存按钮熄灭且退出不提示保存. + if (!mDraftRestoredInThisSession) { + saveStickyDirty = false + mHadDirectEditSinceSave = false + } + syncPrimaryMenuState() val name = intent.getStringExtra(EXTRA_NAME) @@ -418,6 +439,49 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag editor.text = text } + /** + * Restore draft text for this editor session. + * + * Behavior: + * - Applies text immediately. + * - Marks current session as "draft restored", so async file loading won't overwrite it. + * - Marks editor state as dirty (needs save) and refreshes menu state. + * + * zh-CN: + * 为本次编辑会话恢复草稿文本. + * + * 行为: + * - 立即应用文本. + * - 标记本会话为 "已恢复草稿", 防止异步文件加载覆盖. + * - 标记为未保存并刷新菜单状态. + */ + fun restoreDraftTextForThisSession(text: String) { + mDraftRestoredInThisSession = true + mRestoredText = text + editor.text = text + markRestoredDraftAsDirty() + } + + /** + * Mark a restored draft as unsaved and refresh menu state. + * + * Rationale: + * - Draft restore should not be treated as "saved baseline". + * - Otherwise Save button may appear disabled and exit-confirm may not show. + * + * zh-CN: + * 将已恢复的草稿标记为未保存, 并刷新菜单状态. + * + * 理由: + * - 草稿恢复不应被当作 "已保存基线". + * - 否则保存按钮可能呈灰色, 且退出确认可能不弹出. + */ + fun markRestoredDraftAsDirty() { + saveStickyDirty = true + mHadDirectEditSinceSave = true + syncPrimaryMenuState() + } + private fun handleText(intent: Intent): Observable { val content = intent.getStringExtra(EXTRA_CONTENT) if (content != null) { @@ -1045,6 +1109,18 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag mEditorLoading = true syncPrimaryMenuState() + // If draft has been restored in this session, do NOT overwrite it with async file load results. + // Still end loading flags and sync menu state to keep UI consistent. + // + // zh-CN: + // 若本会话已恢复草稿, 则不要用异步文件加载结果覆盖它. + // 但仍需结束 loading 标记并同步菜单状态, 保持 UI 一致. + if (mDraftRestoredInThisSession) { + mEditorLoading = false + syncPrimaryMenuState() + return + } + if (mRestoredText != null) { editor.text = mRestoredText!! mRestoredText = null @@ -1104,7 +1180,7 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag } } - private fun syncPrimaryMenuState() { + internal fun syncPrimaryMenuState() { // Unified primary buttons state. // zh-CN: 统一主按钮状态. when { diff --git a/version.properties b/version.properties index 692cdf36..08a774cb 100644 --- a/version.properties +++ b/version.properties @@ -1,5 +1,5 @@ -#Mon Feb 23 16:51:52 CST 2026 -BUILD_TIME=1771836712381 +#Wed Feb 25 03:02:22 CST 2026 +BUILD_TIME=1771959742388 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=3750 +VERSION_BUILD=3752 VERSION_NAME=6.7.0 Alpha21 VSCODE_EXT_REQUIRED_VERSION=1.0.13