fix: mobile layout, task clicks, list tab corners, hashtags in URLs
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 2m25s

Mobile
- Plus button in triage did nothing: the stored action returned the
  capture function instead of calling it
- Workspace: tabs share the full width; save status sits as an icon next
  to the note title instead of wrapping into its own row; "Neue Notiz" /
  "Neuer Ordner" only in the top menu (and +), not repeated in the list
- Outliner fields measured while hidden stayed one line high (cut-off
  callout); they are measured again when their width changes
- Task dialog: scrolls in a div instead of a fieldset, height in dvh,
  notes editor grows with its text, so long notes are fully reachable

Desktop
- Delete button of the selected task/shopping list sits inside the tab as
  its own rounded button (matches rounded themes like Soft)

Both
- Tasks sometimes did not open: every reload after an action replaced the
  list with a loading placeholder, swallowing clicks; reloads are now
  silent after the first load of a list, stale responses are dropped
- Hashtags need whitespace or "(" before "#", so URL anchors are no
  longer tags (server, browser); one-time cleanup of stored anchor tags

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
sandrodachandClaude Opus 5.5 committed 2026-10-28 16:50:51 +01:00
1 parent 41b02b9564
commit f82ab2fd32
16 files changed
+283 -47

No files matched your search

@@ -14,11 +14,15 @@ import {
Sparkles,
Plus,
Search,
Check,
CloudOff,
AlertTriangle,
} from 'lucide-react';
import { Document, DocumentBlock, User } from '../../lib/types';
import { api } from '../../lib/api';
import { DocSyncEngine, EngineState } from '../../lib/docSync/engine';
import { OutlinerTree, OutlinerTreeHandle } from './OutlinerTree';
import { extractHashtags } from '../../lib/hashtags';
export type DocSaveStatus = 'saved' | 'saving' | 'unsaved' | 'error';
@@ -314,12 +318,7 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
const extractedTags = useMemo(() => {
const tagSet = new Set<string>();
for (const b of blocks) {
const matches = b.content?.match(/#([a-zA-Z0-9äöüÄÖÜß_-]+)/g);
if (matches) {
for (const m of matches) {
tagSet.add(m.slice(1).toLowerCase());
}
}
for (const tag of extractHashtags(b.content)) tagSet.add(tag);
}
return Array.from(tagSet);
}, [blocks]);
@@ -755,6 +754,33 @@ export const DocumentEditor: React.FC<DocumentEditorProps> = ({
</div>
)}
{/* Save status on phones (the desktop shows it above the workspace) */}
{engineState && (
<span
className="sm:hidden inline-flex items-center shrink-0"
title={
engineState.status === 'saving'
? 'Speichert…'
: engineState.status === 'offline'
? 'Offline – Änderungen sind lokal gesichert'
: engineState.status === 'error'
? engineState.errorMessage || 'Fehler beim Speichern'
: 'Gespeichert'
}
aria-label="Speicherstatus"
>
{engineState.status === 'saving' ? (
<Loader2 className="w-3.5 h-3.5 animate-spin text-accent" />
) : engineState.status === 'offline' ? (
<CloudOff className="w-3.5 h-3.5 text-status-warn" />
) : engineState.status === 'error' ? (
<AlertTriangle className="w-3.5 h-3.5 text-status-err" />
) : (
<Check className="w-3.5 h-3.5 text-status-ok" />
)}
</span>
)}
{/* Read-only indicator */}
{!canEdit && (
<span className="inline-flex items-center gap-1 px-2 py-0.5 rounded-btn text-[11px] font-medium bg-status-warn/10 text-status-warn border border-status-warn/30">