Previously, clicking a detail view in one AppPage would close the
overlay in all other AppPages because the global click handler closed
on ANY click outside the overlay card.
Now the click handler only closes the overlay when the click is
inside the SAME AppPage but outside the overlay card. Clicks in
other AppPages are ignored, allowing multiple detail views to be
open simultaneously side by side.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Entity registration was async (dynamic imports) so acceptedDropTypes
was always empty when $derived first evaluated. Now entities register
synchronously at import time. Store imports (Dexie, etc.) are deferred
to createItem() call time to avoid circular dependencies.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clicking a linked item in a DetailView opens the target app's DetailView
as a stacked overlay on top of the current one. Supports:
- Cross-app navigation (e.g. click linked event from todo detail)
- Back button to return to previous overlay
- Correct app color + title in overlay header
- Overlay stack with goBack() popping the top frame
- Added paramKey to EntityDescriptor for correct ID mapping
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
New habit tracking module: define habits (emoji, color, daily target), tap to log with timestamp, view streaks and 7-day charts. Includes workbench ListView with inline creation, full-page detail view, and drag/drop entity integration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Window buttons now live in the drag handle bar alongside the move arrows,
appearing on hover. Header row is simplified to just icon + title.
Layout: ◀ ···drag··· [−] [□] [✕] ▶
All buttons appear on hover, close button has red hover state.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Arrow buttons appear on hover at the left/right edges of the drag bar
to quickly reorder pages without dragging. Hidden when the page is
already first (no left arrow) or last (no right arrow).
- PageShell: onMoveLeft/onMoveRight props, CaretLeft/CaretRight icons
- AppPage: pass through move callbacks
- +page.svelte: handleMoveLeft/handleMoveRight with array swap + persist
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
DragPreview now accepts a resolveEntity callback that maps drag type
+ data to display info (title, app color, app name). Dragging a task
shows "Meeting mit Team · Todo" instead of just "task".
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Drag handle bar spans full width (not just the icon)
- Entire bar is draggable with grab cursor
- Subtle background color differentiates it from content (border-bottom)
- Hover/active states for visual feedback
- DotsSixVertical icon rotated 90° (horizontal grip lines)
- Dark mode support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
First panel no longer sticks to the left edge. Left padding set to
calc(50vw - 240px) so the carousel starts with generous breathing room.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Break out of the layout's max-w-7xl px-4 container using negative
margins so the workbench carousel fills the entire viewport width.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Page reorder drag now only starts from the drag-handle icon, not from
anywhere in the page. This allows dragSource on list items (tasks,
events, contacts) to work without being intercepted by page reorder.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Making guestMode reactive with $state() triggered an infinite effect
cascade: guestMode.notifications being accessed in the template created
a reactive dependency that, combined with 8+ AppPages each running
$effect for module loading, exceeded Svelte's effect update depth limit.
Root cause: GuestMode object has reactive getters that return new
references on each access. Wrapping it in $state() made every template
access trigger a re-render, which triggered more effects, creating an
unbounded cascade.
Fix: Keep guestMode as plain variable (non-reactive). The warning about
non_reactive_update is acceptable — guestMode is set once during init
and its properties are accessed imperatively, not reactively.
Also:
- Remove debug console.logs from AppPage, +page, +layout
- Keep onMount for workbench state loading (replaces $effect)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Delete all 25 apps/*/apps/web-archived/ directories (superseded by unified ManaCore app)
- Remove stale +page.server.ts stubs from teams, organizations, settings (always returned empty data)
- Simplify teams and organizations pages to static empty-state (no server load dependency)
- Delete empty apps/context/apps/mobile/components/variants/index.ts
- Remove commented-out apps-archived entries from pnpm-workspace.yaml
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Make entity registration lazy (ensureEntitiesRegistered) to avoid
circular imports at module load time
- Re-enable cross-module drop target in AppPage
- Fix Component type in app-registry to accept any props (AnyComponent)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Introduce EntityDescriptor pattern: each module declares how its items
can be displayed, dragged, dropped, and created from other modules.
- Entity types + registry with executeDrop orchestration
- Entity descriptors for todo, calendar, contacts
- List items are now draggable (dragSource) across pages
- Pages accept cross-module drops (event→todo, contact→calendar, etc.)
- Drops create new items + bidirectional manaLinks via shared-links
- LinkedItems component shows cross-module links in DetailViews
- Visual feedback: page glows purple on valid hover, green on success
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
$derived cannot reference variables declared later in the script.
Moved the calculation below the isTagStripVisible $state declaration.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Dev env vars (_CLIENT suffixed) are empty, so localhost:3001 (auth),
localhost:3050 (sync), localhost:3060 (api) were blocked by CSP.
Added http://localhost:* and ws://localhost:* to connect-src when
NODE_ENV !== 'production'.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bind:clientHeight + $effect setting CSS variable caused infinite reflow
loop: height change → CSS var → padding change → height change.
Now using $derived calculation from state (isCollapsed, isTagStripVisible)
instead of DOM measurement. No reflow loop possible.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Per-app SSE connections exhaust the browser's 6-connection-per-origin
limit, causing the app to hang on load. Reverted to HTTP polling for
both eager and lazy apps.
SSE server endpoint remains available for future use as a single unified
stream (one connection for all apps, similar to the old unified WebSocket).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Times ListView: inline timer with start/stop, name input, live elapsed display
- Times DetailView: editable entry with duration (h/m/s), project, billable, delete
- Zitare ListView: tap-to-cycle quotes, inline fav button, tag drag-and-drop support
- Zitare DetailView: full quote view with category, author bio, share, favorite
- Homepage: remove tag bar (available via PillNav), carousel uses full width
- Register both DetailViews in app-registry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
These are secondary pages accessible via settings/profile, not primary navigation.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Display assigned tags as colored pills in todo, calendar, contacts
DetailViews. Clicking a tag pill removes it from the item. Hover turns
the X icon red for clear affordance.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace tiny 6px tag dots with readable pills showing colored dot +
tag name. Uses color-mix for subtle tinted background per tag color.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useAllTags() returns a Svelte 5 runes object with .value, not an
Observable with .subscribe(). Also fix getTagsByIds() calls to pass
the allTags array as first argument.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add rightAction snippet prop to QuickInputBar (InputBar.svelte)
- Move toggle from leftAction to rightAction (renders after submit button)
- Increase toggle size from 28px to 36px for better tap target
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Mount DragPreview + draggable tag bar on workbench homepage
- Add dropTarget on list items in todo, calendar, contacts ListViews
- Show assigned tags as colored dots on list items
- Tags can be dragged from the tag bar onto any item to assign them
- Drop target highlights with module-colored outline on hover
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Toggle button now renders inside the InputBar pill (left side) instead of
as a separate element next to it. Uses the existing leftAction snippet prop.
- Button is 28px circle, subtle background, no border/shadow (lives inside pill)
- Remove bottom-stack-row wrapper (no longer needed)
- Cleaner visual: toggle is part of the input bar, not floating beside it
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Tags pill moved to first position in nav items (leftmost)
- Toggle button: 44px round (matches InputBar height), same border-radius
(9999px), same backdrop-filter blur, same box-shadow, theme-aware colors
- Button sits directly next to QuickInputBar with no gap, vertically centered
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The bottom-stack container now exports its height as --bottom-chrome-height
CSS custom property (via bind:clientHeight + $effect on :root). All elements
that need to position above the bottom chrome read this variable:
- PageCarousel minimized-tabs: bottom: var(--bottom-chrome-height)
- NotificationBar: bottom: var(--bottom-chrome-height)
- Main content padding: calc(var(--bottom-chrome-height) + 2rem)
This ensures tabs, notifications, and content never overlap with the
bottom stack regardless of PillNav collapse state or TagStrip visibility.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace 4 independent position:fixed elements with one flex container that
stacks them naturally from bottom to top. Elements push each other
automatically — no more hardcoded offsets or z-index conflicts.
Stack order (bottom → top):
1. PillNavigation (collapsible)
2. TagStrip (togglable)
3. QuickInputBar + toggle button row
Shared-UI changes:
- PillNavigation: add positioning='fixed'|'static' prop
- QuickInputBar: add positioning='fixed'|'static' prop
- TagStrip: add positioning='fixed'|'static' prop
- All default to 'fixed' for backward compatibility
Layout changes:
- Wrap all bottom elements in .bottom-stack (position:fixed, flex-column)
- Remove hardcoded bottomOffset calculations
- Toggle button is now inline next to QuickInputBar (not separately positioned)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When heightPx is not yet set, use the element's actual offsetHeight
instead of 0 so the first drag correctly adjusts height.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extend PageShell resize handle to support diagonal drag for both
width and height. Height is persisted per page in workbench settings.
Resize cursor changed from ew-resize to nwse-resize.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Small floating button (▼/▲) at the bottom-right that toggles PillNav
visibility. QuickInputBar's bottomOffset adjusts dynamically when nav
is collapsed (70px → 12px), reclaiming vertical space.
- Button uses existing handleCollapsedChange() with localStorage persistence
- Smooth transitions on position and rotation
- Glass-morphism style (blur + semi-transparent background)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Consistent naming: ListView.svelte + DetailView.svelte as a pair.
Update app-registry.ts and splitscreen/registry.ts imports.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add inline-editable DetailViews with auto-save for:
- cards: deck details with color, description, public toggle
- storage: file details with rename, favorite, size/type info
- presi: presentation deck details with slide count
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add inline-editable DetailViews with auto-save for:
planta, inventar, skilltree, memoro, questions, uload, mukke, citycorners
Wire AppView list items to open overlay via navigate() with sibling
navigation support. Fix citycorners table names (cityLocations→ccLocations).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Remove /dashboard (redundant), merge /home into / (app root)
- Update all redirects and navigation references accordingly
- Add panel navigation stack with overlay detail views for workbench
- Implement inline-editable DetailViews for todo, calendar, contacts
- Auto-save on blur, prev/next navigation with sibling arrows
- Fix minimized tabs z-index behind quick input bar
- Fix showNewEvent undefined error in calendar AppView
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Client now connects to GET /sync/{appId}/stream via fetch + ReadableStream
instead of WebSocket + HTTP pull. Each app gets its own SSE connection that
delivers initial sync data + live updates in one persistent stream.
Changes:
- Remove WebSocket connection (connectUnifiedWs)
- Add connectSSE() per app using fetch + ReadableStream
- Parse SSE events (changes, heartbeat) from streamed response
- Auto-reconnect on disconnect with WS_RECONNECT_DELAY
- Fallback to polling if SSE endpoint not available
- ensureAppSynced() connects SSE for lazy apps on first visit
- handleOnline() reconnects all active SSE streams
- handleOffline() aborts all SSE connections
Benefits: 1 connection instead of 2 (WS + HTTP), data delivered instantly
without notification → pull round-trip, works through HTTP proxies/CDN.
Push (POST /sync/{appId}) remains unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only sync eager apps at startup (manacore, todo, calendar, contacts,
tags, links — needed for dashboard widgets). All other apps are lazy:
their collections sync on first module route visit.
Reduces startup pull requests from ~108 to ~20-30. Lazy apps get
synced when the user navigates to their module via ensureAppSynced().
- Add EAGER_APPS config set in sync.ts
- startAll() only starts pull for eager apps
- ensureAppSynced() starts pull + periodic sync for lazy apps
- Route-based trigger in +layout.svelte $effect
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Server now returns hasMore: true when there are more than 1000 changes
pending for a collection. Client continues pulling in a loop until
hasMore is false, using the last row's timestamp as cursor.
Prevents data loss after long offline periods where >1000 changes
accumulated for a single collection.
Server changes (Go):
- GetChangesSince() accepts limit parameter
- HandlePull() fetches limit+1, trims, sets hasMore
- SyncedUntil uses last row's timestamp when paginating
Client changes (TypeScript):
- Pull loop: while (hasMore) { fetch → apply → advance cursor }
- Cursor only persisted after all pages fetched
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Merge the auth store factories (createManaAuthStore, createAuthStore) from
@manacore/shared-auth-stores into @manacore/shared-auth-ui, reducing
from 3 auth packages to 2.
- Copy store files into shared-auth-ui/src/stores/
- Re-export store factories and types from shared-auth-ui
- Update imports in manacore/web and arcade/web
- Remove shared-auth-stores from active package.json dependencies
Result: @manacore/shared-auth (core, platform-agnostic) +
@manacore/shared-auth-ui (Svelte components + stores)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>