6.7.0 - Alpha21 - 修复代码编辑器可能导致未保存内容被重置的问题 (试修)
This commit is contained in:
@@ -110,7 +110,32 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
|||||||
EditorMenu(editorView, readOnly).also {
|
EditorMenu(editorView, readOnly).also {
|
||||||
mEditorMenu = it
|
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
|
draftFileHelper = it
|
||||||
}
|
}
|
||||||
(intent.flags and Intent.FLAG_ACTIVITY_NEW_TASK != 0).also {
|
(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) {
|
override fun onSaveInstanceState(outState: Bundle) {
|
||||||
// Save draft when UI indicates "needs save".
|
|
||||||
// zh-CN: 当 UI 表示 "需要保存" 时保存草稿.
|
// Save draft when content actually differs from baseline OR UI indicates "needs save".
|
||||||
if (!mEditorView.saveStickyDirty) {
|
// 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)
|
super.onSaveInstanceState(outState)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -431,24 +462,10 @@ open class EditActivity : BaseActivity(), DelegateHost, PermissionRequestProxyAc
|
|||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
|
mEditorView.syncPrimaryMenuState()
|
||||||
runCatching { mEditorView.refreshSymbolsBar() }
|
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) {
|
override fun addRequestPermissionsCallback(callback: OnRequestPermissionsResultCallback) {
|
||||||
mRequestPermissionCallbacks.addCallback(callback)
|
mRequestPermissionCallbacks.addCallback(callback)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,6 +158,15 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
|
|||||||
@Volatile
|
@Volatile
|
||||||
private var mHadDirectEditSinceSave: Boolean = false
|
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.
|
// Guard flag to mark text changes caused by undo/redo button actions.
|
||||||
// This is used to distinguish direct edits from history navigation.
|
// 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.
|
// Initialize menu state early to avoid "first render" flicker.
|
||||||
// zh-CN: 尽早初始化菜单状态, 避免首次渲染闪烁.
|
// zh-CN: 尽早初始化菜单状态, 避免首次渲染闪烁.
|
||||||
mEditorLoading = true
|
mEditorLoading = true
|
||||||
|
|
||||||
|
// 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
|
saveStickyDirty = false
|
||||||
mHadDirectEditSinceSave = false
|
mHadDirectEditSinceSave = false
|
||||||
|
}
|
||||||
|
|
||||||
syncPrimaryMenuState()
|
syncPrimaryMenuState()
|
||||||
|
|
||||||
val name = intent.getStringExtra(EXTRA_NAME)
|
val name = intent.getStringExtra(EXTRA_NAME)
|
||||||
@@ -418,6 +439,49 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
|
|||||||
editor.text = text
|
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<String> {
|
private fun handleText(intent: Intent): Observable<String> {
|
||||||
val content = intent.getStringExtra(EXTRA_CONTENT)
|
val content = intent.getStringExtra(EXTRA_CONTENT)
|
||||||
if (content != null) {
|
if (content != null) {
|
||||||
@@ -1045,6 +1109,18 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
|
|||||||
mEditorLoading = true
|
mEditorLoading = true
|
||||||
syncPrimaryMenuState()
|
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) {
|
if (mRestoredText != null) {
|
||||||
editor.text = mRestoredText!!
|
editor.text = mRestoredText!!
|
||||||
mRestoredText = null
|
mRestoredText = null
|
||||||
@@ -1104,7 +1180,7 @@ class EditorView : LinearLayout, OnHintClickListener, ClickCallback, ToolbarFrag
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun syncPrimaryMenuState() {
|
internal fun syncPrimaryMenuState() {
|
||||||
// Unified primary buttons state.
|
// Unified primary buttons state.
|
||||||
// zh-CN: 统一主按钮状态.
|
// zh-CN: 统一主按钮状态.
|
||||||
when {
|
when {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
#Mon Feb 23 16:51:52 CST 2026
|
#Wed Feb 25 03:02:22 CST 2026
|
||||||
BUILD_TIME=1771836712381
|
BUILD_TIME=1771959742388
|
||||||
COMPILE_SDK_VERSION=36
|
COMPILE_SDK_VERSION=36
|
||||||
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
|
||||||
@@ -27,6 +27,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=36
|
TARGET_SDK_VERSION=36
|
||||||
TARGET_SDK_VERSION_INRT=29
|
TARGET_SDK_VERSION_INRT=29
|
||||||
VERSION_BUILD=3750
|
VERSION_BUILD=3752
|
||||||
VERSION_NAME=6.7.0 Alpha21
|
VERSION_NAME=6.7.0 Alpha21
|
||||||
VSCODE_EXT_REQUIRED_VERSION=1.0.13
|
VSCODE_EXT_REQUIRED_VERSION=1.0.13
|
||||||
|
|||||||
Reference in New Issue
Block a user