From 76086031d8f4004681d1de7bde8a82db23c7cf14 Mon Sep 17 00:00:00 2001 From: Frank Barrett Date: Thu, 9 Jul 2026 20:54:20 -0700 Subject: [PATCH] feat: copy a note's text from the Mac menus The web editor has a Copy-text action; the Mac app had no way to grab a note's body without opening it and selecting all. Adds Copy Text to the row context menu and the Note menu, and extracts the pasteboard write shared with Copy Share Link into MacPasteboard. Co-Authored-By: Claude Fable 5 --- ios/KeepMac/KeepMacApp.swift | 5 +++++ ios/KeepMac/MacRootView.swift | 1 + ios/KeepMac/ShareLink.swift | 14 ++++++++++---- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/ios/KeepMac/KeepMacApp.swift b/ios/KeepMac/KeepMacApp.swift index 0f41029..cada9bb 100644 --- a/ios/KeepMac/KeepMacApp.swift +++ b/ios/KeepMac/KeepMacApp.swift @@ -68,6 +68,11 @@ struct NoteCommands: Commands { Divider() + Button("Copy Text") { + if let note { MacPasteboard.copy(note.body) } + } + .disabled(note == nil) + Button("Copy Share Link") { if let note { Task { await store.copyShareLink(note) } } } diff --git a/ios/KeepMac/MacRootView.swift b/ios/KeepMac/MacRootView.swift index 29fdbd1..1c71591 100644 --- a/ios/KeepMac/MacRootView.swift +++ b/ios/KeepMac/MacRootView.swift @@ -177,6 +177,7 @@ struct MacRootView: View { } } Divider() + Button("Copy Text") { MacPasteboard.copy(note.body) } Button("Copy Share Link") { Task { await store.copyShareLink(note) } } if note.shareToken != nil { Button("Stop Sharing") { Task { await store.unshare(note) } } diff --git a/ios/KeepMac/ShareLink.swift b/ios/KeepMac/ShareLink.swift index f1f80dd..a8e18ba 100644 --- a/ios/KeepMac/ShareLink.swift +++ b/ios/KeepMac/ShareLink.swift @@ -1,13 +1,19 @@ import AppKit +@MainActor +enum MacPasteboard { + static func copy(_ string: String) { + let pasteboard = NSPasteboard.general + pasteboard.clearContents() + pasteboard.setString(string, forType: .string) + } +} + /// Mac-side share helper: makes sure the public link exists, then puts it on /// the pasteboard. Lives in the Mac target because of NSPasteboard. extension NotesStore { func copyShareLink(_ note: Note) async { guard let token = (await share(note))?.shareToken else { return } - let url = Config.baseURL.appendingPathComponent("p/\(token)") - let pasteboard = NSPasteboard.general - pasteboard.clearContents() - pasteboard.setString(url.absoluteString, forType: .string) + MacPasteboard.copy(Config.baseURL.appendingPathComponent("p/\(token)").absoluteString) } }