Typing lessons like duolingo & musicmouse cleanup

This commit is contained in:
2026-09-12 18:58:02 +02:00
parent 498243af46
commit a5210fead2
50 changed files with 3074 additions and 710 deletions

View File

@@ -297,13 +297,17 @@ def _build_app(
return app
def _service_of_type[T: Service](services: list[Service], kind: type[T]) -> T | None:
return next((s for s in services if isinstance(s, kind)), None)
def _analysis_batch_hook(services: list[Service]) -> Callable[[], Awaitable[None]] | None:
"""The web front-end's own hub, if it is running - so open tabs refetch the library
as background analysis lands, instead of only after a manual reload. `None` when
there is no web service, which `MusicLibrary.analyze_pending` treats as "nobody to
tell".
"""
web_service = next((s for s in services if isinstance(s, WebService)), None)
web_service = _service_of_type(services, WebService)
return web_service.hub.broadcast_library if web_service else None
@@ -339,7 +343,7 @@ def _build_services(
# Unconditional: a show only starts downloading once someone drops a `feed.txt`
# into its folder, so there is nothing to gate here with its own config section.
web_service = next((s for s in services if isinstance(s, WebService)), None)
web_service = _service_of_type(services, WebService)
services.append(
PodcastFeedService(
app.library,