fix(reminders): Cursor springt beim Schreiben nicht mehr in den Titel
Der Fokus auf das Titelfeld lag im selben Effekt wie der Escape-Listener mit Abhaengigkeit onClose. Die Kachel uebergibt onClose inline und zeichnet alle 10 s neu (NOW_TICK_MS) - der Effekt lief jedes Mal erneut und holte den Cursor aus der Beschreibung zurueck in den Titel. Fokus jetzt nur beim Oeffnen, Escape ueber eine Ref. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -484,6 +484,7 @@ Gerettet aus `.continue-here.md`. Relevant fuer die noch offenen Live-Tests.
|
||||
| 260929-if2 | **Erinnerungen-Widget (Reminder).** Modell `Reminder` + RLS, API /reminders (anlegen/listen/bearbeiten/loeschen/erledigt/snooze, 409/404-Regeln), E-Mail-Scheduler alle 30 s mit Claim-once + max. 3 Versuche, globaler ReminderNotifier (Browser-Notification, Desktop via Tauri-Notification mit Laufzeit-Capability nur fuer die Server-Origin, Pattern escaped + vorab geprueft). Verifier human_needed (Windows-Toast offen); Browser dunkel bestanden inkl. echter Mail ueber MailHog. api 1570, web 1069, cargo 57. Nebenbei: eigene Module ohne Kopfzeile (cd1f8f6), Update-Klick prueft frisch (41d00a3). | 2026-09-29 | 325c5dd,709b41a,6879c75 | [260929-if2-reminder-widget-mit-benachrichtigung](./quick/260929-if2-reminder-widget-mit-benachrichtigung/) |
|
||||
| 260929-lh3 | **Favoriten: eigene Symbol-Adresse wirkt.** Neue iconUrl ersetzt Upload + bumpt iconVersion; iconUrl wird auch gespeichert, wenn nur der Browser sie laden kann (kein 422 mehr, nur Formpruefung); Kachel: Proxy -> iconUrl direkt -> origin/favicon -> Buchstabe; Discovery liest <link rel=icon> auch aus Nicht-2xx-Seiten (docuvita 400). | 2026-09-29 | 7188c5b,b15c746,0e72ad4 | [260929-lh3-favoriten-eigenes-symbol-wirkt-nicht](./quick/260929-lh3-favoriten-eigenes-symbol-wirkt-nicht/) |
|
||||
| 261001-cxo | Desktop-Client: Links mit target=_blank (Favoriten) oeffnen jetzt im System-Browser (DesktopExternalLinks -> window.open) | 2026-10-01 | 61a971c | [261001-cxo](./quick/261001-cxo-desktop-client-links-mit-target-blank-oe/) |
|
||||
| 261001-g68 | Erinnerung: Cursor sprang beim Schreiben der Beschreibung in den Titel (Fokus-Effekt hing an inline onClose, Kachel zeichnet alle 10 s neu) – Fokus nur beim Oeffnen | 2026-10-01 | siehe git log | [261001-g68](./quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/) |
|
||||
|
||||
## Deferred Items
|
||||
|
||||
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
---
|
||||
quick_id: 261001-g68
|
||||
description: "Erinnerung: Cursor springt aus Beschreibung in Titel"
|
||||
date: 2026-10-01
|
||||
---
|
||||
|
||||
# Erinnerung: Cursor springt aus Beschreibung in Titel
|
||||
|
||||
**Befund:** `ReminderFormModal` setzte den Fokus auf den Titel im selben Effekt wie den Escape-Listener, Abhaengigkeit `[onClose]`. `onClose` ist in der Kachel eine Inline-Funktion; die Kachel zeichnet alle 10 s neu (NOW_TICK_MS) und bei jedem Neuladen → Effekt laeuft erneut → Cursor springt in den Titel (User: beim Schreiben, und bei Loeschen-Taste in leerer Beschreibung).
|
||||
|
||||
## Task 1
|
||||
- Fokus-Effekt nur beim Oeffnen (`[]`), Escape-Listener ueber `onCloseRef`.
|
||||
- Test im Widget: Formular oeffnen, Beschreibung fokussieren, 30 s Takt → Fokus bleibt.
|
||||
- CHANGELOG „Unveröffentlicht → Behoben“.
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
---
|
||||
quick_id: 261001-g68
|
||||
status: complete
|
||||
date: 2026-10-01
|
||||
---
|
||||
|
||||
# Summary
|
||||
- `reminder-form-modal.tsx`: Fokus auf Titel nur einmal beim Oeffnen; Escape ueber Ref statt `[onClose]`-Abhaengigkeit.
|
||||
- Neuer Test in `reminder-widget.test.tsx` – schlaegt ohne Fix fehl, mit Fix gruen; 28/28 Erinnerungs-Tests, tsc, biome sauber.
|
||||
- Andere Dialoge mit `[onClose]`-Fokus (Widget-Katalog, Bilderrahmen-Lightbox) fokussieren nur den Dialog ohne Eingabefelder – nicht betroffen.
|
||||
@@ -7,6 +7,7 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T
|
||||
### Behoben
|
||||
|
||||
- Desktop-App: Favoriten und andere Links, die sich in einem neuen Fenster öffnen (etwa „In neuem Tab öffnen“ oder Quellen im Ausschreibungs-Radar), öffnen sich jetzt in Ihrem normalen Browser. Bisher passierte beim Klick in der Desktop-App nichts.
|
||||
- Erinnerungen: Beim Schreiben der Beschreibung springt der Cursor nicht mehr in die Titelzeile zurück. Bisher passierte das alle paar Sekunden, weil sich die Kachel regelmäßig neu aufbaut.
|
||||
|
||||
## 1.9.0 – 2026-09-30
|
||||
|
||||
|
||||
@@ -65,14 +65,23 @@ export function ReminderFormModal({
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const titleRef = useRef<HTMLInputElement>(null);
|
||||
|
||||
// Fokus nur EINMAL beim Oeffnen (quick-261001-g68): `onClose` kommt aus der
|
||||
// Kachel als neue Funktion bei jedem Neuzeichnen — die Kachel zeichnet alle
|
||||
// 10 s neu (NOW_TICK_MS). Hing der Fokus mit am `onClose`-Effekt, sprang der
|
||||
// Cursor beim Schreiben der Beschreibung immer wieder in den Titel.
|
||||
useEffect(() => {
|
||||
titleRef.current?.focus();
|
||||
}, []);
|
||||
|
||||
const onCloseRef = useRef(onClose);
|
||||
onCloseRef.current = onClose;
|
||||
useEffect(() => {
|
||||
const onKey = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') onClose();
|
||||
if (e.key === 'Escape') onCloseRef.current();
|
||||
};
|
||||
document.addEventListener('keydown', onKey);
|
||||
return () => document.removeEventListener('keydown', onKey);
|
||||
}, [onClose]);
|
||||
}, []);
|
||||
|
||||
const handleSubmit = async (e: React.FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
@@ -349,6 +349,32 @@ describe('ReminderWidget — Faelligkeit ohne Neuladen', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('ReminderWidget — Formular behaelt den Fokus (quick-261001-g68)', () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
});
|
||||
|
||||
it('der 10-s-Takt der Kachel holt den Cursor nicht aus der Beschreibung zurueck in den Titel', async () => {
|
||||
vi.useFakeTimers();
|
||||
vi.setSystemTime(new Date('2026-09-29T12:00:00.000Z'));
|
||||
mockList.mockResolvedValue([]);
|
||||
render(<ReminderWidget {...props} />);
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(0);
|
||||
});
|
||||
fireEvent.click(screen.getByText('reminder.add'));
|
||||
expect(document.activeElement).toBe(screen.getByLabelText('reminder.titleLabel'));
|
||||
|
||||
const description = screen.getByLabelText('reminder.descriptionLabel');
|
||||
description.focus();
|
||||
fireEvent.change(description, { target: { value: 'Unterlagen mitnehmen' } });
|
||||
await act(async () => {
|
||||
await vi.advanceTimersByTimeAsync(30_000);
|
||||
});
|
||||
expect(document.activeElement).toBe(description);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ReminderWidget — Spaeter erinnern kurz nach Mitternacht', () => {
|
||||
afterEach(() => {
|
||||
vi.useRealTimers();
|
||||
|
||||
Reference in New Issue
Block a user