feat(studio): generic Today stories + auto-hide after 3 modules + brand chips out + editor 0.13.0
Some checks failed
Security / Security check (push) Failing after 2s

Two visible UX shifts:

1. Store Today carousel.
   - Three hardcoded stories rewritten to be generic:
     'Modules are the building blocks',
     'Flows chain modules deterministically',
     'Bring your own sources' — no DeepWiki / Semgrep /
     text.extract / extract-summarize.yaml mentions. The
     concrete brand suggestions live in Settings → MCP
     Clients where the operator goes deliberately.
   - +DeepWiki / +Semgrep quick-add chips removed from
     the hero footer. They felt like ads on every page
     load. The standalone Suggested Sources strip below
     still picks them up, but the editorial hero stays
     clean.
   - Auto-hide the entire carousel once installedCount
     ≥ 3 — the operator has demonstrably been here
     before; the welcome strip stops earning its scroll
     cost.

2. Editor bump to 0.13.0:
   - Edge selection (click a wire to select it)
   - Properties panel edge-info mode with type-compat
     indicator + Disconnect button
   - Canvas-wide background tap closes the panel (works
     even when zoomed out so the grid doesn't fill the
     viewport)

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-02 15:23:23 +02:00
parent 3db875c903
commit 2731062a13
3 changed files with 56 additions and 35 deletions

View file

