Skip to content

Visão em tabela (OmniDataGrid) + painel de detalhes à direita ou abaixo - #7

Merged
afernandes merged 8 commits into
feat/roadmap-p3from
feat/detail-panel-position
Jul 29, 2026
Merged

Visão em tabela (OmniDataGrid) + painel de detalhes à direita ou abaixo#7
afernandes merged 8 commits into
feat/roadmap-p3from
feat/detail-panel-position

Conversation

@afernandes

Copy link
Copy Markdown
Owner

Resumo

O painel de detalhes só abria à direita. Agora um botão na toolbar alterna entre à direita e abaixo da lista — à direita funciona melhor em telas largas; abaixo, para stack traces longos e telas estreitas.

Base: este PR sai de feat/roadmap-p3 (#6), que ainda não foi mergeado.

Como ficou

Botão Só aparece quando há um detalhe aberto para reposicionar
Ícone Aponta para onde o painel vai ( / ), não onde ele está — a Omni não tem ícones de painel, e a seta remove a ambiguidade
Persistência A escolha sobrevive a reabertura do app

Duas decisões que valem explicação

1. A preferência vai em ui.json, não em settings.json. O SettingsService dispara Changed ao salvar, e o LogStore reage a esse evento recarregando todos os arquivos de log. Uma preferência puramente visual não pode custar isso. O enum é gravado por nome ("Bottom") porque o arquivo é editável à mão — 1 não diria nada.

2. O splitter recebe @key na orientação. Ele mede e fixa os tamanhos dos panes na inicialização; reaproveitar a instância deixaria as larguras da disposição anterior aplicadas na nova. O @key força a recriação na troca.

Verificação

  • 153 testes verdes (6 novos: padrão, alternância nos dois sentidos, persistência, gravação por nome, arquivo corrompido e valor desconhecido caindo no padrão).
  • Validado no app real: alternei direita → abaixo → direita, e confirmei que a escolha sobrevive ao fechar e reabrir (ui.json com "DetailPanelPosition": "Bottom").

🤖 Generated with Claude Code

O detalhe so abria a direita. Um botao na toolbar passa a alternar entre a
direita e abaixo: a direita funciona melhor em telas largas, abaixo e melhor
para stack traces longos e telas estreitas.

O icone aponta para ONDE o painel vai (seta para baixo / para a direita), e nao
onde ele esta — a lib nao tem icones de painel, e a seta remove a ambiguidade.
O botao so aparece quando ha um detalhe aberto para reposicionar.

O splitter recebe @key na orientacao: ele mede e fixa os tamanhos dos panes na
inicializacao, entao reaproveitar a instancia deixaria as larguras da
disposicao anterior aplicadas na nova.

A preferencia e persistida em ui.json — e nao no settings.json de proposito: o
SettingsService dispara Changed ao salvar e o LogStore reage recarregando todos
os arquivos, o que seria absurdo para uma preferencia visual. O enum e gravado
por nome (Bottom), ja que o arquivo e editavel a mao.

Validado no app: alterna nos dois sentidos e a escolha sobrevive a reabertura.
6 testes novos, incluindo arquivo corrompido e valor desconhecido caindo no
padrao.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 28, 2026 14:44
@gemini-code-assist

Copy link
Copy Markdown

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Este PR adiciona uma preferência de UI persistida para alternar a posição do painel de detalhes no LogViewer entre à direita e abaixo da lista, escolhendo a disposição mais adequada conforme o tamanho da tela e o tamanho do stack trace. A persistência é feita em ui.json via um novo serviço dedicado, evitando impactos colaterais do SettingsService (como recarregamento de logs).

Changes:

  • Cria UiPreferencesService para carregar/salvar preferências visuais em ui.json (com enum serializado por nome).
  • Introduz o enum DetailPanelPosition e integra a orientação do splitter no LogViewer (com @key para recriar na troca).
  • Adiciona um botão (condicional) na LogToolbar para alternar a posição do painel, e adiciona testes cobrindo default, alternância e persistência.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
test/ClefExplorer.Tests/UiPreferencesTests.cs Testa default, alternância, persistência e tolerância a ui.json inválido/desconhecido.
src/Services/UiPreferencesService.cs Implementa carregamento/salvamento de ui.json com enum em string e fallback seguro.
src/Program.cs Registra UiPreferencesService no DI container.
src/Models/DetailPanelPosition.cs Define o enum persistido (Right/Bottom) com documentação.
src/Components/LogViewer.razor Alterna orientação do OmniSplitter com base na preferência e persiste via serviço.
src/Components/LogToolbar.razor Inclui botão (apenas com detalhe aberto) para alternar a posição do painel.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Alem da lista, um botao na toolbar alterna para uma tabela com ordenacao,
agrupamento (arrastando a coluna para a faixa acima), filtro por coluna e
redimensionamento. A escolha e persistida.

Colunas derivadas do CONTEUDO: logs CLEF carregam propriedades estruturadas que
variam conforme a aplicacao que os gerou, entao fixa-las na mao nao
funcionaria. O LogColumnDiscovery amostra os eventos carregados, conta a
frequencia de cada propriedade e oferece como coluna as que aparecem o
suficiente, com o nome ja legivel - "MachineName" vira "Machine Name". O
desempate por nome mantem a ordem estavel entre aberturas.

O seletor de colunas e proprio, e nao o embutido (AllowColumnVisibility=false).
Motivo: a coluna aplica a visibilidade no proprio OnInitialized, entao toda vez
que o grid e recriado - o que acontece ao abrir/fechar o detalhe, ja que o
layout troca de splitter - as escolhas do menu interno se perdiam. Mantendo o
conjunto do lado do app, ele sobrevive a recriacao e ainda persiste entre
execucoes.

Tentei estabilizar a arvore mantendo o splitter sempre montado com o pane do
detalhe colapsado, mas isso reintroduz a race de medicao do splitter aninhado
(o conteudo mede 0px e some). Por isso a renderizacao condicional foi mantida e
o problema foi resolvido pelo lado do estado.

19 testes novos: descoberta (frequencia, corte de raras, exclusao das que ja tem
coluna fixa, teto, estabilidade, amostragem), rotulo legivel e valor da celula
(sem as aspas que o ScalarValue adiciona).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@afernandes afernandes changed the title Painel de detalhes: alternar entre à direita e abaixo da lista Visão em tabela (OmniDataGrid) + painel de detalhes à direita ou abaixo Jul 28, 2026
afernandes and others added 5 commits July 28, 2026 12:19
Com 'pull_request: branches: [main]', PRs empilhados — que apontam para outra
branch de feature — ficavam sem CI: aconteceu no #5 e no #7, onde o gate de
testes so passou a valer depois de disparar o workflow na mao. Removido o
filtro de base; o gatilho de push continua restrito a main.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A versao vivia solta no csproj e ficou em 1.0.0 enquanto a Store ja estava em
1.0.2 — o titulo da janela, que le a versao do assembly, mostrava um numero
diferente do publicado.

Directory.Build.props passa a ser a fonte unica:
- o csproj herda Version/FileVersion/AssemblyVersion (verificado: o assembly
  agora sai 1.1.0.0);
- publish-store-package.ps1 usa esse valor quando -Version nao e informado;
- release.yml passa /p:Version com a versao da tag, entao o exe dentro do
  pacote carrega a mesma versao carimbada no manifesto — antes o manifesto ia
  com a versao da tag e o assembly ficava em 1.0.0.

Higiene:
- o tipo de arquivo registrado virou 'Clef Log File'; 'Reader Log File' era
  sobra de copy/paste e divergia do rotulo do Package.appxmanifest;
- RuntimeIdentifiers fica so em win-x64: e o que o CI publica, o que o pacote da
  Store contem e o que o README anuncia. Declarar win-x86 sugeria um suporte
  que nao existe.

Nao suprimi o aviso MSB3277 remanescente: ele vem da unificacao de WindowsBase
pelo proprio pacote WebView2 e mascarar conflitos de assembly com NoWarn e pior
do que conviver com o ruido. Os avisos CS do nosso codigo seguem zerados.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
A lista montava um no no DOM por evento da pagina. O roadmap pedia para medir
antes: com paginas de ate 100 a virtualizacao renderia pouco, entao o ganho de
verdade vinha junto com paginas maiores.

A lista passa a usar OmniVirtualize (Height=null: o pai ja limita a altura e faz
o scroll; sem altura limitada o Virtualize renderiza tudo) e o seletor ganha
250/500/1000 itens por pagina. Verificado com 5000 eventos: pagina de 1000 rola
sem travar.

Correcao encontrada durante esse teste: OmniPagination e zero-based e o app
conta a partir de 1 — que e o numero mostrado no "X-Y de Z". Sem conversao, a
pagina 1 aparecia como "2 / 100" e a ultima pagina ficava inalcancavel, porque o
clamp do app ia ate UltimaPagina enquanto o componente esperava
UltimaPagina - 1. A traducao ficou na fronteira, dentro da LogToolbar. Bug meu,
introduzido na migracao do P2 ao trocar os botoes manuais pelo componente.
Verificado: "1-50 de 5000" com "1 / 100", e o proximo leva a "51-100" / "2 / 100".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Nao houve passe de a11y depois da migracao. Os componentes da Omni ja vem
tratados, mas os elementos clef-* proprios nao.

Lista de eventos: era uma pilha de div com @OnClick - nao recebia foco, nao
respondia ao teclado e o leitor de tela nao a anunciava como lista selecionavel.
Agora e role=listbox com itens role=option, tabindex e aria-selected, ativaveis
por Enter/Espaco. Cada item ganhou um aria-label montado com nivel, hora,
mensagem e a marca de excecao: sem ele o item seria lido como textos soltos e o
nivel, que visualmente e um badge colorido, se perderia.

Itens de grupo viraram button de verdade em vez de div com @OnClick - foco,
teclado e semantica de graca. Nao ha nada interativo aninhado, entao a troca e
segura; o CSS ganhou o reset de aparencia correspondente.

Indicador de foco: nenhum elemento clef-* tinha. Adicionado via :focus-visible,
que mostra o anel so na navegacao por teclado, sem poluir o clique de mouse.

O contraste ja tinha sido tratado na migracao (WCAG AA medido no DOM nos dois
temas), entao ficou de fora deste passe.

Nao consegui confirmar o anel de foco na tela: a maquina bloqueou durante o
teste. As mudancas sao estruturais e compilam, mas a verificacao visual fica
pendente.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Roadmap P4: virtualização, acessibilidade, versionamento e higiene (+ bug de paginação)
@afernandes
afernandes merged commit d2d2201 into feat/roadmap-p3 Jul 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants