Commit graph

292 commits

Author SHA1 Message Date
Claude
e2f0dd6925
feat(issue): clear the issue-updated badge when its toggle button is clicked
The accent-colored "issue updated" indicator could previously only be
cleared via the "mark as checked" button inside the issue-content panel,
which renders only once the issue data (re)loads. For Plainspace tasks —
and any provider whose remote issue is gone/unreachable — the data never
loads, so the badge had no way to be dismissed and stayed stuck forever.

Clicking the task's detail-panel toggle button while it shows the accent
update icon (i.e. issueWasUpdated) now also marks the issue update as read.
This is always available and does not depend on the issue data loading, so
the badge can never get stuck. The manual "mark as checked" button stays.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B9SCXSQvTq8TKUL7LabJQS
2026-06-20 00:39:15 +00:00
Symon Baikov
d0da0aea93
Codex/issue 8081 keep subtask input open (#8423)
* fix(tasks): keep subtask input open after add

* fix(tasks): keep subtask input open after add

* perf(tasks): avoid task row effect reactivity

* fix(tasks): address subtask input review

* feat(tasks): ease in the inline subtask input instead of popping

* fix(tasks): consume inline subtask-input request to prevent stale focus-steal

Address multi-review findings on the inline subtask input:

- The open request was held in a signal that was never cleared, so a task row re-created with the same id (e.g. navigating away from a project and back) re-ran its open effect on init and re-opened the input, stealing focus with no user action. Reset via consume() once the row acts on it.

- Drop the redundant requestId counter (a fresh request value already re-fires the effect); request payload is now just the parentId string.

- Add an aria-label to the input (placeholder is not an accessible name).

- _commit() returns void (its boolean result was unused).

* feat(tasks): animate the inline subtask input out and tighten its top gap

- Use the expandFade animation (enter + leave) so the input collapses out instead of vanishing. Caveat: when the input is the only thing in .sub-tasks (adding the first subtask, then cancelling without creating any), the enclosing @if collapses in the same tick and Angular skips the child leave animation, so it's instant in that one case.

- Reduce the input's top margin from --s-half (4px) to --s-quarter (2px).

* feat(tasks): refocus the task row when the subtask draft is cancelled with Escape

The inline subtask input's 'closed' output now reports why it closed ('escape' vs 'blur'). On Escape (a keyboard cancel) the host task calls focusSelf() so keyboard navigation continues from that row; on blur it doesn't, since focus already moved elsewhere. focusSelf() is a no-op on touch.

Covered by unit tests (reason emitted, host refocus only on escape) and an e2e assertion that the task row is focused after Escape.

* feat(tasks): return focus to the task the subtask draft was opened from

Escape previously refocused the parent row that hosts the input. Capture the originating task (which may be a subtask) when opening the draft — before focus moves into the input and the parent row claims focusedTaskId — and restore that on Escape. Falls back to the host row when no origin was captured; no-op on touch.

Focus-by-id prefers the last #t-<id> instance (the detail side-panel one) to match the existing inline-edit focus convention when a task renders twice.

Covered by unit tests and an e2e proving focus returns to the originating subtask, not its parent.

* test(tasks): update subtask e2e for the inline draft input flow

The add-subtask UX changed from 'press a -> empty subtask title focused for edit' to an inline draft input (type + Enter to commit, stays open for rapid entry). Update every e2e site that added subtasks via the old textarea selector:

- WorkViewPage.addSubTask helper: wait for .e2e-add-subtask-input, fill + Enter, then Escape to close the draft for a clean post-state (fixes simple-subtask, add-to-today, drag-task-into-subtask, finish-day-quick-history, and the sync specs that use the helper).

- add-subtask-with-detail-panel-open.spec.ts: assert the draft input opens focused from panel/main-list focus; rewrite the multi-subtask case to repeated Enter (the new rapid-entry path).

- supersync-archive-subtasks + supersync-lww-conflict: same inline-draft flow (not runnable in-sandbox; fixed by analogy).

Verified locally: detail-panel-open 3/3, simple-subtask, add-to-today 5/5, drag-into-subtask, finish-day-quick-history all green.

---------

Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
2026-06-18 17:58:45 +02:00
Johannes Millan
af3471a140 fix(tasks): render deadline time badge as HTML so AM/PM span styles instead of leaking text 2026-06-18 07:14:42 +02:00
Johannes Millan
0e04e8feaa
feat(tasks): checklist progress, bulk actions & notes editor UX (#8156)
* build: drop unused elevate.exe from Windows build #8135

elevate.exe is bundled by electron-builder's NSIS target solely so
electron-updater can apply privileged per-machine updates. We ship no
in-app auto-updater (electron-updater is not a dependency; the autoUpdater
block in electron/start-app.ts is commented out), so the binary is unused
dead weight and a frequent AV false-positive. Set packElevateHelper: false
to stop bundling it; safe because perMachine is not true.

* docs: flag task component (perf) and sync system (correctness) as high-risk areas

* feat(tasks): show checklist progress indicator on task cards

Derive checklist progress from a task's markdown checklist notes and surface
a compact "done/total" badge in the task controls. The badge switches to a
completed state when every item is checked and opens the notes panel on click,
making checklist progress visible at a glance without opening the task.

https://claude.ai/code/session_0131giFn7PwH5AFMUpSQXdU2

* feat(tasks): add checklist reorder and bulk actions in notes

Add drag-to-reorder for checklist items in the notes editor and a checklist
actions menu (Check all / Uncheck all / Clear completed), shown only when the
notes are recognized as a markdown checklist. All operations are backed by pure,
unit-tested helpers that manipulate the existing markdown notes string and emit
through the normal change flow, preserving interleaved prose lines.

https://claude.ai/code/session_0131giFn7PwH5AFMUpSQXdU2

* refactor(tasks): harden checklist reorder and add drop indicator

Review follow-ups for the checklist actions:
- guard moveChecklistItem against NaN/non-integer indices (a NaN drop index
  previously slipped past the range checks and corrupted ordering)
- show a drop-target highlight while dragging a checklist item
- drop redundant modelCopy.set (the model setter already syncs it)
- add component tests for bulk actions and the drag-and-drop flow

https://claude.ai/code/session_0131giFn7PwH5AFMUpSQXdU2

* refactor(tasks): remove checklist drag-to-reorder, refine card icon

Remove native drag-to-reorder for checklist items in the notes editor
(drag handlers, drop indicator, the moveChecklistItem helper, and the
related styles and tests). The checklist bulk-actions menu (check all /
uncheck all / clear completed) and the task-card progress badge are kept.

On the task card, the checklist progress badge now stands in for the plain
'chat' notes indicator: when a task has a checklist the redundant notes icon
is suppressed, and the badge itself yields to the close (X) button when the
detail panel is open, mirroring how the notes icon behaves.

* feat(tasks): replace unmodified default notes template on checklist toggle

When the notes field shows only the app's stock default template (and it
has not been edited), the checklist button now replaces that placeholder
with a fresh checklist instead of appending a checkbox below it. Edited
content and user notes are preserved and appended to as before.

Adds a `defaultText` input on inline-markdown so the task detail panel can
pass the (replaceable) stock template, guarded by isStockNotesTemplate so a
user-customized template is treated as real content.

* fix(tasks): indent list line on Tab regardless of cursor column

handleTabKey previously only indented when the cursor sat at line start or
at the end of an empty prefix, so pressing Tab mid-item moved focus out of
the editor instead of indenting. It now indents whenever the collapsed
cursor is on a list line, returning null only for multi-char selections or
non-list lines.

* feat(tasks): hint "Notes / Checklist" in empty notes header

When a task has no notes yet, the notes section header now reads
"Notes / Checklist" instead of "Notes", hinting that the section can hold
either a free-form note or a checklist. Plain notes still show "Notes" and
a recognized checklist still shows "Checklist".

* feat(tasks): limit checklist item click target to checkbox and text

Checklist item text was rendered as a bare text node inside the block-level
row, so clicking anywhere on the row (including empty space) toggled the
item. Wrap the text in a <span class="checkbox-label"> and only toggle when
the click lands on the checkbox icon or that label; clicks on the rest of
the row fall through to opening the editor. Cursor affordance is moved off
the row onto the checkbox and label accordingly.

* fix(tasks): map checklist toggle to the correct source line

_handleCheckboxClick mapped the Nth rendered checkbox to the Nth source line
matching `line.includes('- [')`, which also matches non-task lines such as
markdown link bullets (`- [text](url)`) or prose. That shifted the index so
clicking a checkbox could toggle the wrong line (often a no-op). Use the
anchored `isChecklistItemLine` predicate — the same one the bulk-action
helpers use — so source lines align with the rendered checkboxes. Applied to
both the inline editor and the fullscreen markdown dialog (duplicated logic).

* refactor(tasks): unify checklist predicate and dedupe toggle logic

Addresses multi-review feedback (W1/W3/S1):

- Single source of truth for "is a checklist line": isMarkdownChecklist,
  markdownToChecklist and getChecklistProgress now use the checklist-operations
  predicates instead of three divergent definitions. Tightened CHECKLIST_ITEM_RE
  to /^\s*- \[[ xX]\]/ so it matches exactly what marked renders (verified: marked
  treats - [ ]/- [x]/- [X] as tasks but NOT - []). This also fixes the badge not
  recognizing uppercase [X] checklists.
- Extracted toggleChecklistItemAtIndex() into checklist-operations and use it in
  both _handleCheckboxClick copies (inline editor + fullscreen dialog), removing
  the duplicated index-mapping + string-toggle. The helper flips only the
  checkbox marker (item text containing [ ] is safe) and handles [X] uncheck —
  both pre-existing bugs in the old inline toggle.
- getChecklistProgress counts in a single pass over the lines (no intermediate
  markdownToChecklist array / throwaway substring allocations) — it runs on the
  task-card hot path.

* fix(tasks): match checklist predicate exactly to marked's task rendering

Final review follow-up. The line predicate now requires "- [marker] <content>"
(marker box + whitespace + a non-space char), matching what marked actually
renders as a checkbox — verified against marked across 15 cases. Previously an
empty "- [ ] " placeholder line (or "- [x]a" with no space) was counted as an
item even though marked renders no checkbox for it, which could desync the
Nth-checkbox -> Nth-line mapping (e.g. "- [ ] \n- [x] real": marked shows 1
checkbox, predicate matched 2, so clicking the real item toggled the empty
line). Tightening CHECKLIST_ITEM_RE/CHECKED_ITEM_RE closes that gap and makes the
"in sync with marked" comment accurate.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-08 20:21:10 +02:00
Maikel Hajiabadi
313832cb72
feat(menu-tree): show parent folder context for projects/tags with ch… (#7988)
* feat(menu-tree): show parent folder context for projects/tags with chevron separators and globalized grid layout

* fix(menu-tree): collision-aware folder context disambiguation in project/tag menus

Replaces the grid-layout approach with a leaner inline implementation and
adds collision detection so folder hints only appear when two or more
projects (or tags) share the same title.

Key changes:
- MenuTreeService: build title-frequency maps from selectAllProjects /
  selectAllTags; include a folder path in projectFolderMap / tagFolderMap
  only when titleCount > 1; remove dead guards (select() never returns falsy)
- getFolderContext / isEmojiIcon: accept unknown instead of any
- Drop the custom-option-layout grid wrapper and extra .scss additions;
  use plain inline elements so Material menu item layout is untouched
- Templates (task context-menu, add-task-bar, add-task-bar-actions):
  show (folder) hint via @if (folderMap().get(id); as folder) on collision only
- Tests: add collision/non-collision cases to MenuTreeService.spec.ts;
  fix AddTaskBarActionsComponent mock Store to return of([]) so
  MenuTreeService toSignal calls do not crash

* refactor(ui): extract unified select-option-row component and cleanup global leaks

Centralizes the icon + title + folder context layout logic and styles into
a reusable SelectOptionRowComponent, resolving duplication and global CSS
leakage across several project/tag selection menus.

Key changes:
- New UI Component: Add SelectOptionRowComponent to handle grid-based
  option presentation (icon, checkbox, title, and folder subtitle).
- CSS Cleanup: Remove globally leaking ::ng-deep .mat-mdc-menu-panel
  overrides from component SCSS files; styles are now properly scoped
  via :has(select-option-row) within the new component.
- Layout Consolidation: Replace manual markup with the new component in
  TagToggleMenuList, AddTaskBarActions, Task, and TaskContextMenu.
- Mentions Improvement: Update ShortSyntaxTag to include IDs, enabling
  folder context hints within the task-bar mentions dropdown.
- Logic Cleanup: Remove redundant no-op '|| of([])' fallbacks in
  MenuTreeService.select() calls and fix lint errors (unused imports).

* fix(add-task-bar): render chrono suggestions plainly in mention list

* style(add-task-bar): remove broad global mention-menu rule

* fix(menu-tree): filter project and tag lists for folder map collisions

* fix: autocomplete tag visibility and scoped folder disambiguation

* fix: restore corrupted files and fix template errors in TaskContextMenuInnerComponent

* refactor(tasks): clean up unused injections and helper methods

* refactor(ui): make select-option-row purely presentational

* refactor(tasks): update select-option-row callers with explicit inputs

* refactor(menu-tree): dry folder map builders and replace magic string

* style(ui): move select-option-row global styles to _overwrite-material.scss

* test(menu-tree): add regression test for folder path map duplicates and refine select-option-row type contract
2026-06-05 14:08:28 +02:00
Maikel Hajiabadi
bb41a69c7a
feat: Fix visual inconsistencies in icons (#7989)
* feat(tasks): standardize symbols in add task bar autocomplete and chips

* feat(tasks,notes): standardize project icons in task and note context menus

* refactor(tasks): centralize mention icons and styling

- Move icon/color resolution logic into MentionConfigService with strict typing
- Implement shared mention list template in MentionListComponent for visual consistency
- Remove duplicated templates and styles from AddTaskBar and TaskTitle components
- Clean up duplicate imports in TaskComponent
- Add unit tests for resolved mention configuration

* refactor(tasks): remove unused DEFAULT_PROJECT_ICON from add-task-bar

* refactor(tasks): remove vestigial isProject property and assertion

* test(tasks): strengthen mentions integration tests with fallback assertions

* fix(mentions): override child icon and emoji colors on active row
2026-06-04 23:26:30 +02:00
Johannes Millan
0340ca3bf0 feat: improve task swipe menu appearance
- fix(planner): cancel drag-ready state when a planner task swipe starts
- fix(tasks): cancel drag-ready state when a task swipe starts
- fix(tasks): make mobile swipe-left menu affordance clearer (#7841)
2026-05-29 14:55:22 +02:00
Het Savani
b80e81f3e3
feat(tasks): auto add tasks with deadlines today to Today view (#7650)
* feat(tasks): auto add tasks with deadlines today to Today view

* fix(tasks): preserve schedule when completing tasks

* fix(tasks): cover scheduled completion edge cases

* chore(deps)(deps): bump cloudflare/wrangler-action from 3.15.0 to 4.0.0 (#7653)

Bumps [cloudflare/wrangler-action](https://github.com/cloudflare/wrangler-action) from 3.15.0 to 4.0.0.
- [Release notes](https://github.com/cloudflare/wrangler-action/releases)
- [Changelog](https://github.com/cloudflare/wrangler-action/blob/main/CHANGELOG.md)
- [Commits](9acf94ace1...ebbaa15849)

---
updated-dependencies:
- dependency-name: cloudflare/wrangler-action
  dependency-version: 4.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* chore(deps)(deps): bump the github-actions-minor group with 4 updates (#7652)

Bumps the github-actions-minor group with 4 updates: [step-security/harden-runner](https://github.com/step-security/harden-runner), [browser-actions/setup-chrome](https://github.com/browser-actions/setup-chrome), [anthropics/claude-code-action](https://github.com/anthropics/claude-code-action) and [github/codeql-action](https://github.com/github/codeql-action).


Updates `step-security/harden-runner` from 2.19.1 to 2.19.3
- [Release notes](https://github.com/step-security/harden-runner/releases)
- [Commits](a5ad31d6a1...ab7a9404c0)

Updates `browser-actions/setup-chrome` from 2.1.1 to 2.1.2
- [Release notes](https://github.com/browser-actions/setup-chrome/releases)
- [Changelog](https://github.com/browser-actions/setup-chrome/blob/master/CHANGELOG.md)
- [Commits](4f8e94349a...2e1d749697)

Updates `anthropics/claude-code-action` from 1.0.111 to 1.0.123
- [Release notes](https://github.com/anthropics/claude-code-action/releases)
- [Commits](fefa07e9c6...51ea8ea73a)

Updates `github/codeql-action` from 4.35.3 to 4.35.5
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](e46ed2cbd0...9e0d7b8d25)

---
updated-dependencies:
- dependency-name: step-security/harden-runner
  dependency-version: 2.19.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-minor
- dependency-name: browser-actions/setup-chrome
  dependency-version: 2.1.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-minor
- dependency-name: anthropics/claude-code-action
  dependency-version: 1.0.123
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-minor
- dependency-name: github/codeql-action
  dependency-version: 4.35.5
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: github-actions-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* fix(plugins): allow iframe-only plugin installs

* fix(config): validate start of next day boundary

* fix(sync): support separate Nextcloud login name

Refs #7617

* test(tasks): add scheduled completion round trips

* fix(focus-mode): allow active timers to switch to flowtime

* test(tasks): expand completion replay matrix

* perf(sync): use indexed findFirst for op-download minSeq

Prisma operation.aggregate({ _min: { serverSeq } }) compiles to MIN()
over a `SELECT ... OFFSET 0` subquery. The OFFSET is a Postgres planner
optimization fence, so the (user_id, server_seq) index could not serve a
first-row seek and the query degraded to a per-user O(N) scan. Under a
client reconnect stampede this ran minutes inside the 60s interactive
download transaction, blowing the tx timeout (500s) and exhausting the
connection pool (cascading upload+download failures).

Replace it with findFirst ordered by serverSeq asc, which compiles to
ORDER BY server_seq ASC LIMIT 1 — a guaranteed index seek on the existing
unique (user_id, server_seq) index. Behaviour-preserving: same minSeq
value and same null-when-empty semantics.

Update both consuming specs (operation-download.service, gap-detection)
to the two-findFirst-call shape and add a regression test asserting the
indexed query is used and the aggregate path is not reintroduced.

* fix(supersync): use 127.0.0.1 in caddy healthcheck to avoid ::1 refusal

busybox wget in caddy:2.11-alpine resolves `localhost` to ::1 first, but Caddy binds its admin API to IPv4 127.0.0.1:2019. The healthcheck got "connection refused" and marked a healthy Caddy (serving prod traffic with valid TLS) as unhealthy, making deploy.sh report a false "Container startup failed\!".

* test(focus-mode): update skip break e2e assertion

* test(focus-mode): update skip break expectation

* docs(supersync): align caddy admin healthcheck note to 127.0.0.1

Comment-only follow-up to the docker-compose healthcheck fix: the Caddyfile note still said localhost:2019; align it to the literal IP the probe now uses.

* test(focus-mode): restore mode selector locator

* refactor(tasks): make deadline auto-planning atomic

* test(focus-mode): restore mode selector locator

* fix(tasks): prevent duplicate subtask links

* fix(tasks): remove noisy warning chips

* fix(schedule): position over-budget badge correctly in day panel

* feat(tasks): auto add tasks with deadlines today to Today view

* refactor(tasks): make deadline auto-planning atomic

* Checkpoint deadline auto-plan review work

* fix(tasks): make deadline auto-planning atomic

* fix(tasks): clear orphaned remindAt when deadline auto-plan clears dueWithTime

Overdue tasks moved to Today via deadline auto-planning had their
dueWithTime cleared but kept remindAt, leaving a reminder anchored to a
time the task no longer has. Clear remindAt in the same atomic reducer
pass (one op), matching the planTasksForToday/dismissReminderOnly
convention. Document the auto-plan policy and deliberate decisions on
getDeadlineAutoPlanDecision.

* perf(tasks): O(1) Today-membership lookups in deadline auto-plan

Multi-review follow-up:
- getDeadlineAutoPlanDecision takes ReadonlySet instead of array; the
  defensive effect now passes its accumulating Set directly and hoists a
  Set for the due-task filters, removing the O(N*M) array-includes scan
  on the date-rollover path.
- Drop redundant isTodayWithOffset import; reuse the local
  getDateStrWithOffset helper (identical under the positive-finite
  timestamp guard).
- Un-export isTaskDueTodayBySchedule (file-internal only).

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Johannes Millan <johannes.millan@gmail.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-18 21:27:40 +02:00
Anzhao Liu
79138b1ad2
feat(schedule): add scheduling warnings for overlapping tasks and outside work hours (#7559)
* feat(tasks): highlight conflicting and out-of-hours tasks

* feat(work-view): warn when today's remaining estimate exceeds 8h

* feat(schedule): add real-time warnings in task scheduling dialog

* test(schedule): mock selectors for scheduling dialog specs

* fix(tasks): share scheduling conflict detection

* i18n(schedule): add scheduling hint translations

* fix(schedule): present scheduling hints as neutral info

* test(schedule): cover scheduling hint edge cases

* test(tasks): support scheduling selectors in shortcut specs
2026-05-15 14:09:52 +02:00
Johannes Millan
2788ff1e65 feat(tasks): show project icons in move-to-project menu
Closes #7425
2026-05-01 19:35:27 +02:00
Johannes Millan
944d003775 feat(tasks): color deadline badge amber within 2 days of the deadline
The deadline feature spec (issue #4328) promised green/amber/red urgency
tiers, but only the overdue-red state was implemented. Preview testers
flagged the missing intermediate tier.

Adds isDeadlineApproaching(task, todayStr) returning true when an active,
non-overdue deadline is within two calendar days. Task row badge now
shows 'warn' (red) when overdue, 'accent' (amber) when approaching, and
default color otherwise.
2026-04-21 21:50:52 +02:00
Johannes Millan
5005a0e720 feat(core): add runtime input intent tracking for hybrid touch devices
On hybrid devices (e.g. Microsoft Surface Pro), detect-it permanently
classifies the device as touch-primary, hiding hover controls, adding
500ms drag delay, and breaking context menus even when using a mouse.

Add InputIntentService that tracks current input method via Pointer
Events API (pointermove/pointerdown with pointerType) on hybrid devices
only. Dynamically toggles existing isMousePrimary/isTouchPrimary body
classes so all SCSS rules work without changes.

Replace static IS_TOUCH_PRIMARY boolean with isTouchActive() computed
signal across 32 component files. Non-hybrid devices have zero behavior
change — the computed returns the same static value as before.
2026-03-29 19:57:10 +02:00
Johannes Millan
a4bea36520 feat(tasks): dynamic strikethrough gesture for mobile swipe-right
Replace the accent-colored block + checkmark icon on swipe-right with
a dynamic strikethrough line that follows the touch position. The line
extends from left to right tracking the finger, transitions at the
trigger threshold, and snaps to full width on completion.

For undo (swiping on done tasks), the native text-decoration
line-through fades out via text-decoration-color animation, task
opacity increases from dimmed to full, and the checkmark unchecks.

Key implementation details:
- Strikethrough Y position adapts to task title center, with
  even-line-count offset for multi-line titles
- Undo uses text-decoration-color animation on .display-value
- showUndoneAnimation input on done-toggle removes is-done class
- Left swipe (context menu) behavior is unchanged
- Zero performance impact on desktop (IS_TOUCH_PRIMARY guard)
2026-03-26 17:43:03 +01:00
Johannes Millan
89d54dc31c feat(planner): make planner task work like regular task with shared components
Extract done-toggle and swipe-block into shared UI components and reuse
them in planner-task, giving it the same checkmark toggle, swipe
gestures, and drag-ready indication as the regular task component.

- Extract DoneToggleComponent with SVG checkmark, progress ring, and
  keyboard accessibility
- Extract SwipeBlockComponent with pan gesture handling, action
  thresholds, and visual feedback blocks
- Add PanDirective pancancel event for proper touchcancel cleanup
- Add PAN_MAX_START_DELAY derived from DRAG_DELAY_FOR_TOUCH to
  distinguish swipe gestures from long-press drag intent
- Stop touch event propagation during panning to prevent nested
  swipe-blocks from interfering
- Add long-press drag delay and drag-ready visual indication for
  touch devices in planner views
- Show subtask count and time estimates in planner task layout
- Restore desktop right-click context menu on planner tasks
- Apply zen theme styling refinements for planner tasks
- Replace BaseComponent inheritance with takeUntilDestroyed()
- Remove unused dead code (moveToProjectList$, Log.log, etc.)
2026-03-24 14:16:24 +01:00
Johannes Millan
c615dd7555 fix(tasks): hide play indicator immediately when marking current task as done
The play triangle on the checkbox was visible for 200ms during the done
animation because setDone() is called after a timeout. Check
showDoneAnimation() to hide it instantly.
2026-03-23 15:35:39 +01:00
Johannes Millan
2ab461cfea
Refactor task progress ring and play indicator rendering (#6920)
* perf(tasks): conditionally render play indicator SVG elements

Previously, progress-ring and play-indicator SVG elements were rendered
in the DOM for every task (with opacity: 0), even though only the single
current task needs them. With 100+ tasks, this created hundreds of
unnecessary DOM nodes and the infinite CSS animation caused continuous
GPU compositing.

Now these elements are wrapped in @if (isCurrent() && !t.isDone) so they
only exist in the DOM for the active task.

https://claude.ai/code/session_01FGFicJ9Rk6hZ89by3k6yHB

* chore: update package-lock.json

https://claude.ai/code/session_01FGFicJ9Rk6hZ89by3k6yHB

* chore: update package-lock.json dependencies

https://claude.ai/code/session_01FGFicJ9Rk6hZ89by3k6yHB

* fix(tasks): restore hover transition on play indicator elements

The transition property was accidentally removed, causing the hover
fade-out of progress-ring and play-indicator to be instant instead
of smooth.

https://claude.ai/code/session_01FGFicJ9Rk6hZ89by3k6yHB

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-03-22 23:14:50 +01:00
Johannes Millan
c7ba56f879 fix(tasks): use decorative circle-draw animation and subtle play indicator
- Replace progress-based ring with CSS-only circle-draw animation (3s eased loop from 12 o'clock)
- Make play triangle more subtle (0.5 opacity)
- On hover: hide play indicator and progress ring, show default checkbox circle
- Remove JS animation code (no longer needed - pure CSS)
2026-03-22 20:15:20 +01:00
Johannes Millan
902b237220 feat(tasks): add play indicator and progress ring to done-toggle circle 2026-03-22 20:08:53 +01:00
Johannes Millan
31480a5fab feat(tasks): replace drag handle with done toggle circle and improve mobile UX
- Replace drag handle with SVG done-toggle circle with checkmark draw-on animation
- Improve mobile UX: cdkDragStartDelay for touch, bottom-sheet context menu
- Move issue/repeat indicators from drag handle to tag-list as chips
- Add isFinishDayEnabled config toggle
- Reorder context menu: add sub task before duplicate, deadline as own entry
- Fix context menu not opening on swipe left
- Fix race condition in done toggle animation timeout
2026-03-22 18:14:16 +01:00
Johannes Millan
d401e6169e feat(tasks): add deadlines feature with reminders and planner integration
Add deadline support for tasks with date-only and time-specific deadlines.

Core:
- Add deadlineDay, deadlineWithTime, deadlineRemindAt fields to task model
- Add NgRx actions (setDeadline, removeDeadline, clearDeadlineReminder)
- Add meta-reducer with mutual exclusivity and input validation
- Register deadline actions in ActionType enum and op-log codes

UI:
- Create deadline dialog with calendar, time input, and reminder options
- Add deadline badge to task list row with overdue warning color
- Add deadline item to task detail panel with flag icon
- Add deadline options to task context menu
- Show deadlines in scheduled list page

Reminders:
- Add deadline reminder effects and selectors
- Show reminder dialog with grouped deadline/schedule sections
- Handle deadline reminder clearing on dismiss, done, add-to-today
- Cancel Android native deadline notifications on delete/archive

Planner:
- Show deadline tasks in planner day view and overdue section
- Create dedicated planner-deadline-task component
- Optimize deadline grouping with O(N) single-pass selector

Other:
- Add deadline-today banner effect for unplanned deadline tasks
- Add translation keys for all deadline UI strings
- Add E2E tests for deadline reminder flows
- Add unit tests for deadline reducer and overdue utility
- Extract shared isDeadlineOverdue utility function
- Guard app-state selectors against undefined during teardown
2026-03-15 18:48:00 +01:00
Johannes Millan
9bf1b33690 fix(tasks): keep deadline badge text in standard color when overdue 2026-03-14 13:04:44 +01:00
Johannes Millan
fbea061b1c fix(tasks): use standard color for deadline badge, warn only when overdue 2026-03-14 13:04:44 +01:00
Johannes Millan
c133725214 refactor(tasks): use flag icon for deadlines to distinguish from schedule
Replace event_busy with flag/flag_circle icons for all deadline-related UI
elements (task badge, detail panel, context menu, dialog, planner, schedule
page, snack notifications) to avoid confusion with the "unschedule" action.
2026-03-14 13:04:44 +01:00
Johannes Millan
b1a4d9326f fix(tasks): register deadline actions in ActionType enum and add warn color to overdue badge 2026-03-14 13:04:44 +01:00
Johannes Millan
abed45b5a4 feat(tasks): add deadline badge to task list row 2026-03-14 13:04:44 +01:00
Johannes Millan
43b8550fa0 perf(tasks): reduce DOM nodes and subscriptions per task component (#6802)
Defer project menu, guard tag-list rendering, and lazify parent title
subscription to reduce per-task overhead in work-view.
2026-03-12 12:49:22 +01:00
Johannes Millan
e93760dfb8 refactor(tasks): simplify template conditionals with @if/@else patterns
- Convert sequential @if blocks to @if/@else for mutually exclusive conditions
- Remove redundant nested repeatCfgId check (parent already guarantees condition)
- Remove redundant nested subTasks?.length checks (parent already guarantees condition)

Improves template readability without changing behavior.
2026-01-22 13:34:54 +01:00
Johannes Millan
94e1550227 fix(tasks): hide close button in bottom panel on mobile
Prevents the task close button from appearing on mobile screens (≤600px) where task details are shown in the bottom panel, improving UX by avoiding redundant UI elements.
2026-01-21 20:10:38 +01:00
Johannes Millan
9e1116555c refactor(icons): use drag_indicator instead of drag_handle for better visual 2026-01-21 15:51:29 +01:00
Johannes Millan
7329c1cf1e refactor(icons): replace SVG icons with Material Symbols
Replace custom SVG icons with Material Symbols equivalents:
- play.svg → play_arrow icon
- drag-handle.svg → drag_handle icon
- early-on.svg → schedule icon
- estimate-remaining.svg → hourglass_empty icon
- calendar.svg → (unused, removed)
- keep.svg → bookmark_add icon (unpinned state)
- keep-filled.svg → bookmark icon (pinned state)
- bottom-panel-open.svg → (unused, removed)

This reduces custom SVG assets and leverages the Material Symbols font
for consistent icon rendering across the application.
2026-01-21 15:37:59 +01:00
Johannes Millan
7ff7a8bbf2 fix: resolve build errors and add missing electron IPC
- Replace deprecated reminderId with remindAt in templates
- Add fileSyncListFiles to electron preload
- Fix Typia type narrowing in validate-state.service
- Fix jasmine matcher type in hydrator spec
2025-12-12 20:47:48 +01:00
Johannes Millan
84ac3c34c2 feat(task): bring back close button 2025-11-14 10:43:46 +01:00
Johannes Millan
0cef357837 refactor(task): improve 2025-10-30 10:36:26 +01:00
Johannes Millan
847ba4a70e fix: color gets stuck behind glass ui
Closes #5316
2025-10-23 19:07:33 +02:00
Johannes Millan
8610a119af fix: code error 2025-10-23 16:12:58 +02:00
Johannes Millan
69fa815501 feat(task): improve performance of task component 4
#5212
2025-10-23 15:39:46 +02:00
Johannes Millan
fdb0b77943 feat(task): improve performance of task component 3
#5212
2025-10-23 15:21:31 +02:00
Johannes Millan
05ddbceb0a feat(task): improve performance of task component 2
#5212
2025-10-23 14:35:49 +02:00
Johannes Millan
f70f427db4 feat(task): improve performance of task component 1
#5212
2025-10-23 14:25:29 +02:00
Johannes Millan
ae44138fc1 feat(rightPanel): open panel also on desktop on task click 2025-09-12 12:18:30 +02:00
Johannes Millan
982908e820 feat(bottomPanel): get rid of task close button when panel is active 2025-09-12 10:18:18 +02:00
Johannes Millan
973e17afc2 feat: replace hammerjs with custom swipe and pan directives 2025-08-10 12:56:11 +02:00
Johannes Millan
a1c4d527d2 feat(dueDate): improve day changes 1 2025-05-08 13:09:43 +02:00
Johannes Millan
ec39997a70 feat(dueDate): make todayStr dynamic in task component 2025-05-08 12:23:45 +02:00
Johannes Millan
42aa786586 feat(dueDate): remove hover json 2025-05-06 20:45:21 +02:00
Johannes Millan
af45784e18 fix(dueDate): sub task height of task inside overdue accordion broken after ani 2025-05-06 13:50:29 +02:00
Johannes Millan
ff34d6b073 fix(dueDate): simplify and fix task swipe behavior 2025-05-05 19:20:38 +02:00
Johannes Millan
e0024f734c feat(dueDate): show remove and add to today buttons correctly 2025-05-03 15:03:12 +02:00
Johannes Millan
b8f53a8324 feat(dueDate): don't show today schedule button if on today list 2025-05-03 12:56:11 +02:00
Johannes Millan
391b35230a feat(dueDate): make some stuff work and add today icon to mark today tasks better in project lists 2025-05-02 14:56:23 +02:00