JARVIS-UI
Aggiornamento 2.160
20/06/2026
v2.160.0.0MINORJarvis-UI
Fase A–C: ModuleRegistry + Workspace Ready (§17) + Icon Rail senza flyouts (§16) (Jarvis-UI)
- Consegna delle Fasi A–C del
docs/specs/EDITOR_UI_OVERHAUL_PLAN.md§16–§17 (decisioni Halyson 2026-06-20), conforme adocs/ai/PROMPT_UI_GLM_REMAINING_BACKLOG_2026-06-20.md. Ambito: architettura di navigazione + catalogo data-driven + iconografia — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocati; i 68 handlerMenuItem_*non refactorizzati (solo chiamati). Fase A — ModuleRegistry (fonte unica):ModuleCatalogPolicy.csevolve da stub documentale a catalogo autorevole — nuovopublic static class ModuleRegistryconIReadOnlyList<ModuleCatalogEntry> Allpopolato con 41 entries (Home + 10 Core Authoring + 5 Maps + 7 Live + 16 Extras + 2 Wave-1), una per modulo instradato nel rail.ModuleCatalogEntryottieneMode/Notes/Scope/Cluster(enumModuleCluster) oltre alId/Title/Description/IconKey/RequiresProjectoriginale. Copia fedele dei letterali di ogniSetModule(...)inMain_Window.axaml.cs(non reinventata). Politica doc-comment: nuovoMenuItem_*instradato = append nel registry (review blocker). Fase A — Iconografia:StudioIcons.axamlespanso da 14 → 54 icone (<StreamGeometry>Lucide-like, viewBox 24×24) — 1 metafora dedicata per modulo (spada+corni=monster, dischetto=save, teschio=enemy design, griglia hex=sphere grid, ecc.). Check di consistenza (script) conferma che tutti i 41IconKeys del registry si risolvono inStudioIcons. Fase B — §17 Workspace Ready:MainDashboard_Control.axamlsmette di avere 6 tile hardcoded e diventaItemsControl ItemsSource="{Binding Modules}"conDataTemplate(icona + Titolo + Descrizione completa + pill di Modalità).Main_DataModelottienepublic IReadOnlyList<ModuleCatalogEntry> Modules => ModuleRegistry.All. Due converter nuovi inFFXProjectEditor/Converters/:IconKeyToGeometryConverter(resolve string IconKey → Geometry percorrendoResources+MergedDictionariesviaTryGetResource(key, ActualThemeVariant, out )— necessário porque binding{DynamicResource {Binding IconKey}}não funciona paraPathIcon.Dataem Avalonia) eRequiresProjectEnabledConverter(IMultiValueConverterRequiresProject × IsProjectLoaded →IsEnabled). Hero + empty-state CTA + card de Workspace status preservados (§17.4). **Fase C — §16 Icon Rail sem flyouts:** removidos os 5Button.Flyout/MenuFlyoutdoIconRailCol(XAML L156–239) — substituídos por<StackPanel Name="RailStack">populado em code-behind porBuildIconRail()(1 botãorailIconpor entry, agrupado por cluster comBorder1px como separador).Popup#RailDrawer(narrow) troca a lista textual deButton Classes="nav"por<WrapPanel Name="RailDrawerGrid">(grid de ícones). Handler únicoButton_RailModule_Click(sender, e)lêTag=Id→Dispatch(id).RefreshRailProjectGates()re-aplica o gateRequiresProjectquandoProject_Service.IsProjectLoadedmuda. **Fase C — Dispatch genérico:**OnQuickLaunchRequested(6 keys hardcoded: monster/kernel/sphere/save/extras/home) substituído porDispatch(string moduleId)com switch de **todos os 41 Ids** → handlerMenuItem*existente. Rail, drawer e dashboard passam pelo mesmo caminho. **Aceite:** build Release **0 erros** (402 warnings preexistentes); 0MenuFlyoutnoIconRailCol; 0 tile hardcoded no dashboard; 41 ícones renderizando no rail + 41 cards no home com ícone dedicado + descrição completa; cards desabilitados quandoRequiresProject && !IsProjectLoaded. **Bug visual corrigido:** os ícones não renderizavam inicialmente porqueApplication.Current.Resources.TryGetValue()em Avalonia 11 não percorreMergedDictionaries— fix viaResolveGeometry()helper compartilhado que itera os merged dicts comTryGetResource. [anterior:v2.159.6.1`]
v2.160.1.0PATCHJarvis-UI
Fase D1 chiusa: interfaccia `IRestorableModule` + rifattorizzazione `NavigationSnapshot` (Jarvis-UI)
- Primo commit della Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D1). Ambito: architettura di navigazione (back/forward ripristinabile) — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intatti. Nuovo contrattoFFXProjectEditor/Modules/Common/IRestorableModule.cs:CaptureState()→Dictionary<string,object?>?(null = stateless) eRestoreState(state)(idempotente, sicuro con null). Prima del D1, ilMain_Windoweffettuava un pattern-match su tipi concreti (MonEditorSelector_Control/KernelCommands_Control) per catturare lo stato — non scalabile per ~38 moduli. Ora ilMain_Windowchiede al controllo se esso èIRestorableModule. RifattorizzazioneNavigationSnapshot: diventarecord struct (string ModuleId, Dictionary<string,object?>? State); l'enumNavigationSurfaceKindè rimosso. Nuovo campoprivate string _currentModuleId = "home"impostato all'inizio diDispatch(string moduleId).CaptureCurrentNavigationSnapshot()generico tramiteContentFrame.Content is IRestorableModule;IsSameNavigationSurface()confronta soloModuleId;RestoreNavigationSnapshot()esegueDispatch(snapshot.ModuleId)+restorable.RestoreState(snapshot.State). 3 chiamate rotte corrette (ancora riferivanoNavigationSurfaceKind):MenuItem_MonsterMagic1/2(L560/568) →_currentModuleId = "battle-commands-hub"+new NavigationSnapshot("battle-commands-hub")(stessa struttura deiMenuItem_Commands/MenuItem_Itemsgià migrati);NavigateToMonsterEditor(L1549) →new NavigationSnapshot("monster-editor"). Onestà: back/forward continua a funzionare nei 3 originali (Home/Monster/KernelCommands), ma Monster/KernelCommands saranno solo pienamente ripristinab quando i loro controlli implementerannoIRestorableModule(D2/D4). Fino ad allora, lo snapshot viene creato ma ilStaterisultanull(torna al modulo, non ripristina la sotto-selezione). Build Release 0 errori (402 warning preesistenti). [precedente:v2.160.0.0]
v2.160.2.0PATCHJarvis-UI
Fase D2: `IRestorableModule` nei 7 editor semplici (Jarvis-UI)
- Secondo commit della Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D2). Ambito: back/forward ripristinabile in 7 editor Core Authoring — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocati. ImplementaIRestorableModule(definito in D1) in 7 controlli:TreasureEditor_Control,AutoAbilityEditor_Control,PlayerGrowthEditor_Control,CtbBaseEditor_Control,KeyItemEditor_Control,FormationEditor_Control,BukiGetTreasureCatalog_Control. OgniCaptureState()catturafilterText(stringa) +selectedIndex(int? derivato dall'elemento selezionato nella collezioneDisplayed*);RestoreState(state)ripristina il filtro (che ri-applica ilApplyFiltertramiteOnFilterTextChanged) e ri-seleziona la riga per indice. Mappatura per editor: Treasure (SelectedTreasure/DisplayedTreasures), AutoAbility (SelectedAbility/DisplayedAbilities), PlayerGrowth (SelectedCharacter/DisplayedCharacters), CtbBase (SelectedRow/DisplayedRows), KeyItem (SelectedItem/DisplayedItems), Formation (SelectedBattle/Battles— senzaDisplayed*), BukiGetTreasureCatalog (SelectedRow/DisplayedRows). Honestidade: agora Monster Editor + os 7 editores acima são plenamente restorable via back/forward (voltam pra seleção/filtro exatos). KernelCommands + os hubs (BattleCommands/Items/etc.) viram em D3 (SubTabHub). Build Release 0 erros (402 warnings preexistentes). [anterior:v2.160.1.0]
v2.160.3.0PATCHJarvis-UI
Fase D3: `IRestorableModule` nel `SubTabHub_Control` (copre 9 hub) (Jarvis-UI)
- Terzo commit della Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D3). Ambito: **back/forward ripristinabile in tutti gli hub basati emSubTabHub** — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocati.SubTabHub_Control.axaml.csimplementaIRestorableModule: nuovo campoint _activeTabIndextracciato inSelectTab(index);CaptureState()restituisce{["activeTab"] = _activeTabIndex};RestoreState(state)chiamaSelectTab(idx)(che ri-applica pill/active/hosted-content normalmente). Copertura automatica dei 9 hub: BattleCommandsHub, ItemsHub, SphereGridHub, TextHub, EnemyDesignHub, CustomizationsHub, StatsHub, EncountersHub, Blitzball — tutti usanoSubTabHub_ControltramiteAddTab(...), quindi tutti ottengono il ripristino della sotto-scheda attiva gratuitamente in un'unica modifica. Onestà: il contenuto interno di ogni sotto-scheda (filtro/selezione dell'editor ospitato) è responsabilità del controllo ospitato — se implementa anch'essoIRestorableModule(D2 ha coperto Treasure/KeyItem/etc.), ilMain_Windowconcatena il ripristino nella sequenza. Build Release 0 errori (402 warning preesistenti). [precedente:v2.160.2.0]
v2.160.4.0PATCHJarvis-UI
Fase D4: `IRestorableModule` in tutti i controlli rimanenti tramite metodi dell'interfaccia di default (Jarvis-UI)
- Quarto commit della Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D4). Ambito: dichiarare l'interfaccia in tutti i*_Controlrimanenti — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intatti.IRestorableModule.csottiene metodi dell'interfaccia di default:CaptureState() => nulleRestoreState(state) { }(stateless/no-op di default). Così, i controlli senza stato significativo (explorer read-only, hub, runtime lab, debug, tracker, 16 Extras, Wave-1, sotto-controlli) devono solo dichiarare, IRestorableModulenella firma —Main_Windowora può eseguireContentFrame.Content is IRestorableModulein qualsiasi modulo senza distinguere il tipo. Sweep automatizzato tramitework/_irestable_stateless_sweep_20260620.ps1: 65 controlli modificati (aggiungeusing FFXProjectEditor.Modules.Common;+: UserControl, IRestorableModule), 9 saltati (gli 8 già implementati in D1/D2/D3 +MonsterAiEditor2_Controldiscontinuato). Trasparenza: i 3 browser con filtro (MagicDllBrowser/RuntimeDllManager/Ps3MagicBrowser) hanno ereditato il default stateless perché i loroFilterTextvivono nei DataModel privati, non esposti nel controllo — la cattura reale del filtro rimane come backlog minore. Con D1+D2+D3+D4, tutti i ~72 controlli ora dichiaranoIRestorableModule; quelli con stato (8 editori + 9 hub) eseguono l'override esplicito, il resto è stateless. Build Release 0 errori (402 warning preesistenti)
v2.160.3.0