Commit graph

33 commits

Author SHA1 Message Date
a64c801275 Podcast-Radio: die neueste ungehörte Strom-Folge, ohne Spuren (eigene Radio-gehört-Liste, gemischt nach Podcasts, neue Folgen zuerst); Web-Player und Player-Sync; sw v153
Some checks failed
Build and push Docker image / build (push) Failing after 0s
Test / test (push) Failing after 0s
Test / e2e (push) Failing after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 13:17:09 +01:00
89827086ba Gezeichnete Cover: neue Konzepte (funk, musik, kunst, essen, sport, geld, reise), zweite Motive für die meisten; quadratisch für Hörbücher und Podcasts ohne (ladbares) Bild; sw v152
Some checks failed
Build and push Docker image / build (push) Failing after 0s
Test / test (push) Failing after 0s
Test / e2e (push) Failing after 0s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:39:57 +01:00
58003057e3 KI: OpenRouter als zweiter Anbieter (wählbar, chat completions mit json_schema); ✦ Mit KI ordnen für Podcasts (Ordner, Stufen) und Nachrichten/Blogs (Ressort, Ordner, Art); sw v149
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 18s
Test / test (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-25 12:23:54 +01:00
de50debad9 Podcasts im Browser: Mit Projekt verknüpfen (Folgen, Player mit Zeitmarke), Merken in der Folgenansicht (diora-android 4f514cd); sw v142
Some checks failed
Test / test (push) Waiting to run
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 20:19:22 +02:00
6e5092ab3f Podcasts im Browser: Stöbern, Lieblings-Abos, Suche → Folgenansicht (diora-android 1c1ec4e); podcasts-web.js speichert folders, refresh_interval, favorite; sw v140
Some checks failed
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 10m8s
Test / e2e (push) Failing after 1m19s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 19:17:33 +02:00
3c9185689a Podcasts im Browser: Wiedergabeliste · Merkliste · Strom · Abos (diora-android ef914bd), sw v137
Some checks failed
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 9m44s
Test / e2e (push) Failing after 1m24s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 18:21:03 +02:00
ba3c6ff905 Podcasts: Folgen einer Kategorie (?folder=), wie oft ein Podcast erscheint (interval_days) für „Nach Zeitraum, seltene zuerst“
Some checks failed
Test / e2e (push) Waiting to run
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Has been cancelled
- GET /podcasts/episodes/?folder=<name> ('' = ohne Ordner)
- /podcasts/state/: interval_days je Feed (mittlerer Abstand der neuesten 10 Folgen,
  eine Abfrage per Window, eine Stunde gemerkt)
- Podcast-Oberfläche aus diora-android bd98557 (Zeiträume, Ordner-Chips in „Folgen“)
- docs/library.md, sw v134

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-19 17:23:06 +02:00
4e4fac227c Podcast-UI aus diora-android 449118c (Ordner-Chips, ein Kopf je Bereich); E-Ink: Art-Abzeichen in Abos & Quellen lesbar
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 9m5s
Test / e2e (push) Successful in 2m50s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 21:06:41 +02:00
d7930fcdb9 Bibliothek ordnen (Navigation Phase 3): Hörbuch-Reihen und -Ordner, Zeitschriften je Heft
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 8m58s
Test / e2e (push) Successful in 1m57s
- Hörbücher: Reihen werden aus den Titeln erkannt („Das Kapital – Erster
  Band“, „…: Teil 3“, „… – Folge 12“, „Der Zauberberg. Erster Band“) und als
  Stapel gezeigt, darin die Bände in Reihenfolge. Ordner je Hörbuch
  (PodcastFeed.folder, Migration 0020), im Buch über ⋮ → Ordner zuweisen.
- Zeitschriften: ein Heft wird als Zeitschrift markiert (⋮ → Als Zeitschrift
  führen, im verschlüsselten Meta); unmarkiert entscheidet weiter der Ordner
  „Zeitschriften“. Die Hefte stehen nach Zeitschrift gruppiert, neueste zuerst.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:45:14 +02:00
143950df94 Abos & Quellen: alle Abos an einem Ort (Navigation Phase 2)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m58s
Test / e2e (push) Successful in 1m58s
Ein neuer Abschnitt (docs/sources.md, static/js/sources.js) für Podcasts,
YouTube-Kanäle, Hörbücher, Nachrichten und Blogs:
- ein Feld zum Hinzufügen: Adresse (Feed, Seite, YouTube) oder Name eines
  Podcasts; die Art ist wählbar (Podcast, Hörbuch, Nachrichten, Blog);
  /feeds/discover/ erkennt dafür Podcasts (Folgen mit Ton oder Video);
- eine Liste aller Abos mit Filtern (auch „Probleme“) und Suche;
- je Abo: Inhalt öffnen, Einstellungen (die vorhandenen Editoren), Art ändern,
  abbestellen; OPML-Import und -Export.
In der Seitenleiste unten, auf dem Telefon im App-Menü; ⚙ in den Feeds führt
hierher. Abschnitte, die beim Laden schon gezeigt werden, füllen sich jetzt
auch (nav.js zeigt sie nach dem Laden aller Skripte noch einmal).
Podcast-UI aus diora-android 50c6f9c.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 15:23:12 +02:00
a48dca07ea Navigation: diora Reader zeigt die Lesen-Abschnitte in seiner Leiste; Podcast-UI aus diora-android 26f5019
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m59s
Test / e2e (push) Successful in 2m0s
Auf dem tolino stehen Bücher, Zeitschriften, Nachrichten, Blogs direkt in der
Leiste unten (html.nav-flat, keine Abschnittszeile: auf E-Ink nicht wischen).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 14:53:38 +02:00
5be1b3fbaf Hörbücher: Podcasts als Hörbuch markieren und in „Bücher“ hören
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m52s
Test / e2e (push) Successful in 1m59s
Ein Abo lässt sich als Hörbuch (oder Hörspiel) markieren (PodcastFeed.kind).
Es verlässt dann die Podcast-Welt: keine „Neu“-Folgen, keine Warteschlangen-
Automatik, nicht in „Folgen“. In der Bibliothek steht es neben den E-Books
(static/js/audiobooks.js, eine Datei für Web, Desktop und Android):
„Weiterhören“, ein Fortschritt pro Buch, die Kapitel in Reihenfolge,
Lesezeichen mit Notiz, Schlummer bis Kapitelende.

Server: /podcasts/audiobooks/ (+<id>/), /podcasts/bookmarks/…, Migration 0019.
Player (podcasts-web.js): podcastPlayBook spielt die Kapitel nacheinander
außerhalb der Warteschlange; ⏭ markiert nicht als gehört. Vertrag:
docs/audiobooks.md. native-podcast.js aus diora-android 7b1d500.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-16 13:05:00 +02:00
b8a68c63db Podcast-Oberfläche aus diora-android 6a02899 (Vorlesen in der Leiste, Zurück auf dem Podcast-Tab, Farbvariablen); sw v103
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 8m19s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-14 18:05:23 +02:00
080cdbde5a Podcast-Oberfläche aus diora-android 5821dfa (__dioraPlayerNow für den Bildschirmschoner); sw v101
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 8m21s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 20:05:13 +02:00
8b9c28cda1 Home: neue Startseite mit Weiterlesen, Weiterhören, Radio-Favoriten und Ambient; sw v87
Some checks failed
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Has been cancelled
- static/js/home.js rendert #tab-home aus dem, was die Seite schon hat:
  zuletzt gelesenes Buch (und drei weitere), laufende oder nächste Folge mit
  Restzeit und „N neue Folgen“, Favoriten-Sender (sonst die ersten
  gespeicherten) und zuletzt gehörter Sender, Drift mit der zuletzt
  gewählten Klangwelt und Sleep-Timer. Läuft im Browser, in diora desktop und
  in der Android-App (dort mit static/js/ kopiert).
- app.js: Tab 'home' (TOP_TABS), window.__dioraAmbientStart() lädt Drift bei
  Bedarf und startet es; die gewählte Klangwelt wird gemerkt und beim Laden
  wiederhergestellt.
- podcasts-web.js: Startseite Home, wenn nichts anderes gewählt ist.
- native-podcast.js aus diora-android 7dcc0c6 (Home in der Startseiten-Wahl,
  __dioraPodcastView).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 15:34:02 +02:00
6cc62fd4d1 Podcasts: Stille-Schalter im Tempo-Menü, Leiste folgt dem, was spielt, podcastPause; sw v85
All checks were successful
Build and push Docker image / build (push) Successful in 14s
Test / test (push) Successful in 6m58s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 12:25:27 +02:00
6e28312947 Ambient in der Player-Leiste; weniger Aussetzer bei den Klangwelten auf Telefonen; sw v80
Some checks failed
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Has been cancelled
- app.js: __dioraAmbientInfo (spielt, zuletzt gestartet, Klangwelt), meldet Moduswechsel
  an die Leiste; Radio/Folge übernimmt sie wieder
- Drift (Telefone): Musik-Bett, Delay und Hall werden vom Ausgang getrennt, wenn eine
  Klangwelt ohne sie läuft (Braunes Rauschen …); Zugfahrt und Herzschlag planen 2,5 s voraus

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 00:18:06 +02:00
794dbadbf5 Ambient: Sleep-Timer zählt und stoppt Drift (Browser und App), ☾ im Ambient-Tab; sw v74
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 6m55s
- app.js: __dioraAmbientCmd, meldet Start/Stopp an die App (DioraNative.ambientState,
  sie hält Drift bei ausgeschaltetem Bildschirm am Laufen) und an den Browser-Host
- podcasts-web.js: der Sleep-Timer zählt auch, solange Ambient spielt, stoppt es beim
  Ablauf; Nachtautomatik auch beim Ambient-Start

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 23:22:00 +02:00
b7a81f3e26 Neuer Tab „Ambient“: Drift, ein generativer Ambient-Synthesizer; sw v73
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 6m55s
- static/ambient/index.html: Drift (aus der Session "Ambient-Synthesizer-Webapp",
  eine Datei, Web Audio, offline), eingebettet per iframe (?embed=1&bg=#000)
- app.js: Tab 'ambient', iframe lädt beim ersten Öffnen und füllt den Platz bis
  zur Leiste; Radio/Podcast und Ambient wechseln sich ab (postMessage
  {type:'ambient', cmd|state})
- sw.js: Ambient im Offline-Cache (ignoreSearch für die Shell-Dateien)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 23:08:57 +02:00
64e9d70647 Podcasts: mehrere Folgen nacheinander wegwischen, während „Rückgängig“ steht; sw v72
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 6m51s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 14:40:39 +02:00
f12451f30e Sleep-Timer: eigene Zeit, Nachtfenster, auch fürs Radio, von anderen Geräten setzen; sw v70
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 6m54s
- Player-Sync: Aktion 'sleep' (Minuten, -n Folgen, 0 aus); Reports schicken
  sleep {left_ms, episodes} mit, der State zeigt ihn (Migration 0016)
- Browser-Host: Nachtfenster sleep_from/sleep_to, Automatik auch beim
  Radiostart (auch in diora desktop), Timer des anderen Geräts zählt mit,
  ein Timer, der stundenlang nicht lief, verfällt
- Eingabefenster (customPrompt) liegt über Player und Menüs

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 12:59:16 +02:00
985e635f9a Podcasts: "Folge löschen" (episodes/discard/, discarded in state/), Folgen-Seite, sw v69
All checks were successful
Build and push Docker image / build (push) Successful in 13s
Test / test (push) Successful in 6m52s
- EpisodeProgress.discarded_at (Migration 0015); POST /podcasts/episodes/discard/
  {"episode_ids": [...]}: aus der Warteschlange (_dequeue, auch von queue/remove benutzt)
  und aus "Neu" (dismissed), discarded_at = jetzt; gehört, Stelle, Stern und updated_at
  bleiben; fremde Folgen werden ausgelassen (count)
- state/ liefert "discarded": [{id, at}] der letzten 30 Tage: jedes Gerät löscht seine
  ältere Datei; wieder eingereiht (_enqueue) wird discarded_at gelöscht
- Browser-Host: podcastDiscard (pausiert geladene Folge verlässt den Player, laufende spielt
  zu Ende), podcastPlayEpisodeAt (Kapitel auf der Folgen-Seite)
- static/podcasts aus diora-android ee1a910 (Folgen-Seite, Folge löschen, Datei löschen,
  Wischtexte und Icons, Ziehgriff)
- Tests: DiscardTests

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 20:27:24 +02:00
e097e13a11 Podcast-Oberfläche aus diora-android 339de8f (Podcast-Seite mit ⚙, Wischgesten, Schrift, Farben, Startseite); „Neu“ zählt alle neuen Folgen, sw v66
- state/ liefert inbox_total (alle neuen Folgen) und inbox_limit neben der
  gekürzten Liste; Test dazu.
- Browser: Startseite (nui_start_page) beim Öffnen, „Rückgängig“-Leiste über
  der Radioleiste, helle Ansicht für die neuen Teile.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 19:30:03 +02:00
54fbd58293 Podcast-Routine aus AntennaPod: Abspiel-Einstellungen fürs Konto, Listen und Stille pro Podcast; Oberfläche aus diora-android 304abf0, sw v65
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 6m39s
- PodcastSettings (Migration 0014): skip_back / skip_forward (5–60 s),
  smart_played, speed_presets (0,5–3,5×), keep_skipped, delete_dequeue,
  mobile_downloads, mobile_streaming (allow/ask/never), times_by_speed;
  die ersten vier sind anfangs leer (null) und werden mit POST
  settings/ {"initial": {...}} nur dort gesetzt, wo noch nichts steht
- GET/POST /podcasts/settings/ und state.settings mit allen Feldern,
  geprüft, nichts ändert sich bei einem ungültigen Wert
- PodcastFeed: episode_sort, episode_filter, skip_silence in
  feeds/<id>/settings/ und den Feeds des States
- Tempo pro Podcast bis 3,5× (Server und AntennaPod-Import)
- AntennaPod-Import: Sortierung, Filter und Stille pro Podcast, soweit
  diora sie zeigen kann; nicht darstellbare werden gezählt
- Browser-Host: Sprungweiten, "gehört" und keep_skipped aus dem Konto,
  Tempo bis 3,5×, neue Einstellungen werden gespeichert

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 18:46:55 +02:00
3577fca9ba Merge branch 'wt-notify'
All checks were successful
Build and push Docker image / build (push) Successful in 16s
Test / test (push) Successful in 6m28s
# Conflicts:
#	static/js/sw.js
#	static/podcasts/native-podcast.js
2026-10-02 18:03:07 +02:00
da60198bbb Podcast-Oberfläche aus diora-android (Benachrichtigen), sw v61
Der Chip "Benachrichtigen" auf der Podcast-Seite setzt notify auch im
Browser (die Mitteilungen kommen von den Telefonen). Die Einstellung
"Im Hintergrund abgleichen" gibt es nur in der App.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:36:00 +02:00
d3e432e165 Podcast-Oberfläche aus diora-android 3d1281c (Listen + Abonnieren-Vorschau), sw v63
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 6m21s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:29:15 +02:00
69b22cf2e3 Podcast-Listen: Zähler pro Abo, kombinierbare Folgen-Filter, Suche in Shownotes, mehrere Favoriten; Oberfläche aus diora-android, sw v62
- feeds/ und state/: pro Abo episode_count, unplayed_count, new_count (wie
  „Neu“), last_played_at und link – zwei Abfragen, egal wie viele Abos.
- feeds/<id>/episodes/: favorite pro Folge; description, link, rss_url und
  last_refreshed_at des Podcasts für die Infoseite.
- episodes/: filter mit Komma kombinierbar (alle müssen passen), neuer Filter
  queued, ids= (die auf einem Gerät geladenen), sort= (new, old, long, short,
  title, played), notes=1 sucht q auch in den Shownotes (Titeltreffer zuerst).
- POST episodes/favorite/: mehrere Folgen auf einmal (ent)favorisieren.
- Tests dafür; Podcast-Oberfläche aus diora-android übernommen.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 16:23:00 +02:00
3eb6a27ec3 Player-Sync: ein Player für alle Geräte (wie Spotify Connect)
Server: PlayerState und PlayerDevice (Migration 0012), /podcasts/player/
(Stand), report/ (das Gerät, das zu spielen anfängt, wird das aktive und
bleibt es auch pausiert, solange es online ist), command/ (Fernbedienung,
transfer auf ein anderes Gerät) und stream/ (Server-Sent Events, zugleich
die Anwesenheit der Geräte). seq steigt in einem UPDATE und nie zurück.

Browser: podcasts-web.js meldet Abspielen, Pause, Springen, Folgen- und
Senderwechsel (alle 10 s beim Spielen), hört den Stream, hört auf, wenn ein
anderes Gerät startet, führt Befehle aus, zeigt das andere Gerät als remote
und übernimmt, was ein verschwundenes Gerät zuletzt hatte. Eine pausierte
Folge folgt einem neueren Stand von anderswo; im Vordergrund wird nach
15 s neu geholt. Podcast-Seite neu kopiert, sw v58.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 15:18:38 +02:00
649cf0f340 AntennaPod-Import: --replace für einen Neuanfang; Podcast-Oberfläche aus diora-android 6c2b071
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 5m19s
--replace bestellt Podcasts ab, die das Backup nicht hat, behält nur
AntennaPods Warteschlange und lässt AntennaPod auch über spätere
Änderungen in diora gewinnen. Die Oberfläche bringt den gemeinsamen
Player und die Download-Übersicht (nur in der App sichtbar). sw v54.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 12:44:49 +02:00
35ea42b6c2 Podcast-Oberfläche aus diora-android f94c501 (Downloads einreihen), sw v53
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 4m59s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 11:46:37 +02:00
ae0785d5ef Podcast-Oberfläche neu aus diora-android übernommen (Hinweistext ohne „App“)
All checks were successful
Build and push Docker image / build (push) Successful in 15s
Test / test (push) Successful in 4m37s
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:30:00 +02:00
76a164709d Podcasts im Browser: die Podcast-Seite der App statt des alten Podcast-Tabs
Der Podcast-Tab der Web-App zeigt jetzt dieselbe Oberfläche wie die
Android-App: native-podcast.js aus diora-android, unverändert kopiert nach
static/podcasts/ (tools/sync_podcast_ui.py, mit Quell-Commit im Kopf),
dazu die Podcast-Teile von native.css.

static/js/podcasts-web.js spielt im Browser die Rolle der App
(window.DioraPodcastHost statt DioraNative):
- Zustand aus /podcasts/state/, in localStorage für einen schnellen Start;
  Änderungen sofort lokal und der Reihe nach an den Server (Outbox, übersteht
  Neuladen und Offline), wie Podcasts.kt, inkl. „immer sortiert halten“
- eigener Player (nicht das Radio-Audio-Element), Warteschlange = Playlist,
  wie RadioService.EpisodeTracker: Stelle fortsetzen, Intro/Outro, Fortschritt
  alle 10 s und bei Pause, „gehört“ kurz vor Schluss (auch bei „nächste“),
  automatisch weiter, nach Pause etwas zurück (0,8/3/10/20 s), Tempo und
  Lautstärke (bis 1) pro Podcast, Sleep-Timer nur während des Abspielens mit
  Ausblenden
- Sperrbildschirm und Medientasten über navigator.mediaSession
- Abspiel-Einstellungen dieses Geräts in localStorage (wie PlaybackPrefs)
- keine Downloads (die Oberfläche blendet sie aus)
- Radio und Podcast nie gleichzeitig: eine Folge stoppt das Radio, ein Sender
  legt die Folge weg
- Bottom-Sheet und Mini-Player-Dock über der Radio-Leiste; auf breiten
  Bildschirmen eine mittige Spalte (760 px)

In der App und der Desktop-App (window.DioraNative vorhanden) tut
podcasts-web.js nichts.

Entfernt: der alte Podcast-Tab (Markup, ~1000 Zeilen in app.js, CSS), die
Podcast-Leiste im Player, INITIAL_PODCAST_FEEDS und das Herunterladen von
Folgen in den Browser-Cache (der Service Worker räumt diora-podcast-v1 ab).
Service-Worker-Cache auf v52, neue Dateien im App-Shell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-02 10:26:32 +02:00