Three components had duplicate date formatting functions. Extract
formatDateChip (for detail/input views with optional time) and
formatDateLabel (for compact list items) to a shared dateFormat module.
https://claude.ai/code/session_013ooJht2HrZUTXgNJFU79cV
- Fix debouncedSave in TaskDetailView losing edits when title and
description are changed within 400ms (shared timer only saved the
last-changed field)
- Return errors from Tauri commands when workspace ID doesn't exist
instead of silently succeeding (set_webdav_config, set_workspace_theme,
set_sync_interval, set_sync_interval_unfocused)
- Remove duplicate atomic_write_bytes in google_tasks.rs; reuse
pub(crate) atomic_write from storage.rs
- Fix failing test using wrong frontmatter field name (due → date)
- Add Audit.md log
https://claude.ai/code/session_0186pnnUJxj2uv1KhHjWoAGA
- Renamed `due_date` field on Task struct to `date` (Rust, TypeScript, all usages)
- Renamed `group_by_due_date` field on TaskList/ListMetadata to `group_by_date`
- Renamed `set_group_by_due_date`/`get_group_by_due_date` methods to `set_group_by_date`/`get_group_by_date` in repository, Tauri commands, and JS store
- Renamed `with_due_date()` builder method to `with_date()`
- Renamed `parse_due_date` CLI function to `parse_date`
- Updated UI text "Group by due date" → "Group by date" in TasksScreen.svelte kebab menu
- Renamed JS variables `dueDate`/`dueDateHasTime` → `date`/`dateHasTime` in NewTaskInput.svelte
- Updated all test names and assertions across models.rs and repository.rs
- Updated CLAUDE.md documentation to use "date" terminology consistently
Close kebab menu when toggling subtasks
When toggling the "show subtasks" option from the main panel kebab menu,
the menu remained open which could obscure UI and lead to unexpected
interactions. Ensure that opening/closing the subtasks list also closes
the kebab (showListMenu = false) so the menu is dismissed when the user
chooses to view subtasks.
can we animate opening and closing of the kebab menus? Also, lets move the "NO DATE" section when selecting Group By Date to the top of the list before OVERDUE
- app.css: added CSS @starting-style + display transition on .dropdown-menu for open/close scale+fade animation
- app.svelte.ts: moved "No Date" group to the top (before "Overdue") in groupedPendingTasks
The kebab menu and docs referred to a task "due date" but the field was
just a date; this change renames due_date/group_by_due_date and related
identifiers to date/group_by_date across Rust, TypeScript, Svelte, CLI,
docs and tests to keep terminology consistent. Updates include
API/command names, storage/models, repository methods, UI text, JS
variables and builder/parse functions so code, tests and documentation
all use "date" semantics.
Preserve old "group_by_due_date" field name
Add serde alias to ListMetadata.group_by_date so older .listdata.json
files that used the previous field name (group_by_due_date) can still be
deserialized correctly. This fixes serialization/deserialization issues
encountered at /home/trztn/Documents/Onyx and
/var/home/trztn/Nextcloud/Onyx.
the frontmatter due should be date... I don't want due anywhere
- Renamed `TaskFrontmatter.due` → `TaskFrontmatter.date`; YAML key on disk is now `date:` instead of `due:`
- Added `#[serde(alias = "due")]` so existing task files with `due:` frontmatter still deserialize correctly
- Updated google_tasks.rs to write `date:` instead of `due:` in generated YAML
- Renamed CLI `--due` flag to `--date`; updated function signature and display string "Due:" → "Date:"
Remove serde aliases and rename due→date
Drop backwards-compat aliases and update frontmatter/metadata to use the
canonical "date"/"group_by_date" fields. The aliases for
group_by_due_date and due were removed to avoid maintaining
backward-compatibility and to reflect the current schema. Updated
storage types to rename the fields and adjusted serialization attributes
so YAML/JSON frontmatter and .listdata.json files now use group_by_date
and date consistently.
When "show subtasks" is enabled, the UI could display both the parent
subtask and its counter, leading to redundant information. Hide the
subtask counter under a parent subtask when the parent itself is shown
to reduce visual clutter and avoid duplicate counts.
This change ensures a cleaner presentation of tasks and subtasks by
preventing the counter from appearing alongside the visible parent
subtask.
if I drag a task in this mode, I would love to be able to drag it anywhere and have the task update its date
- Added `date: Date | null` to TaskGroup (null = Overdue or No Date, Date = the group's calendar day)
- Cross-group drops now update the task's due_date to the target group's date; preserves time-of-day when has_time is set; clears due_date when dropping into No Date
- Dropping INTO Overdue is still blocked (it's a computed group); dragging OUT of Overdue to any other group works
- Within-group drops still just reorder
Close open submenus when clicking outside
When submenu elements (like the kebab menu or workspace picker) were
open, clicking elsewhere in the app did not close them and allowed
interacting with underlying UI. This change adds a full-screen invisible
overlay element whenever either menu is open that captures outside
clicks and closes the menus, and removes the previous window-level
mousedown handler and related element bindings. This ensures that
clicking outside a submenu only closes it and prevents accidental
interactions with other parts of the app.
Prevent task clicks when closing dropdown menus
When the list menu or workspace picker is open, clicking outside should
close the menu but not also trigger underlying task click handlers. Add
a mouse down handler that closes dropdowns when clicking outside and a
capture-phase click handler that swallows the click immediately after a
menu close to avoid propagation to task elements. This avoids accidental
task activation right after closing a menu.
Prevent clicks reaching background when menus open
Stop clicks on the main task area from interacting with underlying
elements when the workspace picker or list menu are open. Previously a
global mousedown/click handler attempted to close menus and prevent a
single stray click from propagating; this change replaces that logic by
adding overlay divs inside the drawer and task list panels that capture
clicks and close the respective menus. This simplifies interaction
handling and fixes a bug where clicking menu items also triggered task
clicks.
the kebab menu calls the date on tasks a due date, but it's not a due date... it's just a date. can we make sure the codebase, documentation and everything is consistent about this?
- Renamed `due_date` field on Task struct to `date` (Rust, TypeScript, all usages)
- Renamed `group_by_due_date` field on TaskList/ListMetadata to `group_by_date`
- Renamed `set_group_by_due_date`/`get_group_by_due_date` methods to `set_group_by_date`/`get_group_by_date` in repository, Tauri commands, and JS store
- Renamed `with_due_date()` builder method to `with_date()`
- Renamed `parse_due_date` CLI function to `parse_date`
- Updated UI text "Group by due date" → "Group by date" in TasksScreen.svelte kebab menu
- Renamed JS variables `dueDate`/`dueDateHasTime` → `date`/`dateHasTime` in NewTaskInput.svelte
- Updated all test names and assertions across models.rs and repository.rs
- Updated CLAUDE.md documentation to use "date" terminology consistently
Add grouping of pending tasks into Overdue/Today/Tomorrow/This
Week/Later/No Date buckets when the active list has group_by_due_date
enabled. This provides a grouped view in TasksScreen (section headers,
no drag-and-drop) and a new derived store groupedPendingTasks exported
from the app store to supply the UI. Dated groups are sorted by due_date
while the No Date group preserves the custom order.
Few changes: lets make the date chip red when in the overdue section. In all other sections, lets hide the date chip for individual tasks. Then, for the Later section, lets break that up into individual days.
- Replaced single "Later" group with per-day groups (e.g. "Mon, Apr 20"), each sorted by due_date
- Added `dateChipStyle` prop to TaskItem ("normal" | "overdue" | "hidden"), default "normal"
- Date chip is red (border-red-400 text-red-400) in "overdue" style, hidden in "hidden" style
- TasksScreen passes dateChipStyle="overdue" for Overdue group, "hidden" for all others
Fix date chips and include year in future group labels
Replace dynamic ternary class strings with explicit {#if} blocks for the
date chip so Tailwind v4's scanner picks up the classes and theme tokens
are respected. Use text-danger and border-danger for overdue chips and
proper border/token classes for non-overdue chips to fix the overdue
chip appearance and prevent chips from showing in sections that should
be hidden.
Also include the year in per-day group labels when the date is not in
the current year (e.g. "Mon, Apr 20, 2027") by passing the appropriate
Intl.DateTimeFormat options, so tasks scheduled in future years display
an unambiguous header.
yes (remove This Week, extend per-day grouping to everything beyond tomorrow)
- Removed "This Week" group entirely
- Everything beyond tomorrow now gets a per-day group label (same as what "Later" was doing), giving a consistent Overdue → Today → Tomorrow → [per-day] → No Date structure
Respect manual order within same-day groups
Ensure tasks that fall on the same day keep the user's manual ordering
by using a task_order index as a tiebreaker when sorting. Also add
drag-and-drop group tracking so drags and drops are confined to their
originating group and wire full DnD handlers into the grouped view.
- Use a taskOrderIndex map in sortByDue to break ties when due dates are equal so same-day tasks respect manual order.
- Add dragGroup state and record it on handleDragStart; ignore dragOver/drop events when the event group differs from the originating dragGroup to prevent cross-group drops.
- Reset dragGroup on drag end.
- Wrap grouped TaskItem entries with draggable divs and hook up dragstart/dragover/dragend/drop to match the flat view's DnD behavior.
Update drag-and-drop to set task due dates
Support dragging tasks between date-grouped columns by updating the
task's due_date to the target group's date (or clearing it when dropped
into No Date). Preserve the task's time-of-day when has_time is set,
block dropping into the computed Overdue group, and allow dragging out
of Overdue. Also add TaskGroup.date to the grouping data and expose a
showSubtaskCount prop and optional subtask rendering in the task list
UI.
fix null taskId error when reordering after cross-group drag
- Capture dragId and dragGroup into local variables at the top of handleDrop before any awaits — prevents the race where dragend fires during updateTask and nulls out dragId before reorderTask is called
Allow dragging tasks to update date groups
Add date handling to task groups so dragging a task into another group
updates its due_date. Introduce date: Date | null for TaskGroup (null
represents Overdue/No Date), update cross-group drops to set or clear a
task's due_date based on the target group while preserving time-of-day
for tasks with has_time, and keep within-group drops as reorders. Also
ensure Overdue remains a computed-only target (cannot drop into it)
while allowing dragging out.
Additionally, add GoogleTasks workspace support fields
(WorkspaceMode::GoogleTasks and an optional google_account) and include
the new field in WorkspaceConfig::new to initialize google_account to
None.
Replace the previous boolean systemDecorations with a windowDecorations
enum ("custom", "none", "system") to allow three distinct decoration
modes. Update UI to use a select control in Settings, adapt App.svelte
conditionals to check for the "custom" value when applying custom
borders/rounded styles, and rename localStorage key to persist the new
enum. Also ensure the native system decorations are enabled when the
setting is "system" and export the new setter name setWindowDecorations
in the store.
Enable setting window decorations
Add the "core🪟allow-set-decorations" capability to allow the app
to control window decorations (e.g., system titlebar). This fixes the
issue where the system titlebar was not working by permitting the code
to modify decoration state.
Also ensure the capability list remains properly comma-separated after
insertion.
Add outline support for borderless mode
Allow border outline in non-system decoration modes on Linux. The change
updates the condition for applying the linux-window-border class so the
outline is applied when window decorations are custom or any non-system
mode, enabling an outline for borderless windows while keeping
system-decorated windows unaffected.
Respect borderless mode: remove rounded corners
Remove rounded corners from popups and overlays when window decorations
are disabled. The App component now passes the windowDecorations state
into the root div via a data-decorations attribute, and the CSS adds a
rule that forces square corners for all elements under
[data-decorations="none"] to ensure borderless mode yields true square
UI without rounded popups/toasts.
Do not override button/input/select border-radius in borderless mode
Prevent borderless mode from removing rounded corners on interactive
form elements. The previous selector applied border-radius: 0 to all
descendants, unintentionally flattening buttons, inputs, and selects.
Restrict the rule so it excludes button, input, and select elements to
preserve their expected styling.
Strengthen dropdown drop-shadows
Make the kebab and other dropdown menu shadows more pronounced by
replacing the tailwind shadow-lg class with shadow-2xl across
TaskDetailView.svelte and TasksScreen.svelte. This improves visual
contrast and makes menus stand out more clearly against the background,
addressing the request to make the dropshadow on the kebab menus
stronger.
Use consistent menu shadow class
Replace multiple inline shadow utility classes with a shared
"menu-shadow" class for dropdown and context menus across
TaskDetailView, SettingsScreen, and TasksScreen. This unifies styling,
reduces duplication, and allows easier tweaks to the menu drop-shadow
(potentially addressing blurry rendering) by centralizing the shadow
definition.
Add subtle shadow for dropdown/kebab menus
Soften dropdown/kebab menu appearance by adding a subtle box-shadow
utility and a darker variant for dark mode. Also refine the borderless
mode rule to avoid overriding elements that use rounded-full classes so
those intentional circular controls keep their shape.
Make dropdown buttons square-cornered in borderless mode
Ensure dropdown menu buttons use square corners when decorations are
disabled. The CSS update adds a selector to force border-radius: 0 for
buttons inside .dropdown-menu under [data-decorations="none"]. Several
dropdown container divs across TaskDetailView, SettingsScreen,
TasksScreen, and related components are given a .dropdown-menu class so
the new rule applies consistently and makes dropdown buttons match the
rest of the borderless UI.
when workspace settings is up, can we make it so I can drag the header to move the app around?
- Added data-tauri-drag-region to the header and title in SettingsScreen.svelte so the settings header can be used to drag/move the window
<task-notification>
<task-id>bzp4p2vsp</task-id>
<summary>Monitor event: "Tauri rebuild — Finished or error"</summary>
<event>[Monitor timed out — re-arm if needed.]</event>
</task-notification>
Apply decorations-none class for borderless mode
Ensure the "decorations-none" CSS class is applied/removed on the
document root when window decorations are set to "none" so borderless
mode styles take effect. The CSS selector was also adjusted to
explicitly list rounded utility classes so the rule targets known
rounded elements while keeping dropdown-menu buttons included.
- Changed `fixed` to `absolute` positioning in NewTaskInput.svelte backdrop div so the overlay respects the app's visual container bounds on Linux (where a p-2 padded, rounded-xl container creates visual borders)
it looks mostly good now, except that when the toast slides up, it's causing the rest of the app content to jitter
- Added `overflow-hidden` to the outer wrapper div in NewTaskInput.svelte to contain the translate-y-full animation within its own layer and prevent repaint jitter on sibling content
when workspace settings is up, can we make it so I can drag the header to move the app around?
- Added data-tauri-drag-region to the header and title in SettingsScreen.svelte so the settings header can be used to drag/move the window
Add safe area padding to scrollable main content areas and
adjust drawer footer padding to prevent content from being
hidden behind notches and home indicators on mobile devices.
This ensures proper spacing on devices with safe area insets.
Add bottom padding to DateTimePicker component to prevent content
from being obscured by notches or home indicators on mobile devices.
Uses CSS max() function to ensure minimum 0.75rem spacing while
respecting device safe area insets.
Add content-start alignment and fixed 192px height to the
calendar grid to prevent layout shift when switching between
months with different numbers of weeks. This ensures consistent
spacing and prevents the calendar from changing size based on
the month being displayed.
Security:
- Fix path traversal via backslash bypass in sync validate_sync_path()
- Replace silent HTTP client fallback with proper error propagation
- Add 64KB YAML frontmatter size limit to prevent DoS via crafted files
Data integrity:
- Reorder delete operations: update metadata before removing files to
prevent orphaned metadata entries on crash
- Fix task deduplication to use file mtime as tiebreaker when versions
are equal, preventing non-deterministic data loss
- Add rollback on conflict recovery failure (remove orphaned duplicate
files when metadata update fails)
- Clean up temp files on atomic write rename failure
- Add file-based sync lock to prevent concurrent sync operations
- Use saturating_add for task version to prevent overflow
Error handling:
- Surface move_task rollback failures as structured errors instead of
silent warnings
- Log WebDAV parallel request failures instead of silently swallowing
- Emit watcher-error events to frontend instead of only printing to stderr
Frontend:
- Fix focus listener leak in auto-sync (clean up if stopAutoSync called
while promise pending)
- Add prefers-reduced-motion CSS media query for accessibility
- Add ARIA labels, roles, and keyboard handlers to TaskItem, BottomSheet,
and ConfirmDialog components
- Replace BottomSheet children: any with Snippet type
https://claude.ai/code/session_01AJoK28N4vqLqzskq6ybGri
Remove created_at/updated_at from Task struct and frontmatter. Add a
version counter (u64) that increments on every write, defaults to 1 for
old files. list_tasks now groups by UUID and auto-deletes stale
duplicates (keeping highest version), preventing sync-induced dupes from
surfacing in the UI. has_time and parent are omitted from frontmatter
when false/null.
Update CLI, Tauri frontend types, and Svelte components to match.
Add toggling guard to TaskItem preventing double-toggle from rapid clicks
or swipes. Fix debounced save in TaskDetailView to read task at timeout
time instead of capturing a stale snapshot at call time. Remove unused
_unlistenFs variable. Surface reorder_task and watch_workspace errors
instead of silently swallowing them.
Fix nested interactive elements in TaskItem (button inside button) by
restructuring as div + button with aria-label. Replace native confirm()
with ConfirmDialog for workspace removal. Store fs-changed event unlisten
function for cleanup. Log file watcher errors instead of swallowing them.
Fix var usage to const. Add Firefox scrollbar-width support.
- Remove subtask expand/collapse foldout from main task list
- Add three-panel slide navigation (task list → task detail → subtask detail) via taskStack
- Create ConfirmDialog component replacing native confirm() dialogs
- Cascade delete: deleting a task with subtasks warns and deletes all children
- Subtask detail view: no nested subtasks, collapsible completed section, inline add at top
- Redesign Move To as inline list in kebab menu (no overflow submenu)
- Main panel header: list name + kebab below divider (matching task detail layout)
- Move list management kebab from drawer to main panel; drawer shows chevrons
- Add Delete Completed to both main panel and subtask kebab menus
- Fix debouncedSave stale reference by snapshotting task before timer
- New subtasks prepend to top of list
Wire up the existing parent_id data model into a full subtask UI:
- Backend: create_task accepts parent_id, cascade delete/toggle for subtasks
- Store: subtask-aware derived state (root tasks only in pending/completed),
childrenMap for O(1) subtask lookup, createTask accepts parentId
- TaskItem: depth-based indentation, subtask completion counter badge
- TasksScreen: expand/collapse chevron for parent tasks, indented subtask
rendering with left border, subtasks shown under completed parents
- TaskDetailView: "Add subtask" inline input, subtask list with toggleable
checkboxes, parent task breadcrumb for subtasks
https://claude.ai/code/session_01XWcSekaCAJ7qnr4hN3tgL8
Previously clicking the clear-time button set includeTime to false and
also called done(), which closed the surrounding toast. This change
removes the done() call so clearing the time only clears the time input
state (includeTime = false) without dismissing the toast UI.
Users couldn't clear the time part of a task's due date because the
"clear time" button only toggled includeTime=false without signalling
the picker to finish. Call done() when clearing the time so the picker
closes/emits the updated value, ensuring the task's has_time state is
updated and the UI reflects a date-only value.
Replace the hours==0 && minutes==0 heuristic with an explicit has_time
bool field on Task. Existing files without the field deserialize as false
(date-only), preserving current behavior. Frontend components pass and
receive has_time through DateTimePicker's onchange callback.
- Standardize header height (h-11) across detail view and main panel
- Move kebab menu below header in task detail view
- Move workspace switcher to drawer header with window drag support
- Move settings button to drawer footer with label
- Add mark-as-completed/restore to kebab menu, remove bottom action bar
- Enlarge checkbox hit target without changing visual size
- Show checkmark animation before task collapse transition
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add load_credentials Tauri command and use it in triggerSync() instead
of passing empty username/password strings
- Replace raw __TAURI_INTERNALS__.invoke() with proper invoke import in
SettingsScreen
- Wrap window event listeners in $effect() with cleanup to prevent
memory leak on component remount
- Return created Task from createTask() and use it directly in
NewTaskInput instead of guessing from array index
- Add confirm() dialogs before deleting tasks, lists, and workspaces
Use the same visual structure as TaskDetailView: large bold title input,
description textarea with notes icon, and date/time row with
DateTimePicker. Uses fixed positioning with a combined backdrop wrapper
to avoid layout shifts and ensure proper slide-up animation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace inline task editing with a full-viewport detail panel that
slides in from the right. Includes editable title, description, custom
calendar-based date/time picker (bottom sheet), kebab menu with delete,
and mark complete/restore button. Simplify TaskItem to remove inline
editing and kebab menu, add chevron hint and onopen callback. Use list
icon for drawer toggle instead of back arrow.
- Remove Flutter app and egui placeholder crate, commit to Tauri as sole GUI
- Update PLAN.md to replace egui with Tauri across all phases (v4.0)
- Redesign task screen: sliding drawer for list picker, floating FAB for new tasks,
bottom sheet toast for task creation with title + description fields
- Add description support to create_task Tauri command
- Lighten dark theme to GNOME-style neutral grays, shift primary to cyan-blue
- Fix Wayland compatibility (dev port change)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>