feat(studio): inline README + per-module update badge in Store (v0.19.0)

Two Phase-2 Store improvements that operators feel
immediately:

- Per-module update badge: store cards compare the operator's
  installed version against the index's `best_version`, raise
  an "update" pill + "Update to vX.Y.Z" button when newer is
  available. Result: a single glance at the Store reveals
  what's behind. The page now fetches `listModules` in
  parallel with the search so the comparison is on the
  current snapshot.

- Inline README rendering: detail sheet has a new
  Documentation section. "Load documentation" button (lazy —
  no network until clicked) calls FetchModuleDocs and renders
  the markdown via flutter_markdown, with the operator's
  theme colors and link-tap routed through SystemActions.
  Auth / not-found / network failures fall back to a
  friendly fix-hint panel + "Open repository in browser"
  button so the operator never hits a dead end.

Adds flutter_markdown ^0.7.7 to pubspec; the package is
maintenance-only upstream but is the only mature option
for Material-themed markdown right now. Easy to swap to
markdown_widget if/when we need GitHub-flavored extras.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-07 20:46:16 +02:00
parent 93926741b1
commit 04cc12bc54
5 changed files with 335 additions and 16 deletions

View file

@ -326,6 +326,19 @@ class HubService {
return (name: r.name, version: r.version);
}
/// Fetch a module's README markdown via the hub. Errors come
/// back as `errorKind` strings (not exceptions) so callers can
/// render fallback UI without try/catch ceremony.
Future<({String errorKind, String text, String sourceUrl})>
fetchModuleDocs(String name) async {
final r = await _client.fetchModuleDocs(name);
return (
errorKind: r.errorKind,
text: r.text,
sourceUrl: r.sourceUrl,
);
}
/// Active channel + per-channel daemon status snapshot.
Future<ChannelStatusSnapshot> channelStatus() async {
final r = await _client.channelStatus();