Commit graph

857 commits

Author SHA1 Message Date
Till JS
fc5dfe2f0f feat: show build date/time on login screen across all apps
- Add BUILD_TIME and BUILD_HASH exports to all version.ts files
- Add getBuildDefines() to all vite.config.ts for compile-time injection
- Add buildTime prop to shared LoginPage component
- Display formatted date/time next to version number (e.g. "v1.0.0 · 21.03.2026 10:30")
- Add app.d.ts type declarations for __BUILD_TIME__ and __BUILD_HASH__

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:40:57 +01:00
Till JS
a6a5265332 docs(storage): update audit score 55 → 70 after tests, preview, and a11y improvements
- Testing: 0 → 50 (109 tests: 83 backend Jest + 26 web Vitest)
- Frontend: 70 → 75 (FilePreviewModal, ARIA improvements)
- UX: 55 → 62 (SEO meta tags, accessibility, semantic HTML)
- Deployment: 42 → 45 (Dockerfile port fix)
- Overall: 55 → 70 (beta status maintained)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:39:43 +01:00
Till JS
62a13d2f45 fix(contacts): stop pruning 'docs' dirs — breaks googleapis sub-modules
The Dockerfile pruning step deleted all 'docs' directories in node_modules,
including googleapis/build/src/apis/docs/ which is the Google Docs API
sub-module. This caused 'Cannot find module ./docs' crash loop on startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:35:17 +01:00
Till JS
a17a3a7f58 feat(storage): add tests, file preview modal, and fix Dockerfile ports
Tests (109 total, all passing):
- Backend (Jest, 83 tests): file, folder, trash, search, share, tag services
- Web (Vitest, 26 tests): API client coverage for all endpoints
- Mock factories for File, Folder, Share, Tag entities