@ -310,12 +310,27 @@ class _StorePageState extends State<StorePage> {
_source.isEmpty &&
!_installedOnly;
final hasNoFederation = !raw.any((e) => e.isFederated);
final showToday = !_todayDismissed && isBrowsing;
// Past-onboarding signal: the operator has
// 3+ modules installed (wasm + federated
// combined). At that point the editorial
// hero stops earning its scroll cost they
// know what FI does. They can still bring
// it back via the "Tour" button (TODO) or
// by clearing _todayDismissed in prefs.
final installedCount = raw
.where((e) => e.installed)
.length;
final pastOnboarding = installedCount >= 3;
final showToday =
!_todayDismissed && isBrowsing && !pastOnboarding;
// Recommended-source quick-adds are inlined in
// the Today footer when both apply, so the
// operator never sees two competing editorial
// cards stacked on top of each other.
final embedRecommended = showToday && hasNoFederation;
// (Hero footer no longer carries the chips
// brand-name suggestions only show in the
// standalone "Suggested sources" strip below
// and via Settings MCP Clients.)
// Standalone strip only fires in the corner
// case: Today dismissed AND no federation.
// Featured strip and Today never compete
@ -377,9 +392,15 @@ class _StorePageState extends State<StorePage> {
TodayCta.openSettings
? () => FaiSettingsDialog.show(context)
: null,
recommendedSources: embedRecommended
? _kRecommendedSources
: const <_RecommendedSource>[],
// Quick-add chips removed from the
// editorial hero they showed the
// same DeepWiki / Semgrep names every
// session, which felt like ads. Public
// sources still live one click away
// under Settings MCP Clients, and
// the standalone "Suggested sources"
// strip below picks them up.
recommendedSources: const <_RecommendedSource>[],
recommendedAdding: _addingSources,
onAddRecommended: _addRecommendedSource,
),
@ -2905,47 +2926,47 @@ class _ScreenshotPlaceholder extends StatelessWidget {
/// on the dedicated Welcome page, not in the store carousel.
const List<TodayStoryData> _kFallbackTodayStories = <TodayStoryData>[
TodayStoryData(
badgeEn: 'PUBLIC SOURCES',
badgeDe: 'ÖFFENTLICHE QUELLEN',
titleEn: 'Fill your store in two clicks',
titleDe: 'Den Store in zwei Klicks auffüllen',
badgeEn: 'MODULES',
badgeDe: 'MODULE',
titleEn: 'Modules are the building blocks',
titleDe: 'Module sind die Bausteine',
bodyEn:
'Right now the store shows only the modules that ship with the hub. Pick a public source from the buttons below and the store fills with whatever tools that server offers — straight over HTTPS, no install steps, nothing to configure.',
'Each tile in the grid below is a sandboxed WASM module. Pick one, hit Install, and the hub adds it to your local registry. Modules declare their permissions up front; the hub denies anything else.',
bodyDe:
'Im Moment zeigt der Store nur die Module, die mit dem Hub mitkommen. Wähle unten eine öffentliche Quelle aus, und der Store füllt sich mit allem, was dieser Server an Tools anbietet — direkt über HTTPS, ohne Installation, ohne weitere Konfiguration.',
ctaLabelEn: 'Manage sources',
ctaLabelDe: 'Quellen verwalten',
icon: Icons.hub_outlined,
cta: TodayCta.openSettings,
),
TodayStoryData(
badgeEn: 'TEXT MODULES',
badgeDe: 'TEXT-MODULE',
titleEn: 'Three text modules already in the store',
titleDe: 'Drei Text-Module sind schon im Store',
bodyEn:
'text.extract pulls plain text from PDFs and DOCX. text.summarize turns long material into a short briefing via your configured System AI. text.translate moves text between languages. All three install in one click from the grid below — search for "text" to find them.',
bodyDe:
'text.extract holt Plaintext aus PDFs und DOCX. text.summarize verdichtet lange Texte über die konfigurierte System-AI zu einem Briefing. text.translate übersetzt zwischen Sprachen. Alle drei lassen sich aus dem Grid unten mit einem Klick installieren — suche nach „text".',
'Jede Kachel unten ist ein sandboxes WASM-Modul. Auswählen, Installieren klicken — der Hub fügt es deiner lokalen Registry hinzu. Module deklarieren ihre Berechtigungen explizit; der Hub verweigert alles andere.',
ctaLabelEn: '',
ctaLabelDe: '',
icon: Icons.menu_book_outlined,
icon: Icons.extension_outlined,
cta: TodayCta.none,
),
TodayStoryData(
badgeEn: 'SAMPLE FLOW',
badgeDe: 'BEISPIEL-FLOW',
titleEn: 'Try the extract → summarize flow',
titleDe: 'Probier den Extract → Summarize-Flow',
badgeEn: 'FLOWS',
badgeDe: 'FLOWS',
titleEn: 'Flows chain modules deterministically',
titleDe: 'Flows verknüpfen Module deterministisch',
bodyEn:
'The bundled `flows/extract-summarize.yaml` chains text.extract into text.summarize so a PDF in one end produces a short briefing at the other. Open the Flows tab, hit Run, point it at any document — the result lands as plain text plus an audit-log trail of which modules ran with which inputs.',
'A flow is a YAML file with three keys — inputs, steps, outputs. Each step calls one module. Every run lands in the audit log with a verifiable hash chain. Build flows graphically or write the YAML directly — either way, the run is reproducible.',
bodyDe:
'Der mitgelieferte Flow `flows/extract-summarize.yaml` reicht text.extract an text.summarize weiter — vorne kommt ein PDF rein, hinten kommt ein kurzes Briefing raus. Flows-Tab öffnen, Run klicken, beliebiges Dokument auswählen; das Ergebnis ist Klartext plus Audit-Spur welcher Modul-Schritt mit welchen Eingaben gelaufen ist.',
'Ein Flow ist eine YAML-Datei mit drei Schlüsseln — inputs, steps, outputs. Jeder Schritt ruft ein Modul auf. Jeder Lauf landet im Audit-Log mit verifizierbarer Hash-Kette. Flows grafisch bauen oder direkt YAML schreiben — der Lauf bleibt reproduzierbar.',
ctaLabelEn: '',
ctaLabelDe: '',
icon: Icons.account_tree_outlined,
cta: TodayCta.none,
),
TodayStoryData(
badgeEn: 'EXTENSIBILITY',
badgeDe: 'ERWEITERBAR',
titleEn: 'Bring your own sources',
titleDe: 'Eigene Quellen anbinden',
bodyEn:
'The hub federates external module sources — public MCP servers, n8n workflows, your own internal registry. Configure a source under Settings → MCP Clients and its tools appear in this store alongside the built-in modules. Same install button, same audit trail.',
bodyDe:
'Der Hub bindet externe Modul-Quellen ein — öffentliche MCP-Server, n8n-Workflows, eigene interne Registries. Eine Quelle unter Einstellungen → MCP-Clients konfigurieren, und ihre Tools erscheinen hier im Store neben den eingebauten Modulen. Gleicher Install-Button, gleiche Audit-Spur.',
ctaLabelEn: 'Manage sources',
ctaLabelDe: 'Quellen verwalten',
icon: Icons.hub_outlined,
cta: TodayCta.openSettings,
),
];
/// Editorial hero strip the first surface a browsing operator