Add useWebSocket composable with:
- Auto-connect on login, disconnect on logout
- Exponential backoff with ±25% jitter for reconnects
- Auth failure detection to prevent reconnect loops
- Trailing slash stripping from API_URL
- Overlapping reconnect prevention
- visibilityState check for fallback polling
Replace notification polling with real-time WebSocket push in the
Notifications component. Initial state is still loaded via REST on
mount, with fallback polling when WebSocket is disconnected. Incoming
notifications are deduplicated against already-loaded REST data.
Notifications are reloaded via REST on WS disconnect to catch missed
events.
Replace the custom div-based Modal with the native HTML <dialog> element
using showModal()/close() API. Uses CSS opacity transitions with a
data-closing attribute for Firefox-compatible close animations, Teleport
to body, and focus save/restore. Updates E2E test selectors and fixes
QuickAddOverlay selectors for the new dialog structure.
Add desktopQuickEntryShortcut to frontend settings with a Desktop
App section in General settings, only visible when running in the
Electron app. The setting syncs to the desktop main process via
IPC whenever settings are loaded or saved.
When creating a task via quick entry, pressing Ctrl+Enter (or
Cmd+Enter on macOS) creates the task and opens it in the main
Vikunja window. Adds show-main-window IPC to bring the main
window to focus.
window is not accessible as a global in Vue templates, causing
"Cannot read properties of undefined (reading 'API_URL')" when
clicking sign in on the desktop app.
Adds name="email" to the email field and fixes the password field's
autocomplete from the invalid "password" to "current-password", also
adding name="current-password". This helps password managers correctly
identify the form as a settings change rather than a login form,
preventing them from autofilling the username into the email field.
Closesgo-vikunja/vikunja#2512
Show a "You can close this tab now" message after the OAuth
authorize page redirects to the desktop app, instead of leaving
a stale "Authenticating..." message in the browser tab.
Add a server selection screen matching the mobile app UX with
Vikunja Cloud, Try the Demo, and Custom Server URL options.
Extract all desktop login logic into a dedicated DesktopLogin
component. Use the existing ApiConfig component for custom server
URL input. Skip loading server config on startup to avoid showing
motd/demo popups on the login screen.
Add a complete OAuth 2.0 PKCE flow for the Electron desktop app:
- Implement PKCE code generation and token exchange in Electron
- Register custom protocol handler (vikunja-desktop://) for deep links
- Handle deep link race conditions (buffered URLs, process.argv fallback)
- Prevent duplicate IPC listener accumulation on re-mount
- Preserve sub-paths in OAuth authorize URL for non-root deployments
- Add token refresh support using Electron's net module
Add /oauth/authorize frontend route with OAuthAuthorize.vue that
handles the OAuth authorization flow: validates required query params,
calls the API to generate an authorization code, and redirects to the
callback URI. Authentication is handled by the standard router guard.
Rename the frontend parsing module from `parseTaskText` to `quickAddMagic`
for clarity. The module handles much more than text parsing — it's the
core of the quick add magic feature. This rename makes its purpose
immediately obvious and aligns with how the feature is referenced
throughout the UI and documentation.
No logic changes — only directory/file renames and import updates.
Move the watchEffect call after the validate function declaration
to fix "Cannot access 'c' before initialization" error that occurred
when visiting the password update page with validateInitially=true.
Fixes#2463
When later `urlToCheck` is restored in catch blocks, `origUrlToCheck`
will already be mutated.
Fixed by storing the original pathname as a string copy instead of
keeping a reference to the same URL object.
Split the monolithic parseTaskText.ts into a parseTaskText/ directory with
separate files for types, prefixes, prefix parsing, priority parsing, repeat
parsing, date parsing, and text cleanup. Moved parseDate.ts from helpers/time/
into the module since it's only consumed by the task text parser. Barrel export
in index.ts maintains backward compatibility — no consumer import changes needed.
https://claude.ai/code/session_01Aeo1ZunQUGKbWx2watMFdW
The kanban task move endpoint (POST /projects/:project/views/:view/
buckets/:bucket/tasks) is registered under the projects group as
views_buckets_tasks. Without this permission, the tasks preset cannot
move tasks between kanban buckets.
https://claude.ai/code/session_01QDWqXJmjriYoAcvMD43vmx
Add preset buttons (Read Only, Task Management, Project Management, Full
Access) to the API token creation form so users don't have to manually
select every individual permission.
https://claude.ai/code/session_01QDWqXJmjriYoAcvMD43vmx
When attachments are uploaded (either via file picker or pasting into
the description editor), update both the local task ref and the kanban
store so that the attachment list and kanban card icons stay in sync.
The attachment store was a global singleton shared between concurrent
TaskDetailView instances, causing a race condition when navigating
between tasks via related tasks from the Kanban view. Attachments
now live on the task ref like every other task field.
The Attachments component now reads attachments from its task prop
and emits update:attachments events instead of using the global
attachment store singleton.
When a user enables two factor authentication, all existing sessions are
now invalidated, requiring re-authentication. This prevents pre-existing
sessions from bypassing 2FA. The frontend now shows a notice explaining
the logout before the user confirms, and properly logs out after enabling.
Ref: GHSA-pgc7-cmvg-mvp4