File Preview Modal:
- Image preview for image/* MIME types, file info display
- Action buttons: download, rename, share, favorite, delete
- Full ARIA accessibility, responsive, escape/click-outside close
- Integrated in /files, /files/[folderId], /favorites, /search pages

Dockerfiles:
- Fix incorrect port 3019 → 3016 in backend Dockerfile and web build arg

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:16:28 +01:00
Till JS
481a88d25a feat(todo): add onboarding wizard — default view, display mode, tips
3-step onboarding using shared-app-onboarding package:
1. Default view: Today (recommended), Inbox, or Kanban Board
2. Display mode: Normal (with details) or Compact (title + priority only)
3. Tips: quick-add syntax, @project #label shortcuts, focus mode

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 12:15:08 +01:00
Till JS
16fe3aa61e feat(contacts): add onboarding wizard — sort preference, import option, tips
3-step onboarding using shared-app-onboarding package (same as calendar):
1. Sort order: first name vs last name
2. Import: Google, vCard/CSV, or skip — navigates to import page on completion
3. Tips: self-contact card, quick input, focus mode, tags

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:31:38 +01:00
Till JS
78526f1d92 fix(storage): improve SEO, accessibility, and best practices for higher audit score
- Add meta description, Open Graph tags, theme-color, preconnect/dns-prefetch to app.html
- Add per-page meta descriptions (files, favorites, search, trash, shared, settings)
- Add ARIA attributes to all loading states (role="status", aria-live="polite")
- Add aria-label, aria-expanded, aria-haspopup to all menu buttons (FileCard, FolderCard, FileRow, FolderRow)
- Add role="menu" and role="menuitem" to all dropdown menus
- Add semantic table roles to FileList (role="table", role="columnheader", role="rowgroup")
- Add aria-label and progressbar ARIA to UploadZone
- Add role="img" with aria-label to emoji icons in trash
- Add aria-label to icon-only delete button in shared page
- Add aria-hidden to decorative SVGs and spinners
- Use type="search" with aria-label on search input
- Remove console.log statements from files, favorites, and search pages

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:22:29 +01:00
Till JS
bbc5919448 fix(mukke): redirect root page to login instead of showing landing page
Replace the marketing landing page at / with an immediate redirect:
authenticated users go to /library, others go to /login. This matches
the behavior of other apps like calendar.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:19:52 +01:00
Till JS
debd55ffcf feat(calendar): implement UnifiedBar — replace standalone bottom bars with layered system
Replaces individual QuickInputBar, DateStrip, DateStripFab, CalendarToolbar, and ViewsBar
with a single UnifiedBar component. Layers stack via flexbox, child positioning overridden
to relative. Overlay menu allows toggling layer visibility. View switcher integrated into
toolbar layer.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:19:37 +01:00
Till JS
a336728e68 feat(calendar): add recurrence selector to quick event overlay
The RecurrenceSelector was already built but only available in the full
EventForm. Now it's integrated into the QuickEventOverlay so users can
set recurring events directly when creating via grid click.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:19:04 +01:00
Till JS
afa9f99705 feat(contacts): add "My Card" self-contact — auto-created on first load
Every user now gets their own contact card (like iOS "My Card") automatically
created on first API call, pre-filled with their email. The self-contact is
shown prominently at the top of the list with an "Ich/Me" badge, can be fully
edited, but cannot be deleted.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:14:44 +01:00
Till JS
99091ecf9e docs+test: add audio format docs and shared-storage utils tests
- Document all supported audio formats in mukke CLAUDE.md with browser
  compatibility matrix and notes on formats needing transcoding
- Add utils.test.ts for shared-storage: MIME type mappings, audio
  extension validation, and AUDIO_EXTENSIONS completeness checks (19 tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:12:58 +01:00
Till JS
7a1ae1284c feat(mukke): support all common audio formats for upload and playback
Expand accepted audio formats beyond MP3/WAV/OGG to include FLAC, AAC,
M4A, AIFF, OPUS, WMA, WebM, ALAC, APE, WavPack, DSF, and DFF.
The HTML5 Audio player already handles whatever the browser supports.

Changes:
- BeatUploader: accept audio/* instead of hardcoded format list
- shared-storage: add MIME type mappings for all common audio formats

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:09:25 +01:00
Till JS
c3927c85f8 fix(calendar): use 1-hour default duration for grid click instead of 15 minutes
The click-to-create handler was using SNAP_INTERVAL_MINUTES (15) as the
initial event duration. Now uses DEFAULT_EVENT_DURATION_MINUTES (60) to
match the configured default. Drag behavior still uses snap interval.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:05:15 +01:00
Till JS
b51f18a910 feat(mukke): add right-click context menu to library songs
Uses the shared ContextMenu component from @manacore/shared-ui to provide
quick actions (play, edit metadata, open in editor, toggle favorite, delete)
on right-click in the song list.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:05:12 +01:00
Till JS
4770e15499 fix(calendar): improve onboarding UX — clearer progress, better selection, apply preferences
- Replace thin progress bar with animated step dots
- Add checkmark icon and stronger highlight for selected options
- Remove redundant step emoji (duplicate of header)
- Hide "Zurück" button on first step instead of just opacity:0
- Remove timezone step (auto-detect is always correct, 4 options too limited)
- Replace unsupported "day" view with "agenda" in view options
- Wire onComplete to actually apply weekStart and defaultView to settingsStore

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 11:00:28 +01:00
Till JS
683a4c5331 feat(docker): add shared NestJS builder base image
- Add docker/Dockerfile.nestjs-base with all shared packages pre-built
- Convert 6 backend Dockerfiles (chat, todo, calendar, clock, contacts,
  mukke) to inherit from nestjs-base:local
- Fix bugs: duplicate shared-nestjs-setup builds (mukke), unnecessary
  shared-error-tracking rebuild in production stage (chat, clock)
- CD pipeline builds base image before services when backends deploy
- Net reduction: 317 lines removed, 112 added (-205 lines)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 10:48:31 +01:00
Till JS
1f9714d250 docs(devlog): add 2026-03-20 cross-app SSO & infrastructure fixes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:12:33 +01:00
Till JS
72ee82e516 docs(calendar): update complexity audit — all items resolved
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:11:55 +01:00
Till JS
3bace08b7a feat(calendar): add calendar sharing UI and service error boundaries
Calendar Sharing:
- Add shares store with full lifecycle (share, accept/decline, remove, permissions)
- Add missing API methods (getInvitations, getSharedWithMe)
- Create /settings/sharing page with:
  - Pending invitations section with accept/decline
  - "Shared with me" section
  - Per-calendar share management (expandable list, add/remove shares)
  - Share modal with email, permission selection
- Add link from main settings page

Error Boundaries:
- Create ServiceStatusBanner component for graceful degradation
- Integrate into main calendar page for Todo and Birthday services
- Shows warning when service unavailable with retry button
- Uses existing serviceAvailable flags from stores

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:11:15 +01:00
Till JS
9df908d838 refactor(calendar): simplify UnifiedBar and extract ViewCarousel gestures
UnifiedBar (633→559 LOC):
- Remove 3 duplicate DateStrip blocks (4→1) and 1 duplicate TagStrip block (2→1)
- Remove deprecated createEventDispatcher (Svelte 4→5)
- Remove unused component imports (DateStrip, TagStrip, CalendarToolbar, DateStripFab)

ViewCarousel (402→162 LOC, -60%):
- Extract all gesture handling (touch, wheel, velocity, snap, animation,
  chain navigation) into useSwipeNavigation composable (260 LOC)
- ViewCarousel now only handles layout, date calculation, and view rendering
- Composable is reusable for any carousel/swipe navigation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 21:04:25 +01:00
Till JS
e57b64590d fix(picture): add missing PUBLIC_GOOGLE/APPLE_CLIENT_ID build args to Dockerfile
SvelteKit $env/static/public requires these vars at build time even if empty.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:59:34 +01:00
Till JS
e64c298cec refactor(auth,planta): optimize storage usage
mana-core-auth:
- Replace manual key generation (Date.now) with generateUserFileKey()
- Replace manual validateFileSize with maxSizeBytes in upload()
- Remove OnModuleInit — init storage directly in constructor
- Add upload hooks for structured logging
- Remove redundant getPublicUrl() fallback chain (presigned URL for 1 year)
- Add deleteAllUserAvatars() for account deletion
- Simplify getAvatarUploadUrl() using storage.getPublicUrl()

planta:
- Replace createStorageClient() with manual config by createPlantaStorage()
- Replace manual uuid + path construction with generateUserFileKey()
- Remove uuid dependency for key generation
- Add maxSizeBytes validation (20MB)
- Add cacheControl header (immutable, 1 year)
- Add upload hooks for structured logging
- Add error handling in deletePhoto()
- Add deleteAllUserPhotos() for account deletion
- Make getPhotoUrl() synchronous (was async unnecessarily)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:59:14 +01:00
Till JS
6476521fd1 fix(picture): add patches directory to web Dockerfile
pnpm install fails without the patches/ directory since pnpm-lock.yaml
references patch files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:57:38 +01:00
Till JS
e5ba591680 refactor(storage): optimize cloud drive storage service
- Replace manual validateFileSize() with maxSizeBytes in upload()
- Add upload hooks for structured logging
- Add deleteFiles() for bulk deletion via deleteMany()
- Add deleteAllUserFiles() for account deletion via deleteByPrefix()
- Remove unused validateFileSize import

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:57:18 +01:00
Till JS
69eac206fa refactor(picture): optimize storage service
- Replace manual key generation (Date.now + Math.random) with
  generateUserFileKey() for UUID-based collision-free keys
- Add maxSizeBytes validation (50MB images, 5MB thumbnails)
- Add cacheControl headers (immutable for images, 7d for thumbnails)
- Add upload hooks for structured logging
- Simplify constructor (remove OnModuleInit, init storage directly)
- Remove unused StorageMode type and getStorageMode()
- Add deleteAllUserFiles() for account deletion
- Consistent error handling in deleteFile() (warn + swallow)
- Board thumbnails use stable path (no timestamp) for overwrite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:56:44 +01:00
Till JS
887b60c8c1 fix(picture): fix health endpoint and port consistency for Docker deployment
Exclude /health from global prefix so healthchecks hit /health instead of
/api/v1/health. Update Dockerfile EXPOSE and healthcheck to use port 3040
matching docker-compose config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:54:27 +01:00
Till JS
15cde622e4 refactor(mukke): optimize storage usage in song and beat services
SongService:
- Use deleteMany() for batch deletion of audio + cover (was sequential)
- Add maxSizeBytes validation on cover art (10MB) and tag writing (500MB)
- Add cacheControl header on cover art uploads (immutable, 1 year)
- Add upload hooks for structured logging
- Use 'songs' subfolder for audio, 'covers' for cover art (was flat)
- Add deleteAllUserFiles() for account deletion via deleteByPrefix()
- Log storage errors instead of silently swallowing

BeatService:
- Add upload:error hook for structured logging
- Use 'beats' subfolder for organized key structure
- Log storage deletion errors instead of swallowing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:53:23 +01:00
Till JS
56c3086ec6 test(calendar): add reminders API client tests
- 4 tests: getReminders (success + error), createReminder with body
  validation, deleteReminder endpoint
- All 120 tests passing across 13 test files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:52:23 +01:00
Till JS
b38e5aecf9 fix(contacts): clean up orphaned photos on duplicate merge
DuplicatesService.mergeContacts() now deletes S3 photos of merged
contacts before removing them from the DB. Photos that were adopted
by the primary contact (via mergeContactData) are preserved.

- Import PhotoModule in DuplicatesModule
- Inject PhotoService into DuplicatesService
- Add photo cleanup loop before DB deletion
- Update test mock

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:50:44 +01:00
Till JS
3ac976f600 feat(picture): migrate web app from Netlify to Docker/Mac Mini deployment
Switch from adapter-netlify to adapter-node for self-hosted Docker deployment.
Add missing Button and Card UI components, remove Netlify config files,
and add picture-backend + picture-web services to docker-compose and
Cloudflare tunnel routing (picture.mana.how).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:50:12 +01:00
Till JS
1ffcfa0e5c docs(calendar): mark reminders as implemented in complexity audit
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:48:44 +01:00
Till JS
6806ef8bde feat(calendar): add reminder UI for creating and managing event reminders
- Create ReminderSelector component with two modes:
  - Draft mode (new events): configure reminders before save with preset
    dropdown, push/email toggles, add/remove multiple reminders
  - Saved mode (existing events): view reminders with status (pending/sent/
    failed), add via preset dropdown, delete individual reminders
- Integrate into EventForm: default reminder pre-configured from settings,
  drafts passed to parent via onSave callback for creation after event save
- Integrate into EventDetailModal: load and display reminders for existing
  events, add/remove reminders directly via API, auto-refresh on change
- German UI labels for all reminder presets (Zum Zeitpunkt, 5/10/15/30 Min.,
  1/2 Stunden, 1/2 Tage, 1 Woche vorher)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:48:26 +01:00
Till JS
ecec3d56fe fix(contacts): optimize storage usage and fix photo orphan bug
Bug fix:
- ContactService.delete() now cleans up S3 photo before DB deletion
  (previously left orphaned files in storage)
- ContactModule imports PhotoModule for dependency injection

PhotoService improvements:
- Use maxSizeBytes in upload() instead of manual validateFileSize()
- Use getPublicUrl()/result.url instead of manual URL construction
  via getStorageConfig() + BUCKETS concatenation
- Add cacheControl header for immutable photo assets (1 year)
- Add upload hooks for structured logging via Logger
- Add deletePhotoByUrl() for contact deletion cleanup
- Add deleteAllUserPhotos() for account deletion via deleteByPrefix()
- Store photos in 'photos' subfolder for cleaner key structure
- Remove unused getStorageConfig/BUCKETS imports

Test fix:
- Add PhotoService mock to ContactService spec

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 20:01:43 +01:00
Till JS
d9ccb5e31b feat(games): add whopixels hosting at whopxl.mana.how
Dockerfile, docker-compose service (port 5100), Caddy and cloudflared
routing for the WhoPixels game. PORT is now configurable via env var.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:57:50 +01:00
Till JS
2eb280cc07 test(calendar): add composable unit tests and WeekView E2E interaction tests
Unit tests (vitest):
- useEventDragDrop.test.ts: 7 tests (idle state, drag start, resize start,
  cancel, hasMoved reset, getResizePreviewTime, preview positions)
- useTaskDragDrop.test.ts: 5 tests (idle state, drag start, resize start,
  cancel, preview position calculation)
- useDragToCreate.test.ts: 4 tests (idle state, guard when other op active,
  cancel, preview time format)

E2E tests (playwright):
- week-view-interactions.spec.ts: 7 tests covering drag-to-create (click,
  drag with time range, escape cancel), event card positioning, current time
  indicator, day headers, and today highlighting

All 116 unit tests passing across 12 test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:51:23 +01:00
Till JS
aeabdcaf8e refactor(calendar): extract WeekView inline logic into composables (1600→903 LOC)
Replace 697 lines of inline drag/drop/resize/create/keyboard handlers
in WeekView.svelte with existing composables:

- useEventDragDrop: event drag & resize (was ~220 LOC inline)
- useTaskDragDrop: task drag & resize (was ~180 LOC inline)
- useSidebarDrop: sidebar task drop (was ~70 LOC inline)
- useDragToCreate: new composable for click-drag event creation (was ~105 LOC)
- useCalendarKeyboard: Escape key cancel (was ~50 LOC inline)

Also adds getResizePreviewTime() to useEventDragDrop return value
so WeekView doesn't need access to internal resize state.

WeekView.svelte: 1600 → 903 lines (-44%)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:43:19 +01:00
Till JS
70671e2b2b perf(docker): prune devDeps and cleanup node_modules in all backend Dockerfiles
Add pnpm prune --prod and remove .ts/.map/test/docs files from
node_modules in the builder stage for chat, todo, calendar, clock,
and contacts backends. Same approach as mana-core-auth optimization.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:42:01 +01:00
Till JS
822e75368a feat(shared): add DevBuildBadge component and getBuildDefines() helper
- shared-vite-config: getBuildDefines() injects __BUILD_HASH__ and
  __BUILD_TIME__ as compile-time constants via Vite define
- shared-ui: DevBuildBadge component shows git hash + build timestamp
  in a small fixed badge at bottom-right (click to expand)
- Integrated into mukke-web for deployment verification

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:34:21 +01:00
Till JS
511b51e372 test(calendar): add tests for CalDAV sync API, external calendars store, and recurrence
- sync.test.ts: 8 tests for API client (CRUD, sync, discovery, OAuth, export URL)
- external-calendars.test.ts: 8 tests for store (fetch, connect, disconnect,
  update, triggerSync success/error, getById)
- events-recurrence.test.ts: 9 tests for recurrence expansion (daily, weekly,
  exceptions, non-recurring passthrough, helpers, delete occurrence/series)

All 100 tests passing across 9 test files.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:31:34 +01:00
Till JS
5c9e16f634 fix(calendar): integrate recurrence dialog and external calendars into UI
- Wire RecurrenceEditDialog into EventDetailModal and QuickEventOverlay
  so deleting recurring events shows "this/all/future" options
- Add external calendars section to CalendarSidebar with visibility
  toggle and sync error indicator
- Update COMPLEXITY_AUDIT.md to mark sync and recurrence as implemented

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 19:22:28 +01:00
Till JS
ab42c265e1 feat(calendar): add CalDAV/iCal sync UI and recurring events support
CalDAV/iCal Sync:
- Add sync API client (lib/api/sync.ts) for all external calendar endpoints
- Add external calendars store with connect, disconnect, sync operations
- Add /settings/sync page with provider selection (Google, CalDAV, iCal URL, Apple),
  credentials form, CalDAV discovery, sync status display, and manual sync trigger
- Add link to sync settings from main settings page

Recurring Events:
- Add RecurrenceSelector component with preset selection (daily, weekly, monthly,
  yearly, weekdays) and custom configuration (interval, weekday picker, end date)
- Integrate RecurrenceSelector into EventForm between date fields and location
- Expand recurring events into individual occurrences in events store using
  generateOccurrences() from @calendar/shared
- Add recurrence-aware delete: single occurrence (exception), all occurrences,
  or series update via dedicated store methods
- Add RecurrenceEditDialog component for "this/all/this and future" selection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 18:46:33 +01:00
Till JS
d3a3bc7b77 refactor(calendar): remove tag groups hierarchy and legacy drag-drop composables
Remove unnecessary complexity from the calendar web app:

- Remove tag groups system entirely (store, API client, route, components)
  Tags are now a flat alphabetically-sorted list instead of grouped hierarchy
- Remove unused legacy composables (useDragDrop, useResize) that were never
  imported by any component — useEventDragDrop already consolidates both
- Simplify TagStripModal from 1,452 to ~350 LOC by removing group CRUD,
  drag-drop between groups, and group hierarchy rendering
- Add complexity audit report documenting remaining issues

Total: -2,170 LOC across 13 files

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:33:57 +01:00
Till JS
70b1c4429d test(mukke): add vitest setup and 34 frontend tests for player & library stores
- Set up vitest with jsdom, testing-library/svelte, and SvelteKit mocks
- Player store: 16 tests covering playSong, queue, shuffle, repeat,
  volume, error handling, clearQueue, removeFromQueue
- Library store: 18 tests covering loadSongs, loadCoverUrls (including
  non-image path filtering), albums, artists, genres, stats, favorites,
  tabs, upload, and delete

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:16:47 +01:00
Till JS
67326b738a fix(shared-api-client): add useRuntimeUrl flag for cross-app clients
getBaseUrl() always overrides baseUrl with window.__PUBLIC_BACKEND_URL__,
which breaks cross-app API clients (e.g. calendar→todo, calendar→contacts)
by routing all requests to the host app's backend.

Added useRuntimeUrl: false option to skip the runtime override when
the client already resolves its own base URL.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:11:31 +01:00
Till JS
a5940abfc2 feat(mukke): clickable songs in library, player error handling & cover fallbacks
- Songs in library are now clickable to play (with full queue support)
- Active song highlighted with primary color and play/pause overlay on cover
- Player store: error state, audio error listener, auto-skip on failure
- MiniPlayer: error toast bar with dismiss button
- Library store: filter non-image paths from cover URL loading
- Cover images: onerror fallback to icon when S3 file is missing

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:05:07 +01:00
Till JS
26d8eb0898 fix(calendar): add shared-app-onboarding to web Dockerfile
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:45:55 +01:00
Till JS
93e1c7de4a refactor(calendar): simplify settings from 41 to 18 persisted preferences
Remove unused header/dateStrip settings (hardcode defaults), move runtime
UI state (sidebar, tags, immersive mode) to non-persisted $state() variables,
and add localStorage migration for existing users.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:40:47 +01:00
Till JS
98d1d1cc90 fix(calendar): add shared-pwa package to web Dockerfile
vite.config.ts imports @manacore/shared-pwa for PWA config.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:40:24 +01:00
Till JS
58bdf984bc fix(calendar): add patches dir to web Dockerfile
pnpm install fails without the patches directory since the lockfile
references react-native-reanimated patch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 16:38:47 +01:00