# Desktop GNOME-Shell-Extension (GNOME 46, Ubuntu 24.04): Kalender, Todos und Notizen direkt auf dem Desktop, unter allen Fenstern, über dem Wallpaper. ## Bedienung - **Woche:** startet mit der aktuellen Uhrzeit in der Mitte, rote Linie markiert jetzt. - **Termin anlegen:** in der Wochenansicht auf eine Stunde drücken und bis zur Endstunde ziehen, auch über mehrere Tage. Klick ohne Ziehen = eine Stunde. Ziehen in der Zeile „ganz“ = ganztägig. Oder Rechtsklick auf einen Tag (Monat), eine Stunde (Woche) oder die Tagesfläche: „Termin erstellen“. Popover: Titel, Von und Bis je mit Datum und Uhrzeit. Ohne Ende gilt eine Stunde, ohne Uhrzeit ganztägig. - **Todo anlegen:** Rechtsklick ins Todo-Panel oder in den Kalender, „Todo erstellen“. Text plus Datum und Uhrzeit. - **Notiz:** Rechtsklick irgendwo im Notiz-Panel, „Notiz erstellen“ fragt den Namen und öffnet den Editor. Klick in die Notizfläche bearbeitet. Mit Fokus steht der rohe Markdown-Text, ohne Fokus die formatierte Ansicht. Gespeichert wird alle 5 Sekunden und beim Klick woanders hin. - **Maustasten:** links bearbeitet, Mitte hakt ein Todo ab oder benennt Notiz/Ordner um, rechts öffnet das Menü. Alle Popover öffnen am Mauszeiger. - **Rechtsklick auf freie Fläche:** Erstellen (Todos, Tagesansicht, Notizbaum im Wurzelordner). - **Ordner:** Klick klappt auf und zu, das Symbol zeigt den Zustand. - **Rechtsklick auf Ordner:** Notiz oder Unterordner darin erstellen, Umbenennen, Löschen. - **Rechtsklick auf Eintrag:** Umbenennen, Löschen. - Popover: Enter speichert, Esc oder Klick daneben bricht ab. Keine Buttons. ## Aufbau - `desktop@marha.de/` – die Extension - `extension.js` – Layout auf dem Arbeitsbereich, Stapelung über Desktop-Icons - `calendar.js` – Monat, Woche (Drag), Tag, Termin-Popover - `todos.js` – Todo-Liste, Todo-Popover - `notes.js` – Ordnerbaum, Markdown-Anzeige, Inline-Editor, Kontextmenü - `widgets.js` – Popover (Grab, Esc, Tab, Klick daneben), Kontextmenü, Datums- und Zeitauswahl - `markdown.js`, `dates.js` – reine Logik, ohne Shell testbar - `store.js` – Ablage, Tombstones, Übernahme vom Server - `sync.js` – Abgleich mit dem Server (Soup, Timer) - `backend/` – Sync-Server (FastAPI, SQLite), `Dockerfile`, `docker-compose.yml` - `android/` – native Android-App mit denselben drei Bereichen, siehe `android/README.md` - `dev/` – Test-Werkzeuge ## Daten `~/.local/share/desktop-app/` - `events.json` – Termine - `todos.json` – Todos - `notes/` – Notizen als `.md`, Ordner beliebig verschachtelt (Obsidian kann den Ordner öffnen) - `deleted-notes.json` – gelöschte Notizen mit Zeitpunkt, damit der Sync sie auch woanders löscht - `folders.json` – Ordner mit Zeitpunkt und deleted-Flag, damit auch leere Ordner mitlaufen - `sync.json` – Server-Zugang, siehe Sync - `sync-state.json` – letzter Server-Stand Gelöschte Termine und Todos bleiben mit `deleted: true` in der Datei und werden nur ausgeblendet. ## Sync Der Server (`backend/`, FastAPI + SQLite) hält den Kern. Jedes Gerät gleicht regelmäßig ab und sofort nach jeder eigenen Änderung: eigene Änderungen hoch, fremde Änderungen runter. Der Takt richtet sich nach der Aktivität: nach einer Änderung (eigene oder vom Server) eine Minute lang jede Sekunde, dann alle 5 Sekunden, nach 5 Minuten Ruhe alle 10 Sekunden. Bei Konflikten gewinnt der Eintrag mit dem neueren `updated` (Notizen: Änderungszeit der Datei, ganze Datei). Offline geht weiter, beim Wiederverbinden wird nachgeliefert. Eine gerade offene Notiz wird nicht von außen überschrieben. Zugang auf jedem Gerät in `~/.local/share/desktop-app/sync.json`: ``` {"url": "https://planer.marha.de", "token": ""} ``` Ohne diese Datei läuft die Extension rein lokal. Optional `"interval"`: Ruhetakt in Sekunden statt 10. Server-API (alle Aufrufe mit `Authorization: Bearer `): - `POST /api/sync` – `{"since": , "events": [...], "todos": [...], "notes": [...], "folders": [...]}`; Antwort: Änderungen seit `since` plus neuer `cursor` - `GET /api/events`, `/api/todos`, `/api/notes` – aktueller Stand ohne Gelöschte, für andere Anwendungen ### Server starten ``` cp .env.example .env # SYNC_TOKEN setzen make dev # lokal, http://localhost:8040 (anderer Port: make dev PORT=8050) make prod # auf dem Server: Docker Compose hinter Traefik, https://planer.marha.de make stop | make logs | make down make test # Server-Tests make apk # Android-App bauen, make apk-install schickt sie aufs Handy (android/README.md) ``` ## Installation ``` cp .env.example .env # SYNC_TOKEN eintragen (derselbe wie auf dem Server) make install # kopiert die Extension nach ~/.local/share/gnome-shell/extensions und aktiviert sie make update # überschreibt eine installierte Extension mit dem Stand aus diesem Ordner ``` Beide legen `~/.local/share/desktop-app/sync.json` aus der `.env` an, falls sie fehlt. Ohne `.env` läuft die Extension rein lokal. Danach ab- und wieder anmelden. Unter Wayland lädt die Shell neuen Code erst nach einem neuen Login. `make update` startet die Extension neu, damit ein neuer Sync-Zugang sofort greift. Voraussetzung: GNOME 46 (Ubuntu 24.04). ## Entwicklung ``` gjs -m dev/tests/run.js # Unit-Tests für dates.js und markdown.js dev/restart.sh # Test-Shell als Fenster starten (zum Selbst-Ausprobieren) dev/restart.sh headless # Test-Shell unsichtbar, für simulierte Eingaben dev/tests/input.sh # Ablauf-Tests mit echter Maus und Tastatur (headless) dev/tests/sync.sh # Sync-Test: lokaler Server plus headless Shell, beide Richtungen dev/eval.sh dev/seed.js # Testdaten einspielen dev/eval.sh 'js' # JavaScript in der Test-Shell ausführen (oder Dateipfad) dev/shot.sh [datei.png] # Screenshot der Test-Shell dev/input.sh click X Y # Maus und Tastatur simulieren (nur headless gefahrlos) dev/press.sh "Text" # Button mit diesem Text direkt auslösen dev/stop.sh # Test-Shell beenden ``` Die Test-Shell läuft mit `GSETTINGS_BACKEND=keyfile` und eigenem `XDG_DATA_HOME` unter `/tmp/desktop-app-nested/`. Die echte Session bleibt unberührt. Im Fenstermodus (nested, X11-Backend) würden virtuelle Eingabegeräte auf dem echten Desktop landen. Deshalb nutzt `dev/input.sh` nur den headless Modus (natives Backend). `dev/fake-ding.py` startet ein Fenster wie Desktop Icons, um die Stapelung zu prüfen.