JARVIS-UI
Atualização 2.160
20/06/2026
v2.160.0.0MINORJarvis-UI
Fase A–C: ModuleRegistry + Workspace Ready (§17) + Icon Rail sem flyouts (§16) (Jarvis-UI)
- Entrega das Fases A–C do
docs/specs/EDITOR_UI_OVERHAUL_PLAN.md§16–§17 (decisões Halyson 2026-06-20), conformedocs/ai/PROMPT_UI_GLM_REMAINING_BACKLOG_2026-06-20.md. Escopo: arquitetura de navegação + catálogo data-driven + iconografia — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocados; os 68 handlersMenuItem_*não refactorados (só chamados). Fase A — ModuleRegistry (fonte única):ModuleCatalogPolicy.csevolui de stub documental pra catálogo autoritativo — novopublic static class ModuleRegistrycomIReadOnlyList<ModuleCatalogEntry> Allpreenchido com 41 entries (Home + 10 Core Authoring + 5 Maps + 7 Live + 16 Extras + 2 Wave-1), uma por módulo roteado no rail.ModuleCatalogEntryganhaMode/Notes/Scope/Cluster(enumModuleCluster) além doId/Title/Description/IconKey/RequiresProjectoriginal. Copy fiel dos literais de cadaSetModule(...)emMain_Window.axaml.cs(não reinventada). Política doc-comment: novoMenuItem_*roteado = append no registry (review blocker). Fase A — Iconografia:StudioIcons.axamlexpandido de 14 → 54 ícones (<StreamGeometry>Lucide-like, viewBox 24×24) — 1 metáfora dedicada por módulo (espada+chifres=monster, disquete=save, caveira=enemy design, grade hex=sphere grid, etc.). Check de consistência (script) confirma que todos os 41IconKeys do registry resolvem emStudioIcons. Fase B — §17 Workspace Ready:MainDashboard_Control.axamldeixa de ter 6 tiles hardcoded e viraItemsControl ItemsSource="{Binding Modules}"comDataTemplate(ícone + Title + Description completa + pill de Mode).Main_DataModelganhapublic IReadOnlyList<ModuleCatalogEntry> Modules => ModuleRegistry.All. Dois converters novos emFFXProjectEditor/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
v2.159.6.1
v2.160.1.0PATCHJarvis-UI
Fase D1 fechada: interface `IRestorableModule` + refator `NavigationSnapshot` (Jarvis-UI)
- Primeiro commit da Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D1). Escopo: arquitetura de navegação (back/forward restaurável) — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocados. Contrato novoFFXProjectEditor/Modules/Common/IRestorableModule.cs:CaptureState()→Dictionary<string,object?>?(null = stateless) eRestoreState(state)(idempotente, safe com null). Antes do D1, oMain_Windowfazia pattern-match em tipos concretos (MonEditorSelector_Control/KernelCommands_Control) pra capturar estado — não escala pra ~38 módulos. Agora oMain_Windowpergunta ao controle se ele éIRestorableModule. RefatorNavigationSnapshot: virarecord struct (string ModuleId, Dictionary<string,object?>? State); o enumNavigationSurfaceKindé removido. Novo campoprivate string _currentModuleId = "home"setado no início deDispatch(string moduleId).CaptureCurrentNavigationSnapshot()genérico viaContentFrame.Content is IRestorableModule;IsSameNavigationSurface()compara sóModuleId;RestoreNavigationSnapshot()fazDispatch(snapshot.ModuleId)+restorable.RestoreState(snapshot.State). 3 chamadas quebradas corrigidas (ainda referenciavamNavigationSurfaceKind):MenuItem_MonsterMagic1/2(L560/568) →_currentModuleId = "battle-commands-hub"+new NavigationSnapshot("battle-commands-hub")(mesmo padrão dosMenuItem_Commands/MenuItem_Itemsjá migrados);NavigateToMonsterEditor(L1549) →new NavigationSnapshot("monster-editor"). Honestidade: back/forward continua funcionando nos 3 originais (Home/Monster/KernelCommands), mas Monster/KernelCommands só serão plenamente restorable quando seus controles implementaremIRestorableModule(D2/D4). Até lá, o snapshot é criado mas oStatevemnull(volta pro módulo, não restaura sub-seleção). Build Release 0 erros (402 warnings preexistentes)
v2.160.0.0
v2.160.2.0PATCHJarvis-UI
Fase D2: `IRestorableModule` nos 7 editores fáceis (Jarvis-UI)
- Segundo commit da Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D2). Escopo: back/forward restaurável em 7 editores Core Authoring — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocados. ImplementaIRestorableModule(definido em D1) em 7 controles:TreasureEditor_Control,AutoAbilityEditor_Control,PlayerGrowthEditor_Control,CtbBaseEditor_Control,KeyItemEditor_Control,FormationEditor_Control,BukiGetTreasureCatalog_Control. CadaCaptureState()capturafilterText(string) +selectedIndex(int? derivado do item selecionado na coleçãoDisplayed*);RestoreState(state)repõe o filtro (que re-aplica oApplyFilterviaOnFilterTextChanged) e re-seleciona a row pelo índice. Mapeamento por editor: Treasure (SelectedTreasure/DisplayedTreasures), AutoAbility (SelectedAbility/DisplayedAbilities), PlayerGrowth (SelectedCharacter/DisplayedCharacters), CtbBase (SelectedRow/DisplayedRows), KeyItem (SelectedItem/DisplayedItems), Formation (SelectedBattle/Battles— semDisplayed*), 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)
v2.160.1.0
v2.160.3.0PATCHJarvis-UI
Fase D3: `IRestorableModule` no `SubTabHub_Control` (cobre 9 hubs) (Jarvis-UI)
- Terceiro commit da Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D3). Escopo: back/forward restaurável em todos os hubs baseados emSubTabHub— writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocados.SubTabHub_Control.axaml.csimplementaIRestorableModule: novo campoint _activeTabIndexrastreado emSelectTab(index);CaptureState()retorna{["activeTab"] = _activeTabIndex};RestoreState(state)chamaSelectTab(idx)(que re-apilla pill/active/hosted-content normalmente). Cobertura automática dos 9 hubs: BattleCommandsHub, ItemsHub, SphereGridHub, TextHub, EnemyDesignHub, CustomizationsHub, StatsHub, EncountersHub, Blitzball — todos usamSubTabHub_ControlviaAddTab(...), então todos ganham restauração de sub-aba ativa de graça numa única mudança. Honestidade: o conteúdo interno de cada sub-aba (filtro/seleção do editor hospedado) é responsabilidade do controle hospedado — se ele também implementarIRestorableModule(D2 cobriu Treasure/KeyItem/etc.), oMain_Windowencadeia o restore na sequência. Build Release 0 erros (402 warnings preexistentes)
v2.160.2.0
v2.160.4.0PATCHJarvis-UI
Fase D4: `IRestorableModule` em todos os controles restantes via default interface methods (Jarvis-UI)
- Quarto commit da Fase D (
docs/ai/PROMPT_GLM_PHASE_D_TO_F_2026-06-20.md§3.D4). Escopo: declarar a interface em todos os*_Controlrestantes — writers/save bytes/hooks/FfxLib/RT0/RT2/SGM/SPIRA FORGE intocados.IRestorableModule.csganha default interface methods:CaptureState() => nulleRestoreState(state) { }(stateless/no-op por padrão). Assim, controles sem estado significativo (explorers read-only, hubs, runtime labs, debug, trackers, 16 Extras, Wave-1, sub-controles) só precisam declarar, IRestorableModulena assinatura — oMain_Windowagora pode fazerContentFrame.Content is IRestorableModuleem qualquer módulo sem distinguir tipo. Sweep automatizado viawork/_irestable_stateless_sweep_20260620.ps1: 65 controles alterados (adicionausing FFXProjectEditor.Modules.Common;+: UserControl, IRestorableModule), 9 pulados (os 8 já implementados em D1/D2/D3 +MonsterAiEditor2_Controldiscontinued). Honestidade: os 3 browsers com filtro (MagicDllBrowser/RuntimeDllManager/Ps3MagicBrowser) herdaram o default stateless porque seusFilterTextvivem nos DataModels privados, não expostos no controle — captura real do filtro fica como backlog menor. Com D1+D2+D3+D4, todos os ~72 controles agora declaramIRestorableModule; os que têm estado (8 editores + 9 hubs) fazem override explícito, o resto é stateless. Build Release 0 erros (402 warnings preexistentes)
v2.160.3.0