feat(studio): show module origin store ('from <store>')

StoreItem gains source (mapped from StoreEntry.source); the store grid
shows a 'from <store>' label for operator-added stores (bundled seed
unlabelled). Foundation for grouping by store. EN+DE l10n.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-22 00:59:51 +02:00
parent 255348c062
commit 27cf7e8382
7 changed files with 44 additions and 0 deletions

View file

@ -786,6 +786,7 @@ class HubService {
kind: e.kind, kind: e.kind,
provider: e.provider, provider: e.provider,
sourceKind: e.sourceKind, sourceKind: e.sourceKind,
source: e.source,
), ),
) )
.toList(); .toList();
@ -1793,6 +1794,12 @@ class StoreItem {
/// from `kind` for pre-0.12 hubs. /// from `kind` for pre-0.12 hubs.
final String sourceKind; final String sourceKind;
/// Name of the store this entry came from ("bundled" for the built-in
/// seed, otherwise the operator-added store's name). Distinct from
/// `sourceKind` (the transport) this is the ORIGIN store, used to
/// label and group modules by where they came from.
final String source;
bool get isFederated => kind == 'federated'; bool get isFederated => kind == 'federated';
const StoreItem({ const StoreItem({
@ -1817,5 +1824,6 @@ class StoreItem {
required this.kind, required this.kind,
required this.provider, required this.provider,
this.sourceKind = '', this.sourceKind = '',
this.source = '',
}); });
} }

View file

@ -2,6 +2,7 @@
"@@locale": "de", "@@locale": "de",
"errModuleDownload": "Modul-Download fehlgeschlagen", "errModuleDownload": "Modul-Download fehlgeschlagen",
"errModuleDownloadHint": "Die Bundle-URL des Moduls ist nicht erreichbar (Statuscode unten). Der Hub läuft — URL/Host korrigieren oder anderen Store wählen.", "errModuleDownloadHint": "Die Bundle-URL des Moduls ist nicht erreichbar (Statuscode unten). Der Hub läuft — URL/Host korrigieren oder anderen Store wählen.",
"storeFromSource": "aus {store}",
"guidedSetupTitle": "Setup-Assistent", "guidedSetupTitle": "Setup-Assistent",
"guidedSetupIntro": "Beantworte drei Fragen — Ch∆In stellt passende Konfiguration, Modul-Set und Start-Flow zusammen.", "guidedSetupIntro": "Beantworte drei Fragen — Ch∆In stellt passende Konfiguration, Modul-Set und Start-Flow zusammen.",
"guidedSetupScenario": "Szenario", "guidedSetupScenario": "Szenario",

View file

@ -2,6 +2,12 @@
"@@locale": "en", "@@locale": "en",
"errModuleDownload": "Module download failed", "errModuleDownload": "Module download failed",
"errModuleDownloadHint": "The module's bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.", "errModuleDownloadHint": "The module's bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.",
"storeFromSource": "from {store}",
"@storeFromSource": {
"placeholders": {
"store": { "type": "String" }
}
},
"guidedSetupTitle": "Setup assistant", "guidedSetupTitle": "Setup assistant",
"guidedSetupIntro": "Answer three questions and Ch∆In assembles a tailored config, module set and starter flow.", "guidedSetupIntro": "Answer three questions and Ch∆In assembles a tailored config, module set and starter flow.",
"guidedSetupScenario": "Scenario", "guidedSetupScenario": "Scenario",

View file

@ -110,6 +110,12 @@ abstract class AppLocalizations {
/// **'The module\'s bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.'** /// **'The module\'s bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.'**
String get errModuleDownloadHint; String get errModuleDownloadHint;
/// No description provided for @storeFromSource.
///
/// In en, this message translates to:
/// **'from {store}'**
String storeFromSource(String store);
/// No description provided for @guidedSetupTitle. /// No description provided for @guidedSetupTitle.
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View file

@ -15,6 +15,11 @@ class AppLocalizationsDe extends AppLocalizations {
String get errModuleDownloadHint => String get errModuleDownloadHint =>
'Die Bundle-URL des Moduls ist nicht erreichbar (Statuscode unten). Der Hub läuft — URL/Host korrigieren oder anderen Store wählen.'; 'Die Bundle-URL des Moduls ist nicht erreichbar (Statuscode unten). Der Hub läuft — URL/Host korrigieren oder anderen Store wählen.';
@override
String storeFromSource(String store) {
return 'aus $store';
}
@override @override
String get guidedSetupTitle => 'Setup-Assistent'; String get guidedSetupTitle => 'Setup-Assistent';

View file

@ -15,6 +15,11 @@ class AppLocalizationsEn extends AppLocalizations {
String get errModuleDownloadHint => String get errModuleDownloadHint =>
'The module\'s bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.'; 'The module\'s bundle URL is unreachable (status code below). The hub is running fine — fix the URL/host or choose another store.';
@override
String storeFromSource(String store) {
return 'from $store';
}
@override @override
String get guidedSetupTitle => 'Setup assistant'; String get guidedSetupTitle => 'Setup assistant';

View file

@ -1930,6 +1930,19 @@ class _StoreCardState extends State<_StoreCard> {
color: theme.colorScheme.onSurfaceVariant, color: theme.colorScheme.onSurfaceVariant,
), ),
), ),
// Origin store ("from <store>") only for
// operator-added stores; the built-in seed
// ("bundled") needs no label.
if (item.source.isNotEmpty &&
item.source != 'bundled')
Text(
l.storeFromSource(item.source),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.labelSmall?.copyWith(
color: theme.colorScheme.onSurfaceVariant,
),
),
], ],
), ),
), ),