Files
Domipoke 955801c666 noctalia
2026-06-25 19:58:23 +02:00

9.0 KiB

Clipper Plugin - Changelog

Version 2.0.0 (2026-02-05)

🎯 Major Changes

New Feature: Add Selection to NoteCard

  • New IPC command: addSelectionToNoteCard
  • Captures selected text and presents context menu to add to existing notes or create new note
  • Text is automatically formatted as bullet points with "- " prefix
  • Integrated with Hyprland keybind: Super+V, X (chord)

Translation System Overhaul

  • Migrated from I18n.tr() to pluginApi?.tr() across all files
  • Added comprehensive i18n/en.json with 28 toast message keys
  • All user-facing strings now use translation system with fallbacks
  • Translation key structure: component.key (e.g., toast.note-created)

Architecture Improvements

  • Fixed IPC handlers to use pluginApi.withCurrentScreen() instead of direct Quickshell.screens[0] access
  • Added proper Component.onDestruction cleanup for 6 data structures (pinnedItems, noteCards, items, firstSeenById, imageCache, imageCacheOrder)
  • Memory leak prevention with proper process termination
  • Unified translation syntax: pluginApi?.tr("key") || "fallback"

📁 New Files

  1. NoteCardSelector.qml (173 lines)

    • Fullscreen overlay for note selection menu
    • Synchronously loads notecards from files
    • Shows "Create New Note" + list of existing notes
    • Mouse-position-aware context menu
    • ESC to cancel, click outside to close
  2. NoteCard.qml (~300 lines)

    • Updated visual style to match ClipboardCard
    • Icon + title left-aligned (not centered)
    • Transparent buttons without background
    • Increased font sizes (13-14px)
    • Auto-height expansion based on content
    • Drag handle on icon only (24px width)
    • All corners rounded on main card
    • Only top corners rounded on header
  3. NoteCardsPanel.qml (updated)

    • Background click-to-close functionality
    • Controls moved to top-left corner
    • Note counter and add button repositioned
    • Starting Y position increased to 80px to avoid control overlap

🔧 Files Modified

Main.qml (+250 lines, massive refactoring)

New IPC Handlers:

  • addSelectionToNoteCard() - Main entry point for feature
  • Uses same pattern as addSelectionToTodo() for consistency

New Functions:

  • getSelectionAndShowNoteSelector() - Triggers selection capture
  • showNoteCardSelector(text) - Displays note selection menu
  • handleNoteCardSelected(noteId, noteTitle) - Handles existing note selection
  • handleCreateNewNoteFromSelection() - Creates new note with bullet text
  • appendTextToNoteCard(noteId, text) - Adds bullet point to existing note

New Process:

  • getSelectionForNoteSelectorProcess - Captures primary selection via wl-paste
  • StdioCollector: noteSelectionStdout
  • Calls showNoteCardSelector() on successful capture

New Variants:

  • NoteCardSelector instances for each screen
  • Registered as noteCardSelector property
  • Connected to signal handlers for note selection/creation

New Properties:

  • noteCardSelector: null - Reference to selector instance
  • pendingNoteCardText: "" - Stores captured selection

Translation Updates:

  • All 28 Toast messages now use pluginApi?.tr()
  • String interpolation for dynamic values ({max}, {fileName}, {count})
  • Consistent error handling with translated messages

Bug Fixes:

  • Fixed createNoteCard() to call saveNoteCard() after creation
  • Removed duplicate saveNoteCard(newNote) calls from wrong functions
  • Fixed Component.onDestruction syntax error (duplicate })

i18n/en.json (+30 keys)

New Toast Section:

"toast": {
  "invalid-clipboard-item": "Invalid clipboard item",
  "max-pinned-items": "Maximum {max} pinned items reached",
  "note-created": "Note created",
  "note-not-found": "Note not found",
  "text-added-to-note": "Text added to note",
  "could-not-open-note-selector": "Could not open note selector",
  // ... 22 more keys
}

NoteCard.qml (visual redesign)

  • Header layout changed from centered to left-aligned
  • Icon (note) + title in RowLayout
  • Drag handle isolated to icon Item (24px width)
  • Separate MouseArea for title focus
  • Transparent button styling: colorBg: "transparent"
  • Font changes: removed bold, increased size to 14px
  • Radius system:
    • Main card: radius: Style.radiusM (all corners)
    • Header: topLeftRadius/topRightRadius: Style.radiusM, bottom: 0
  • Auto-height expansion via ScrollView content measurement
  • Size changed: 300x180 → 350x280px
  • Title input wider, better usability

NoteCardsPanel.qml

  • Background MouseArea with z: -1 for click-to-close
  • Controls repositioned to anchors.top + anchors.left
  • Note counter + add button in top-left corner
  • 16px margins from edges

