fix(ios): always start new notes blank
This commit is contained in:
1 parent
a558062d37
commit
41921ad96f
3 files changed
+44
-35
No files matched your search
@@ -142,7 +142,7 @@ final class SharedTipTapRuntime: NSObject, WKScriptMessageHandler, WKNavigationD
|
||||
needsForcePushOnBind = true
|
||||
}
|
||||
// Drop action callbacks for the dismantled SwiftUI host so late JS `change`
|
||||
// events cannot rewrite the next create draft with this session's body.
|
||||
// events cannot rewrite a later editor session with this session's body.
|
||||
if var s = session {
|
||||
s.onChange = nil
|
||||
s.onResourcePress = nil
|
||||
@@ -635,7 +635,7 @@ final class SharedTipTapRuntime: NSObject, WKScriptMessageHandler, WKNavigationD
|
||||
pushContentIfNeeded(force: true)
|
||||
case "change":
|
||||
// Host dismantled (create/edit dismissed) — drop late events so they cannot
|
||||
// resurrect the previous body into a new-note draft via onChange autosave.
|
||||
// resurrect the previous body in a later editor session.
|
||||
guard let session, session.onChange != nil else { return }
|
||||
let md = body["contentMarkdown"] as? String ?? ""
|
||||
let json = body["contentJson"] as? String ?? session.documentJSON
|
||||
|
||||
@@ -9,7 +9,8 @@ private enum ImagePickerRoute: String, Identifiable {
|
||||
}
|
||||
|
||||
enum MemoEditMode: Equatable {
|
||||
/// `seed` pre-fills title/body/tags (template / clip-style create). When nil, restores local new-note draft.
|
||||
/// `seed` pre-fills title/body/tags for an explicit template, clip, or share flow.
|
||||
/// A regular create always starts blank.
|
||||
case create(notebookId: String, seed: CreateMemoSeed? = nil)
|
||||
case edit(memoId: String)
|
||||
}
|
||||
@@ -781,19 +782,23 @@ struct MemoEditView: View {
|
||||
guard let scope = env.session.dataScope else { return }
|
||||
switch mode {
|
||||
case .create(let nb, let seed):
|
||||
// A regular create must never inherit state from the previous create
|
||||
// session. Clear both in-memory fields and any legacy persisted draft.
|
||||
title = ""
|
||||
tagsText = ""
|
||||
contentMarkdown = ""
|
||||
contentJSON = MemoEditViewModel.emptyDocJSON
|
||||
notebookId = nb
|
||||
memoId = nil
|
||||
expectedRevision = nil
|
||||
expectedContentHash = nil
|
||||
try? env.drafts.clear(scope: scope, key: DraftRepository.newKey)
|
||||
if let seed {
|
||||
// Template / explicit seed wins over local new-note draft (Android initialDraft).
|
||||
// Only explicit template / clip / share input may prefill a create.
|
||||
title = seed.title
|
||||
tagsText = seed.tagsText
|
||||
contentMarkdown = seed.contentMarkdown
|
||||
contentJSON = MemoEditViewModel.emptyDocJSON
|
||||
} else if let draft = try? env.drafts.read(scope: scope, key: DraftRepository.newKey) {
|
||||
title = draft.title
|
||||
tagsText = draft.tagsText
|
||||
contentMarkdown = draft.contentMarkdown
|
||||
contentJSON = draft.contentJson ?? contentJSON
|
||||
if !draft.notebookId.isEmpty { notebookId = draft.notebookId }
|
||||
}
|
||||
baselineMarkdown = contentMarkdown
|
||||
case .edit(let id):
|
||||
@@ -893,29 +898,14 @@ struct MemoEditView: View {
|
||||
}
|
||||
let now = EdgeEverDate.nowString()
|
||||
|
||||
// Create mode before materialize: draft only.
|
||||
// Create mode after materialize (image upload) OR edit: mirror + outbox update.
|
||||
// A non-materialized create remains in memory until Done/Back commits it.
|
||||
// Persisting it under the shared `new` key would leak this content into a
|
||||
// later create session.
|
||||
if isCreate, !hasMaterializedServerMemo {
|
||||
try? env.drafts.write(
|
||||
scope: scope,
|
||||
draft: viewModel.makeDraft(key: DraftRepository.newKey, expectedRevision: nil, updatedAt: now)
|
||||
)
|
||||
NSLog(
|
||||
"MemoEditView persist draft-only mdLen=%d hasImg=%d",
|
||||
contentMarkdown.count,
|
||||
contentMarkdown.contains("/api/v1/resources/") ? 1 : 0
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
guard let memoId, !memoId.hasPrefix("local:") else {
|
||||
// Offline local: create still in flight — keep draft.
|
||||
if isCreate {
|
||||
try? env.drafts.write(
|
||||
scope: scope,
|
||||
draft: viewModel.makeDraft(key: DraftRepository.newKey, expectedRevision: nil, updatedAt: now)
|
||||
)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -955,14 +945,16 @@ struct MemoEditView: View {
|
||||
)
|
||||
expectedRevision = rev
|
||||
expectedContentHash = hash
|
||||
try? env.drafts.write(
|
||||
scope: scope,
|
||||
draft: viewModel.makeDraft(
|
||||
key: isCreate ? DraftRepository.newKey : DraftRepository.memoKey(memo.id),
|
||||
expectedRevision: rev,
|
||||
updatedAt: now
|
||||
if !isCreate {
|
||||
try? env.drafts.write(
|
||||
scope: scope,
|
||||
draft: viewModel.makeDraft(
|
||||
key: DraftRepository.memoKey(memo.id),
|
||||
expectedRevision: rev,
|
||||
updatedAt: now
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
NSLog(
|
||||
"MemoEditView persist update memo=%@ baseRev=%d mdLen=%d hasImg=%d jsonHasImg=%d",
|
||||
memo.id,
|
||||
|
||||
@@ -119,6 +119,23 @@ final class ChromeParityTests: XCTestCase {
|
||||
XCTAssertFalse(src.contains("ToolbarItem(placement: .cancellationAction)"), "system Close toolbar not Android create chrome")
|
||||
}
|
||||
|
||||
func testRegularCreateNeverRestoresOrPersistsPreviousCreateContent() throws {
|
||||
let src = try readShippedSource("Features/Workspace/MemoEditView.swift")
|
||||
|
||||
XCTAssertFalse(
|
||||
src.contains("env.drafts.read(scope: scope, key: DraftRepository.newKey)"),
|
||||
"regular create must not restore the previous new-note draft"
|
||||
)
|
||||
XCTAssertFalse(
|
||||
src.contains("makeDraft(key: DraftRepository.newKey"),
|
||||
"regular create must not persist content for a later create session"
|
||||
)
|
||||
XCTAssertTrue(
|
||||
src.contains("env.drafts.clear(scope: scope, key: DraftRepository.newKey)"),
|
||||
"regular create must remove legacy new-note drafts"
|
||||
)
|
||||
}
|
||||
|
||||
func testMemoDetailViewUsesDetailChromeAndEditFab() throws {
|
||||
let src = try readShippedSource("Features/Workspace/MemoDetailView.swift")
|
||||
XCTAssertTrue(src.contains("DetailMemoChrome.header") || src.contains("detailHeader"), src)
|
||||
|
||||
Reference in new issue
Block a user