- Remove separate title input field - first line of content is now the title (standard Markdown behavior)
- Update note parsing to extract title from first line while keeping full content
- Move favorite star button to toolbar to save vertical space
- Fix image upload attachment directory path sanitization
- Add automatic background sync after save operations (create, update, move)
- Add rotating sync icon animation during sync operations
- Fix infinite sync loop by preventing sync complete callback from triggering another sync
- Bump IndexedDB version to 2 to clear old cached notes with stripped first lines
- Remove dialog permission errors in attachment upload (use console.log and alert instead)
- Add detailed debug logging for attachment upload troubleshooting
Major Changes:
- Switch from Nextcloud Notes API to direct WebDAV file access
- Notes stored as .txt files with filename-based IDs for reliability
- Implement safer sync strategy without clearNotes() to prevent data loss
- Add ETag-based conflict detection for concurrent edits
- Add category color sync to .category-colors.json on server
- Show neutral gray badges for categories without assigned colors
Technical Improvements:
- Replace numeric IDs with filename-based string IDs
- Update Note type to support both number and string IDs
- Implement WebDAV methods: fetchNotesWebDAV, createNoteWebDAV, updateNoteWebDAV, deleteNoteWebDAV
- Add CategoryColorsSync service for server synchronization
- Remove hash-based color fallback (only show colors when explicitly set)
Bug Fixes:
- Fix category badge rendering to show all categories
- Prevent note loss during sync operations
- Improve offline-first functionality with better merge strategy
- Add custom color picker for categories (10 pastel colors)
- Store category colors in localStorage
- Add real-time color updates across components using custom events
- Change folder icons to filled/solid style for better visibility
- Use vibrant darker shades for folder icon colors
- Add 'Remove Color' option to reset category to default
- Add color indicator dots (replaced with filled icons)
- Improve hash distribution using FNV-1a algorithm for auto-assigned colors
- Expand auto-assigned color palette from 10 to 20 colors
- Add double-click to rename categories (deprecated in favor of pencil icon)
- Add pencil icon on hover for intuitive category renaming
- Click pencil icon to enter inline rename mode
- Show helpful hint (Enter to save, Esc to cancel)
- Update all notes with old category name to new name
- Sync category changes to server
- Update selected category if currently viewing renamed category
- Bump version to 0.1.5
- Fix inline code padding to prevent overlap with line above
- Add proper heading styles (h1, h2, h3) with correct font sizes
- Add list styling (ul/ol) with proper bullets and numbering
- Embed images as data URLs in PDF export
- Fix list layout issues when images are present
- Add image styling to prevent layout interference
- Remove grey background from inline code for cleaner appearance
- Load TTF font files as base64 from local fonts directory
- Use pdf.addFileToVFS() and pdf.addFont() to register custom fonts
- Use pdf.setFont() to explicitly set preview font before rendering
- Support all preview fonts: Merriweather, Crimson Pro, Roboto Serif, Average
- Include italic variants for proper markdown italic rendering
- Embed Source Code Pro for code blocks
- Maintains efficient file size (~120KB increase vs 18MB with html2canvas)
- Keeps proper margins, pagination, and page breaks
- Add back hidden file input element removed with Attach button
- InsertToolbar still uses file upload functionality
- Fixes TypeScript build error TS6133 (unused handleAttachmentUpload)
- Attachment upload still available via floating insert toolbar
- Add local font files to public/fonts directory
- Replace Google Fonts CDN with local @font-face declarations
- Include both regular and italic variants for preview fonts
- Remove unused editor italic fonts to reduce bundle size
- App now fully functional offline without external dependencies
- Total font bundle: ~22.8 MB (10 font files)
- Remove confusing attachment upload button from header
- Simplify UI by keeping only category selector and preview toggle
- Attachment functionality removed from this section
- Add color-coded category badges with consistent pastel colors
- Fix scroll jump issue when editing at bottom of note
- Add localStorage persistence for notes list width
- Prevent notes list from shrinking with flex-shrink-0
- Preserve cursor and scroll position during textarea resize
- Add IndexedDB storage layer for notes (src/db/localDB.ts)
- Implement sync manager with queue and conflict resolution (src/services/syncManager.ts)
- Add online/offline detection hook (src/hooks/useOnlineStatus.ts)
- Load notes from local storage immediately on app startup
- Add sync status UI indicators (offline badge, pending count)
- Auto-sync every 5 minutes when online
- Queue operations when offline, sync when connection restored
- Fix note content update when synced from server while viewing
- Retry failed sync operations up to 5 times
- Temporary IDs for offline-created notes
- Settings panel in categories sidebar now collapses/expands with toggle button
- Settings collapsed by default to save space
- Notes list column now resizable with drag handle (240px-600px range)
- Improved UI flexibility and space management
- Fixed race condition where image processing ran before localContent updated
- Added synchronization guard to prevent processing stale content
- Added comprehensive logging for debugging note switches
- Bumped version to 0.1.1
A cross-platform desktop application for Nextcloud Notes built with Tauri, React, and TypeScript.
Features:
- Full Nextcloud Notes integration with real-time sync
- Rich markdown editor with live preview
- Category management and organization
- Image and attachment support
- Customizable fonts and UI themes
- Focus mode for distraction-free writing
- Floating toolbar for quick formatting
- PDF export functionality
- Offline mode support
Tech Stack:
- Tauri (Rust backend)
- React + TypeScript
- TailwindCSS for styling
- Vite for build tooling
- Markdown-it for rendering
- Add uploadAttachment method to NextcloudAPI (WebDAV PUT to .attachments directory)
- Add InsertToolbar component that appears on cursor placement in editor
- InsertToolbar provides quick access to insert links (with modal) and files
- Add Attach button to main toolbar as alternative upload method
- Insert markdown references at cursor position after upload
- Fetch attachments via WebDAV using Tauri HTTP plugin (bypasses CORS)
- Parse markdown for image references and convert to base64 data URLs
- In-memory cache to avoid re-fetching images
- Loading indicator while images load
- Register tauri-plugin-http in Rust builder
- Add HTTP permissions in capabilities
- Added Google Fonts: Source Code Pro, Roboto Mono, Inconsolata (editor)
and Merriweather, Crimson Pro, Roboto Serif, Average (preview)
- Font face and size selectors in Categories sidebar with polished UI
- Editor font applied to markdown textarea
- Preview font applied to preview mode and PDF export
- Code blocks always render in monospace
- Settings persist in localStorage
- Fixed textarea height recalculation when switching from preview to edit
Categories sidebar:
- Collapsible first column with category management
- Create new categories directly from sidebar
- Thin tab when collapsed
- Moved user info, logout, and theme selector here
Note editor redesign:
- Clean toolbar with pill-style buttons
- Category dropdown with folder icon
- Preview toggle in toolbar
- Streamlined action buttons
Floating formatting toolbar:
- Appears on text selection
- Bold, italic, strikethrough, code, code block, quote, lists, link, headings
- Active state highlighting for applied formats
- Toggle behavior removes formatting if already applied
Focus mode:
- Hides sidebars for distraction-free writing
- Content centered with max-width
- Escape key to exit
- Scrolling works from anywhere in viewport
- Increased editor padding from 6 to 8 for better spacing
- Simplified preview generation to show first 100 characters
- Remove markdown syntax (#, *, `) from note previews for cleaner display
- Replaced multi-line filtering logic with direct substring approach
- Centered note title in PDF exports for better visual balance
- Increased inline code font size from 0.9em to 1.1em for better readability
- Removed paragraph margins inside list items to fix spacing issues
- Removed html2canvas import that was causing TypeScript error
- html2canvas is no longer needed since we switched to jsPDF's html() method
- Fixes build error: TS6133 'html2canvas' is declared but never read
- Reordered jsPDF html() options for clarity
- Added autoPaging: 'text' for better page break handling
- Adjusted windowWidth to 650px for better content scaling
- Maintains 20mm margins on all sides
- Content width set to 170mm (210mm A4 - 40mm margins)
- Should produce more balanced left/right margins
- Removed complex manual page-by-page rendering logic
- Using jsPDF's built-in html() method instead (like dompdf does)
- Handles pagination automatically with proper page breaks
- Set 20mm margins on all sides via margin parameter
- Content width set to 170mm (210mm - 40mm margins)
- Much simpler and more reliable approach
- Leverages jsPDF's native HTML rendering engine
- Rewrote PDF export to render content page-by-page instead of as one image
- Calculate total content height and number of pages needed
- Create separate canvas for each page with proper dimensions
- Use overflow:hidden wrapper to show only one page's worth of content at a time
- Position content with negative top offset for each subsequent page
- Each page gets proper 20mm margins on all sides
- Fixes issue where content flowed continuously across pages
- Bottom margins now properly respected on every page
- Installed @tauri-apps/plugin-dialog for native dialogs
- Added tauri-plugin-dialog to Rust dependencies
- Registered dialog plugin in Tauri app initialization
- Replaced web alert() with Tauri message() dialog
- Success dialog shows filename and download location
- Error dialog shows if export fails
- Added 20mm margins on all sides of PDF pages
- Content width adjusted to 170mm (210mm - 40mm margins)
- Multi-page support respects margins on all pages
- Native dialogs work properly in Tauri app
- Fixed multi-page PDF generation - now properly splits long documents across pages
- Added isExportingPDF state for loading feedback
- Replaced generic download icon with document/PDF icon
- Button shows spinning loader during PDF generation
- Button changes to blue background while exporting
- Added success alert with filename and download location
- Button disabled during export to prevent multiple clicks
- Improved visual feedback throughout export process
- Installed jsPDF and html2canvas libraries
- Implemented handleExportPDF function to convert note to PDF
- Creates temporary styled container with title and content
- Uses html2canvas to render content as image
- Generates A4 format PDF with proper formatting
- Added export button (download icon) in note header
- Button positioned between discard and favorite buttons
- PDF filename uses note title
- Includes error handling with user feedback
- Prevent delete button from working when there are unsaved changes on a different note
- Delete button now checks hasUnsavedChanges before allowing deletion
- Only the currently selected note can be deleted when it has unsaved changes
- Prevents accidental deletion of other notes when locked
- Added handleDiscard function to reload original note content
- New discard button appears next to save button when there are unsaved changes
- Button uses X icon and gray styling to distinguish from save
- Clicking discard reloads the original note title and content
- Resets hasUnsavedChanges to false, allowing note switching again
- Provides way to abandon changes without saving
- Added hasUnsavedChanges state tracking in App.tsx
- NoteEditor now notifies parent via onUnsavedChanges callback
- NotesList receives hasUnsavedChanges prop
- Clicking on other notes is prevented when current note has unsaved changes
- Visual feedback: other notes become semi-transparent with cursor-not-allowed
- Tooltip shows 'Save current note before switching' on disabled notes
- Much simpler and more reliable than trying to auto-save on switch
- Added loadNewNote helper function to encapsulate note loading logic
- Check for unsaved changes when switching notes
- Save previous note if it has unsaved changes
- Add 100ms delay before loading new note to ensure save completes
- Prevents data loss when switching from unsaved note to another note
- Fixes bug where new note content would overwrite unsaved changes
- Changed productName from 'nextcloud-notes-tauri' to 'Nextcloud Notes'
- Updated identifier to 'com.davidrelich.nextcloud-notes'
- App will now show as 'Nextcloud Notes' in macOS Applications
- DMG and .app bundle will use proper name
- Changed disabled save button background from light grey to dark grey in dark mode
- Changed disabled save button text from grey-400 to grey-500 in dark mode
- Button now blends better with dark mode design
- No longer draws unwanted attention when disabled
- Shows 'Click again to delete' text when delete button is clicked once
- Text appears next to the red delete button in confirmation state
- Makes the double-click deletion flow much more intuitive
- Button also stays visible (opacity-100) during confirmation state
- Text styled in red to match the delete action