ClipboardCard.qml

  • Applied same radius pattern as NoteCard
  • Main card: all corners rounded
  • Header: top corners only

BarWidget.qml

  • Migrated I18n.tr()pluginApi?.tr()
  • Keys: bar.tooltip, context.toggle, context.settings

Settings.qml

  • Already had full translation coverage
  • Verified all labels use pluginApi?.tr()

🎨 UI/UX Changes

NoteCard Visual Updates:

  • More modern, cleaner look matching ClipboardCard
  • Better readability with larger fonts
  • Improved drag interaction (icon-only handle)
  • Responsive to global radius settings (Style.radiusM)
  • Auto-expands height based on content

NoteCardsPanel Improvements:

  • Better spatial organization (controls top-left)
  • No accidental close when clicking on notes
  • Clear visual hierarchy

Context Menu for Note Selection:

  • Appears at cursor position
  • Smooth 150ms delay for compositor
  • First option always "Create New Note"
  • Separator before existing notes
  • Note icons for visual distinction

⚙️ Technical Improvements

Memory Management:

  • Cleanup of 6 data structures in Component.onDestruction
  • Process termination for getSelectionForNoteSelectorProcess
  • Proper array clearing: items = [], imageCache = {}

Code Quality:

  • Consistent translation syntax across codebase
  • No hardcoded user-facing strings
  • Proper null-safe operators: pluginApi?.tr()
  • Immutable array updates maintained

IPC Architecture:

  • Correct use of pluginApi.withCurrentScreen()
  • No direct Quickshell.screens access in IPC handlers
  • Consistent pattern with existing addSelectionToTodo

🐛 Bug Fixes

  1. Syntax Errors:

    • Fixed duplicate } in Component.onDestruction
    • Removed extra closing braces in function declarations
    • Fixed missing } catch(e) { block in loadNoteCardsProc
  2. Runtime Errors:

    • Fixed ReferenceError: newNote is not defined by removing invalid saveNoteCard(newNote) calls from functions that don't have access to newNote
    • Only createNoteCard() calls saveNoteCard(newNote) now
  3. Functional Issues:

    • Fixed note selector not showing existing notes (timing issue with async loading)
    • Fixed "Create New Note" not working (signal connection verified)
    • Fixed notes not being saved to files (added saveNoteCard() call)

📝 Usage Examples

IPC Commands:

# Add selected text to note via keybind
qs -c noctalia-shell ipc call plugin:clipper addSelectionToNoteCard

# Or with dev repo
qs -c ~/dev/repo/noctalia ipc call plugin:clipper addSelectionToNoteCard

Hyprland Keybind (chord):

# In ~/.config/hypr/keybind.conf
binds = SUPER_L, V&C, exec, qs -c ~/dev/repo/noctalia ipc call plugin:clipper addSelectionToTodo
binds = SUPER_L, V&X, exec, qs -c ~/dev/repo/noctalia ipc call plugin:clipper addSelectionToNoteCard

User Flow:

  1. Select text anywhere
  2. Press Super+V (opens chord mode)
  3. Press X (triggers addSelectionToNoteCard)
  4. Context menu appears at cursor
  5. Click "Create New Note" or select existing note
  6. Text is added as bullet point: - selected text

📊 Statistics

Lines Changed:

  • Main.qml: +250 lines
  • NoteCard.qml: ~300 lines (redesigned)
  • NoteCardSelector.qml: +173 lines (new)
  • NoteCardsPanel.qml: +50 lines
  • i18n/en.json: +30 keys
  • Total: ~800 lines added/modified

Files:

  • New: 1 file (NoteCardSelector.qml)
  • Modified: 7 files
  • Total: 8 files changed

Translation Coverage:

  • 28 new toast message keys
  • 100% coverage for user-facing strings
  • All components use pluginApi?.tr()

🔄 Breaking Changes

Translation System:

  • Old: I18n.tr("clipboard.key", "Fallback")
  • New: pluginApi?.tr("component.key") || "Fallback"
  • All plugins must update if they were using I18n

IPC Handlers:

  • Now use pluginApi.withCurrentScreen() instead of Quickshell.screens[0]
  • More robust multi-screen support

🚀 Next Steps (Future Enhancements)

  1. i18n Completion:

    • Translate en.json to all other language files (de, es, fr, etc.)
    • Maintain identical structure across all languages
  2. Feature Enhancements:

    • Resizable note cards
    • Rich text formatting
    • Note categories/tags
    • Search functionality
  3. Performance:

    • Lazy loading for large note collections
    • Virtual scrolling if >20 notes
  4. Integration:

    • Share notes between devices
    • Sync with cloud services

Version: 2.0.0
Date: 2026-02-05
Author: Development Team
Reviewed by: Code Review (QML-code-reviewer.md)