fix: batch note formatting to prevent typing flashes
This commit is contained in:
@@ -41,6 +41,57 @@ func noteFormattingHidesSyntaxButPreservesMarkdownAndLiteralCode() throws {
|
||||
#expect(reloaded.contents.string == source)
|
||||
}
|
||||
|
||||
private final class NotesLayoutProbe: NSLayoutManager {
|
||||
var observeFormatting: ((NSTextStorage) -> Void)?
|
||||
|
||||
override func processEditing(for textStorage: NSTextStorage, edited editMask: NSTextStorageEditActions,
|
||||
range newCharRange: NSRange, changeInLength delta: Int,
|
||||
invalidatedRange invalidatedCharRange: NSRange) {
|
||||
observeFormatting?(textStorage)
|
||||
super.processEditing(for: textStorage, edited: editMask, range: newCharRange,
|
||||
changeInLength: delta, invalidatedRange: invalidatedCharRange)
|
||||
}
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func typingDoesNotExposeUnformattedExistingTextToLayout() throws {
|
||||
_ = NSApplication.shared
|
||||
let suite = "NotesFlashing.\(UUID().uuidString)"
|
||||
let defaults = try #require(UserDefaults(suiteName: suite))
|
||||
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(suite)
|
||||
defer {
|
||||
defaults.removePersistentDomain(forName: suite)
|
||||
try? FileManager.default.removeItem(at: directory)
|
||||
}
|
||||
let store = try NotesStore(directory: directory)
|
||||
let id = try store.create()
|
||||
try store.update(id: id, contents: NSAttributedString(string: "# Heading\n- [ ] Task\nPlain"))
|
||||
defaults.set(id.uuidString, forKey: "selectedNote")
|
||||
let controller = NotesController(defaults: defaults, directory: directory)
|
||||
let window = NSWindow(contentRect: NSRect(x: 0, y: 0, width: 570, height: 404),
|
||||
styleMask: .borderless, backing: .buffered, defer: false)
|
||||
window.contentViewController = controller
|
||||
defer { _ = controller.close(); window.orderOut(nil) }
|
||||
func descendants(_ view: NSView) -> [NSView] { [view] + view.subviews.flatMap(descendants) }
|
||||
let editor = try #require(descendants(controller.view).compactMap { $0 as? NotesTextView }.first)
|
||||
let layout = NotesLayoutProbe()
|
||||
try #require(editor.textContainer).replaceLayoutManager(layout)
|
||||
editor.refreshTasks()
|
||||
window.makeFirstResponder(editor)
|
||||
layout.observeFormatting = { storage in
|
||||
let text = storage.string as NSString
|
||||
let heading = text.range(of: "Heading")
|
||||
let task = text.range(of: "Task")
|
||||
#expect((storage.attribute(.font, at: heading.location, effectiveRange: nil) as? NSFont)?.pointSize == 26)
|
||||
#expect((storage.attribute(.paragraphStyle, at: task.location, effectiveRange: nil) as? NSParagraphStyle)?.headIndent == 22)
|
||||
#expect(storage.attribute(MarkdownHighlighting.hiddenMarkup, at: 0, effectiveRange: nil) as? Bool == true)
|
||||
}
|
||||
defer { layout.observeFormatting = nil }
|
||||
editor.insertText("!", replacementRange: NSRange(location: editor.string.utf16.count, length: 0))
|
||||
#expect(editor.markdownString == "# Heading\n- [ ] Task\nPlain!")
|
||||
#expect(try NotesStore(directory: directory).notes.first?.contents.string == editor.markdownString)
|
||||
}
|
||||
|
||||
@Test @MainActor
|
||||
func noteImagesRenderRoundedWithoutChangingSavedImageData() throws {
|
||||
_ = NSApplication.shared
|
||||
@@ -196,8 +247,6 @@ func notesFormattingShortcutsToggleCombinedStylesAndRespectPopupFocus() throws {
|
||||
#expect(try shortcut("b"))
|
||||
#expect(editor.markdownString == "fox 🦊")
|
||||
|
||||
let hide = try #require(descendants(content).compactMap { $0 as? NSButton }.first { $0.toolTip == "Hide formatting" })
|
||||
hide.performClick(nil)
|
||||
#expect(try shortcut("x", shift: true))
|
||||
#expect(editor.markdownString == "~~fox 🦊~~")
|
||||
#expect(try shortcut("x", shift: true))
|
||||
|
||||
Reference in New Issue
Block a user