Last updated: 2026-04-10
- Build a polished native macOS menu bar notes utility
- Keep the experience lightweight, elegant, and recognizably Mac-native
- Publish publicly on GitHub first, then decide later whether paid distribution is still worth pursuing
- Phase 3: public open-source packaging and issue-driven stabilization
- Status: core note workflow is implemented; the repo is now being packaged for direct GitHub publication while App Store submission remains optional future work
- Product direction, research summary, and long-form memory documented
- Local git repository initialized and remote configured:
git@github.com:C23333/topleaf.git
- GitHub publication docs added:
README.mdREADME.zh-Hans.mdCONTRIBUTING.mddocs/open-source-release-guide.mddocs/open-source-release-guide.zh-Hans.mddocs/github-release-guide.mddocs/github-release-guide.zh-Hans.mddocs/assets/README.md- existing remote
LICENSEmerged locally asMIT
- GitHub automation added:
scripts/package-github-release.sh.github/workflows/ci.yml.github/workflows/release.yml.github/release.yml
- Native macOS stack established:
SwiftUI + AppKitNSStatusItem + anchored NSPanelNSTextViewwrapper for editing
- Project infrastructure completed:
project.yml- generated
Topleaf.xcodeproj .gitignore.swift-version
- Environment validated:
- full Xcode selected
xcodegen,swiftformat,xcbeautifyinstalled
- Menu bar shell implemented:
- left click toggles anchored panel
- right click opens fallback menu
- configurable panel size persistence
- Main panel implemented:
- large dropdown workspace
- search
- new note
- settings entry
- empty states
- toast feedback
- Note workflow implemented:
- create, open, copy, delete
- configurable primary click action
Optionclick alternate action- context menu fallback
- open in panel
- open in separate window
- Note metadata implemented:
- pinning
- priority
- retention mode
- auto-delete expiration
- Persistence implemented:
- local SQLite database via
SQLite3 - notes stored under Application Support
- automatic schema creation
- fetch, upsert, delete, expiration cleanup, clear-on-quit cleanup
- local SQLite database via
- Save lifecycle implemented:
- debounced autosave
- flush on editor disappearance
- flush on app resign active
- flush on panel hide
- flush and cleanup on termination
- Clipboard capture implemented:
- manual capture from the panel header and status menu
- optional automatic clipboard capture
- clipboard-origin notes are now persisted explicitly as note source metadata, independent of categories
- independent retention policy for auto-captured clipboard notes:
- clear on quit
- 1 day
- 7 days
- keep forever
- independent type filters for text, images, and files
- configurable allowed file extensions
- optional filing of captured notes into a dedicated
Clipboard Inbox / 剪贴板收纳category - categories-off prompt when enabling clipboard archiving from settings
- unsupported manual clipboard items show toast feedback
- unsupported automatic clipboard items are silently ignored
- app-originated clipboard copies are ignored to prevent self-recursion
- copied images are stored in Application Support attachments
- copied files are now copied into Application Support attachments instead of being kept as external path references
- attachments can now be copied back to the pasteboard:
- images as image pasteboard content when possible
- other attachments as file URLs
- Settings implemented:
- primary click action
- alternate click action
- default open mode
- default retention mode
- auto-delete days
- autosave debounce
- in-app space analysis:
- app bundle footprint
- local data footprint
- database footprint
- attachments footprint
- note/category/reference counts
- refresh + reveal-data-folder actions
- destructive clear-local-data action with explicit consequence copy and second confirmation
- clipboard auto-capture
- clipboard type filters
- clipboard file-extension filters
- Markdown preview toggle
- launch at login
- clipboard quick-access shortcut:
- configurable modifier preset
- configurable key
- optional auto-paste after copy
- real macOS paste-permission status surfaced inside settings
- explicit setup + refresh actions when automatic paste permission is missing
- support and diagnostics:
- feedback mail now always targets the fixed support inbox
ytemail163@163.com - daily rotating logs with automatic compression
- configurable diagnostic-log retention:
- 3 days
- 7 days
- open logs in Finder
- feedback mail now always targets the fixed support inbox
- about and support center:
- custom About window replaces the standard AppKit about panel
- shows app version/build, local-first positioning, and key support actions
- surfaces storage footprint summary and direct reveal actions for:
- data folder
- logs folder
- current active log file
- current app bundle
- includes direct entry points for:
- getting started
- settings
- support email draft
- includes a release-readiness self-check for:
- install location
- debug vs release-like build context
- auto-paste accessibility status
- launch-at-login setting
- first-run completion
- code-signing identity and team ID when available
- can now export support materials for testing and issue reporting:
- plain-text support report copy/export
- Finder reveal after export
- support-package export containing the current report plus recent logs
- backup and restore:
- export self-contained JSON backup archives from settings
- restore notes, categories, and attachments from a previous Topleaf backup
- destructive import confirmation before replacing local data
- readable exported attachments are embedded in the archive
- restore stages attachments before replacing local attachment storage
- readable exported external-file attachments are restored as app-managed local files
- skipped or fallback attachments are counted and surfaced to the user
- clear logs with confirmation
- mailto-based feedback draft
- storage analysis now includes log footprint
- category shortcuts:
- two configurable global shortcut slots
- each slot can target an existing root or child category
- shortcuts open the main panel near the pointer and pre-apply the category filter
- transient shortcut filters clear when the panel closes
- duplicate in-app shortcut detection
- known macOS-reserved shortcut warnings
- stale shortcut/category links are cleared when categories or all local data are deleted
- Localization implemented:
- Simplified Chinese
- English
- string-key parity test between the two shipping languages
- UX polish implemented:
- focus routing for panel reopen and editor open
- keyboard shortcuts for new note and settings
- safe empty-copy feedback
- error toast visual differentiation
- localized generic persistence errors
- app-owned native settings window path for reliable local testing
- delayed focus scheduling to avoid transition/input races
- editor-local draft buffering to reduce typing lag
- upgraded panel chrome, note row surfaces, and empty-state styling
- simplified status-bar icon for clearer menu bar recognition
- panel root now extends into the titlebar area to remove wasted top space
- stable creation timestamps replaced relative ticking timers in note surfaces
- settings view rebuilt as a custom hosted preferences panel
- click-through hosting added so the first click lands on controls and note rows reliably
- menu bar tooltip now explains left-click vs right-click behavior
- status-bar icon now uses a simpler custom menu-bar-note template glyph for better small-size clarity
- status-bar icon geometry and rendering scale were adjusted again so it sits closer to neighboring menu bar apps instead of reading undersized
- editor header now uses a unified toolbar language instead of mixing a text pill with symbol groups
- detached note windows now open larger and cascade with predictable spacing instead of piling up
- settings window default and minimum size increased to avoid clipped content
- settings window reopen no longer forces an extra size mutation during presentation
- note list now supports multi-select mode with select-visible and bulk-delete confirmation
- clipboard quick-access shelf now opens near the pointer and uses a smaller panel footprint than the main list
- settings layout rewritten with aligned native-style cards, row descriptions, and better category management
- optional note colors implemented:
- five color tokens
- row indicators
- editor chips
- context-menu assignment
- optional two-level categories implemented:
- SQLite-backed category library
- root + child categories
- note assignment
- category filter in the panel
- non-destructive hide/show behavior through settings toggles
- Markdown note viewing implemented:
- source mode
- preview mode
- split mode
- block-based preview rendering for headings, lists, quotes, dividers, and fenced code blocks
- normalization for common pasted inline HTML fragments before Markdown rendering
- attachment cards in the detail surface
- in-app attachment preview window implemented:
- images previewed natively inside Topleaf
- PDFs previewed with
PDFKit - copy / reveal in Finder / open externally actions
- reduced-motion polish:
- panel transitions now reduce to opacity-only when macOS Reduce Motion is enabled
- row hover animation softens under Reduce Motion
- settings performance pass:
- settings window now uses a standard
NSHostingController - settings sections render inside a
LazyVStack - implicit settings-page animations are disabled to reduce dropdown/scroll jank
- settings window now uses a standard
- quick-access permission and paste reliability pass:
- automatic paste now accepts either macOS Accessibility trust or CoreGraphics post-event access, avoiding false negatives from checking only one path
- settings now show the current automatic-paste permission state inline
- missing permission now gets explicit setup + refresh controls instead of a permanently visible generic warning
- setup now opens
Privacy & Security > Accessibilitydirectly - quick-access copy now dismisses the panel before reactivating the previous app and sending
Command-V
- detached utility-window presentation pass:
- welcome/settings/about windows are now opened on the next main-runloop turn after menu actions
- detached windows now activate first and then force themselves to the front more reliably
- this specifically targets the case where
Getting Started / 新手引导logged as opened but did not visibly appear
- diagnostics noise reduction:
- app info-level diagnostics are still written to the local log file
- only warning/error entries are mirrored into the unified console now, which keeps Xcode output more readable
- panel sizing recursion mitigation:
- panel presentation now adjusts frame size instead of synchronously calling
setContentSize - this should further reduce the reported
layoutSubtreeIfNeededwarning frequency
- panel presentation now adjusts frame size instead of synchronously calling
- Release scaffolding implemented:
- app category metadata
- copyright metadata
- Release entitlements for:
- App Sandbox
- user-selected file read/write access
- About panel entry in the status menu
- Launch documentation implemented:
- public repository README
- Chinese public repository README
- contribution guide
- GitHub release publishing guide in English
- GitHub release publishing guide in Chinese
- GitHub open-source release guide in English
- GitHub open-source release guide in Chinese
- App Store launch guide
- App Store Connect submission guide in Chinese
- store metadata draft
- privacy policy template
- final store metadata recommendation
- icon direction guide
- generated first-pass app icon asset set plus generator script
- screenshot production script
- first-launch checklist in Chinese
- static landing page prepared for
hlkt.xyz - static privacy page prepared for
hlkt.xyz - static support page prepared for
hlkt.xyz - local release QA guide in Chinese
- manual testing checklist in Chinese
- local release QA shell script
- Verification completed:
swiftformat Sources Testsswiftformat Sources Tests scriptsxcodegen generatexcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafDerivedData buildxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafDerivedData testxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafBuildStage2 buildxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafUXPolishTests test- current passing test count:
30 xcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafBuild buildxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTests testxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTestsEscalated testxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTestsEscalated3 testxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTestsEscalated5 testxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafBuildNew2 build | xcbeautifyxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTestsEscalated6 test | xcbeautifyxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafBuildCurrent2 build | xcbeautify./scripts/run-release-qa.shxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafDerivedData test | xcbeautifyxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafQuickCheck build | xcbeautifyxcodebuild -project Topleaf.xcodeproj -scheme Topleaf -configuration Debug -derivedDataPath /tmp/TopleafTestsCurrent test | xcbeautify
- Automated coverage currently includes:
- SQLite repository behavior
- autosave persistence
- clear-on-quit cleanup
- auto-delete expiration assignment
- note color/category round-trip persistence
- category subtree deletion behavior
- settings-toggle hide/show preserving note metadata
- clipboard file-extension normalization
- clipboard auto-capture lifetime persistence
- clipboard archive preference persistence
- quick-access shortcut and support-email preference persistence
- English and Simplified Chinese localization key parity
- storage analysis aggregation for bundle/data/database/attachments
- note bulk deletion
- full local-data clearing
- clipboard note-source persistence
- repository clear-all behavior
- rotating-log retention and compression behavior
- log-retention preference persistence
- category shortcut persistence
- shortcut validation for duplicates / reserved combinations / missing categories
- AppPreferences startup no longer queries launch-at-login status from
SMAppService, reducing debug-console noise on launch - 2026-04-07 UX polish pass now also validated after editor/input, clipboard, preview-window, and visual-surface refactors
- current passing tests:
24
- Tightening local UX polish before broader external testing
- Keeping architecture notes, roadmap, and review log aligned with implementation
- Holding release work until the current panel/editor experience feels smooth enough in daily use
- Waiting on hands-on local testing feedback for the latest category-shortcut flow, rotated-log support loop, and quick-access polish
-
Added a maintenance and support layer around the storage panel:
- clear-local-data button with explicit destructive copy
- second confirmation before wiping notes, categories, imported attachments, and logs
mailto:feedback draft plus Finder-reveal logs
-
Added clipboard quick access:
- persisted clipboard note source in SQLite
- configurable global hotkey
- smaller cursor-near clipboard shelf
- optional auto-paste via Accessibility-backed
Command-V
-
Tightened quick-access paste permission handling and status-bar polish:
- switched automatic-paste permission checks to a composite Accessibility-trust + post-event-access model
- surfaced real permission state plus setup / refresh controls in settings
- setup button now opens the Accessibility pane directly, with prompt fallback
- stopped prompting immediately when the auto-paste toggle changes
- dismisses the quick-access panel before pasting back into the previous app
- enlarged the menu bar icon so it reads more naturally beside other status items
-
Added list multi-select workflows:
- explicit selection mode
- select visible under current search/filter
- bulk delete with clear consequence text
-
Added supporting infrastructure and tests:
- file-based diagnostic logger in Application Support
- support-email preference
- tests for quick-access preferences, note bulk delete, local-data clear, clipboard source persistence, and repository clear-all
-
Fixed note-list hit testing and interaction smoothness:
- note rows now declare an explicit rounded-card hit region
- list scroll content now expands to the full panel width instead of shrinking to visible labels
- focus handoff after open and dismiss was shortened to reduce perceived lag
-
Added clipboard intake controls:
- automatic clipboard capture preference
- independent text, image, and file filters
- allowed file-extension parsing with normalization for entries like
.pdf - manual capture feedback for skipped unsupported items
-
Added separate lifecycle control for auto-captured clipboard notes:
- clear on quit
- 1 day
- 7 days
- keep forever
-
Added dedicated clipboard archive behavior:
- captured notes can be auto-filed into
Clipboard Inbox / 剪贴板收纳 - enabling the feature now prompts to turn on categories if they are currently hidden
- disabling categories later does not destroy archive metadata, and settings now explain that hidden state
- captured notes can be auto-filed into
-
Added Markdown detail modes:
- source, preview, and split modes
- per-mode tooltips in the detail header
- preview rendering moved off the main actor to reduce typing hitching
- split mode now uses a simpler side-by-side layout instead of
HSplitView
-
Added in-app attachment handling:
- images and PDFs now open in a native preview window instead of always leaving the app
- attachment cards support copy, reveal in Finder, and open externally
- file-type pasteboard copies now work for PDFs, ZIPs, and other file attachments
-
Rebuilt the note editor bridge around a native placeholder-drawing
NSTextView:- fixes the first-input overlap with Chinese IME marked text
- avoids rebinding text during marked-text composition
- reduces the likelihood of SwiftUI "Modifying state during view update" warnings from editor sync
-
Tightened focus timing:
- panel editor focus now lands sooner after transitions
- search focus uses a task-based handoff instead of manual
DispatchQueue.main.async
-
Strengthened visual grouping for note colors:
- switched to Apple system color families
- added a visible leading accent rail on note rows
- added stronger tinted row/editor surfaces and clearer color chips
-
Smoothed panel motion and chrome:
- replaced heavier slide transitions with lighter fade/scale transitions
- reduced oversized shadows and improved surface consistency
- flattened the top action controls toward a more native toolbar-like shape language
- reduced row-hover scale/shadow weight for better scroll smoothness
- slightly reduced the panel's visual top-weight
-
Unified top-bar controls more strictly around macOS toolbar patterns:
- editor header now uses grouped symbol controls rather than a wrapped text pill for opening a new window
- note-list header now uses a grouped utility toolbar plus one prominent primary action
- compact fallback layouts now activate earlier through
ViewThatFitsto avoid crushed controls on narrower widths
-
Refined visual clarity:
- replaced the blurred menu bar symbol approach with a simpler custom template glyph:
- top menu-bar strip
- clearer note-card silhouette
- added per-mode hints for Markdown controls so icon-only affordances stay understandable
- replaced the blurred menu bar symbol approach with a simpler custom template glyph:
-
Refined the settings window presentation:
- calmer grouped background
- section headings now live inside their cards
- row alignment and inset cards are more consistent
- wide rows now gracefully collapse into stacked rows on narrower settings widths
- storage settings now include a lightweight space-analysis panel with:
- refresh on demand
- Finder reveal shortcut
- explicit separation between local storage and external file references
-
Reduced one app-side source of layout recursion risk:
- the main panel now compares content size instead of frame size before calling
setContentSize - this avoids an unnecessary resize pass on every open and should reduce the reported
layoutSubtreeIfNeededwarning frequency
- the main panel now compares content size instead of frame size before calling
-
Reworked menu-bar presentation stability:
- status-item primary actions now fire on mouse-down for a snappier, more reliable open
- the main panel now uses explicit outside-click and app-deactivation dismissal monitors instead of hiding on every key-window transition
- panel presentation now reactivates the app first, uses popup-menu window level, and no longer depends on the noisier transient/deactivate behavior
-
Refined first-run onboarding:
- removed the eager auto-popup welcome window on launch
- first-time onboarding now appears on the first primary status-item interaction instead of stealing focus during startup
- the welcome screen now includes clearer three-step Accessibility guidance plus direct actions for:
- opening the right System Settings page
- revealing the current app in Finder
- copying the exact running app path
-
Tightened permission and clipboard robustness:
- settings now expose
Copy App Pathbeside the existing Accessibility setup actions - clipboard import now reads file URLs through explicit class-constrained pasteboard APIs
- quick-access auto-paste keeps a slightly longer handoff delay before posting
Command-V
- settings now expose
-
Reduced settings-window jank:
- replaced the main settings
LazyVStackwith a stableVStackto avoid lazy creation churn during fast scrolls - lightened card fills/strokes to reduce compositing cost while keeping the grouped macOS look
- replaced the main settings
-
Refined panel row hierarchy and hover clarity:
- note rows now keep default surfaces quieter and reserve lift/shadow for hover/selection states
- hover emphasis now comes from clearer edge contrast, subtle accent glazing, and a slight raised offset instead of a washed-out all-white fill
- non-hover rows no longer carry continuous shadows, which should reduce scroll cost in longer lists
- toolbar controls and metadata chips were nudged toward the same calmer contrast system for a more unified panel chrome
- Apple Human Interface Guidelines:
https://developer.apple.com/design/human-interface-guidelines/the-menu-barhttps://developer.apple.com/design/human-interface-guidelines/search-fieldshttps://developer.apple.com/design/human-interface-guidelines/toolbarshttps://developer.apple.com/design/human-interface-guidelines/alertshttps://developer.apple.com/design/human-interface-guidelines/helping-peoplehttps://developer.apple.com/design/human-interface-guidelines/colorhttps://developer.apple.com/design/human-interface-guidelines/motionhttps://developer.apple.com/design/human-interface-guidelines/iconshttps://developer.apple.com/documentation/appkit/nspasteboardhttps://developer.apple.com/documentation/pdfkit/pdfviewhttps://developer.apple.com/documentation/applicationservices/1462083-axisprocesstrustedwithoptionshttps://developer.apple.com/documentation/coregraphics/cgevent
- Product-quality reference surfaces:
https://maccy.app/https://pasteapp.io/https://dropoverapp.com/https://www.craft.do/
- Finish store-facing assets:
- final screenshots
- final icon polish if needed
- final review-note wording after one more install-state pass
- Harden distribution:
- signing and archive workflow with the real Apple team
- notarized DMG pipeline for direct-download releases
/Applicationsinstall-state QA- verify the new in-app uninstall flow from an installed release build, not only from Xcode
- launch-at-login verification in signed builds
- App Store Connect record creation and first upload
- Refine premium UX only where real testing justifies it:
- real-device testing for IME composition, first-click reliability, and long-note editing smoothness
- final spacing and animation pass after the new settings layout
- empty-state and onboarding wording
- better detached-window restoration polish if needed after user testing
- Evaluate near-V1 additions only if they improve commercial viability:
- keyboard shortcuts / command palette
- richer search and filtering
- Close release engineering validation:
- signed build / archive verification
- auto-paste permission retest outside Xcode
- final release assessment closure against
docs/release-assessment.zh-Hans.md
- Topleaf now has a settings-driven backup/export-import flow
- Archive format:
- JSON
- notes and categories serialized directly
- readable attachments embedded as base64 payloads
- Restore semantics:
- prepare archive first
- stage attachments in a temporary directory
- replace local attachment storage
- restore categories and notes inside one repository transaction
- reload note state and storage analysis afterward
- Attachment policy:
- managed attachments restore as managed local files
- readable exported external-file attachments are imported into app-managed storage during restore
- unreadable exported external-file attachments fall back to their original absolute path only if that path still exists
- otherwise skipped attachments are counted and surfaced
- Automated coverage now includes backup/export-import round-trip validation
- Real signing, archive upload, and store distribution are not yet validated on your Apple account
- Launch-at-login is wired through
SMAppService, but signed-distribution QA is still pending - Search is currently plain substring matching across preview title and content
- Store screenshots and final submission data still need your manual completion
- Local UX still needs hands-on user testing after the latest smoothness pass
- Menu bar icon/app icon artwork is still provisional and can be refined further before release branding
- Auto-paste still needs live-user validation with real Accessibility permission outside the build/test harness
- Global category shortcut conflict detection is intentionally partial:
- Topleaf can detect duplicate in-app mappings
- Topleaf can warn on a small set of common macOS-reserved shortcuts
- public APIs still cannot enumerate every third-party global shortcut on the system
- Some debug-console messages still appear to come from macOS/Xcode system services during local debug runs and should be rechecked against a manually tested app session
- The
layoutSubtreeIfNeededwarning should be retested after the latest panel/onboarding presentation changes; if it still appears, another AppKit-hosting resize path remains to be isolated - The new About window still needs live visual QA for compact-width behavior and button density on smaller displays
- Release-readiness self-check still needs to be compared against a real signed
/Applicationsbuild to confirm the most useful wording and states - GitHub release automation now covers unsigned DMG packaging, but customer-grade direct distribution still needs:
- Developer ID signing
- notarization
- final install/uninstall QA outside the development environment
- In-app uninstall is now present, but signed sandboxed builds still need real-device validation for the exact behavior Apple permits in each distribution channel
- All UI should feel at home on macOS
- Keep the visual hierarchy calm and compact enough for daily utility use
- Prefer direct actions with contextual fallbacks over modal-heavy flows
- Any new feature must justify its weight against launch readiness