Skip to content

Redesenho da interface: Fila por grupos, Configurações por seções, celular e tokens únicos - #3

Merged
bps2414 merged 8 commits into
mainfrom
claude/trusting-gates-lequph
Oct 14, 2026
Merged

bps2414 merged 8 commits into
mainfrom
claude/trusting-gates-lequph

Conversation

@bps2414

@bps2414 bps2414 commented Oct 14, 2026 •

Copy link
Copy Markdown
Owner

Redesenho da interface do Ferry (web e app Windows) seguindo o plano. A identidade da Fase 2 continua (visual escuro "PlayStation noir", Geist, acento azul, Fila "Régua" com a barra como travessia). O que muda é a hierarquia e a densidade de informação. No caminho apareceram quatro bugs; cada um foi reproduzido antes da correção (detalhes abaixo).

Antes × depois

Todas as capturas usam o mesmo estado (1 erro, 1 PKG enviado, 1 enviando, 1 pausado, 1 aguardando partes, 4 concluídos), gerado por e2e/web/showcase.mjs contra o código original (fab0939) e contra esta branch. Arquivos em docs/redesign/.

Fila — desktop (1440×900)

Antes Depois
antes depois
  • Agrupada por urgência: Precisa de você → Enviando → Na fila → Concluídos. O erro sai do fim da lista e vai para o topo.
  • Os cartões parados deixaram de mostrar 0,0% / — / —. Só o ativo mostra %, MB/s e tempo restante; um cartão pausado mostra só o %.
  • Título com tamanho fixo. Antes, um cartão sem capa ganhava 30 px e ficava maior que o jogo que estava enviando.
  • Cabeçalho com o progresso total da fila. O horário previsto de término só aparece quando todos os itens têm tamanho conhecido (aqui não aparece porque um item ainda espera partes).
  • A fila inteira cabe em 900 px (antes ocupava 1391 px).

Concluídos aberto: desktop · celular

Fila — celular (390×844)

Antes (página inteira) Depois (página inteira) Depois (tela)

A página com 9 jogos tinha 2666 px e agora tem 1238 px. Marca e abas ficam numa linha, os cartões parados são compactos, o botão Adicionar arquivos fica fixo no rodapé (decisão sua) e os botões de ação têm alvo de 44 px.

Configurações

Antes Depois
antes depois

São seis seções (PS5, Destinos, Envio, Senhas conhecidas, Avisos, Geral; no Windows também Energia), com um índice fixo que acompanha a rolagem. O título de cada seção ficou maior e os subgrupos aparecem em versalete com fio. Sobre o que você relatou (rolagem estranha, barra de rolagem no meio da tela): agora há uma rolagem só, com a barra na borda da janela. A caixa de senhas cresce com o conteúdo em vez de rolar dentro do campo. Celular: antes · depois.

Inglês: fila antes · fila depois · configurações depois

O que mudou

Web (web/ui, web/Hub.cs)

  • Grupos com a ordem do motor preservada dentro de cada um (a ordem que você escolhe com "Transferir agora").
  • Concluídos recolhido por padrão (decisão sua), com a escolha lembrada no navegador e Limpar concluídos no cabeçalho do grupo.
  • Estado como etiqueta com ponto de cor. Com erro, Tentar de novo vira botão com texto.
  • Status do PS5 saiu do rodapé da barra lateral e virou um selo no topo de todas as páginas; "Achei um PS5" aparece ao lado.
  • Avisos: um por jogo e tipo. Avisos de erro e de PKG ganham Ver, que rola até o cartão. O servidor passou a mandar jobId no aviso (campo novo e opcional, compatível).

Windows (app/)

  • Mesma estrutura: lista agrupada (CollectionView + QueueGroups), cartão compacto na fila e nos concluídos, progresso total, status no topo, Configurações com índice.
  • A lista só se reorganiza quando algum jogo muda de grupo ou de posição. Recriar os cartões a cada atualização perderia a animação da barra e o foco do teclado.

Base comum

  • tools/tokens.json gera as cores e medidas de app.css e App.xaml (tools/generate-tokens.py), e a CI acusa divergência. Antes os tokens eram copiados à mão e havia só um comentário dizendo "mesmos tokens".

Bugs encontrados (reproduzidos antes de corrigir)

# Bug Como reproduzi Causa Correção Teste
1 Avisos duplicados ("Senha necessária" empilhado) Vitrine com 2 pedidos de senha do mesmo jogo: o código original mostrou 2 avisos (antes); também aparece em 05-enviando.png do relatório antigo Senha incorreta gera um novo pedido e um novo aviso, e a página empilhava cada um Aviso com chave tipo + jogo: um pedido repetido renova o aviso que já está na tela (depois, 1 aviso) medidas.json da vitrine
2 "Testando…" preso para sempre Rota de /api/ps5/test e /api/ps5/discover abortada (rede caiu): o resultado ficou em "Testando…"/"Procurando…" e Failed to fetch escapou 2× no console try/finally sem catch: a promessa rejeitada não era tratada A linha de status diz "Sem resposta do servidor Ferry…", com o botão liberado Novo teste no E2E web: Teste sem resposta do servidor não fica preso (pt-BR e en)
3 Prefixo \\?\ no caminho Visível em 03-fila-vazia.png do relatório antigo (servidor rodando no Windows) O caminho longo do Windows chegava como estava Só a exibição remove \\?\ e \\?\UNC\; o valor salvo não muda Checagem do helper com 4 casos
4 Rolagem aninhada nas Configurações (relatado por você) Caixa de senhas e coluna com barra própria no meio da tela Áreas com rolagem própria dentro da página Rolagem única na borda da janela (web e WPF) Capturas

Instabilidade nos testes (não é bug do produto):

  • E2E web local — falhava em "webhook depois do reinício" já no código original. Reproduzi na primeira execução da linha de base. O modo local parava o servidor com SIGTERM, o desligamento gracioso deixava o envio terminar e o webhook se perdia. O modo Docker já usava KILL pelo mesmo motivo; o local passou a usar também.
  • ResumeChecks no Windows (CI desta PR) — IOException: being used by another process ao ler commands.txt. File.ReadAllLines abre com FileShare.Read, o que conflita com o FTP falso (Python) com o arquivo aberto para escrita. A leitura agora usa FileShare.ReadWrite e tenta de novo se o arquivo ainda estiver ocupado. Os 44 testes de retomada passam.
  • PkgChecks no Linux (uma rodada) — Scenario.Stop estourou 20 s após o cenário de persistência e concorrência. Esta PR não toca o core nem esse teste; no commit anterior, com o mesmo código, o job Linux passou inteiro. Fica registrado como intermitente fora do escopo desta PR.

Desempenho

Medido no Chromium com e2e/web/showcase.mjs: 200 jogos, 300 atualizações de progresso (o SSE manda até 4 por segundo), descartando as 20 primeiras como aquecimento.

Antes Depois
render() por atualização — mediana ~13 ms ~2,2 ms
render() — p95 ~20 ms ~3,4 ms
Altura da fila (desktop, 9 jogos) 1391 px 900 px
Altura da fila (celular, 9 jogos) 2666 px 1238 px
Avisos para 2 pedidos de senha do mesmo jogo 2 1

Como ficou mais rápido: o SSE manda a fila inteira a cada mudança e a página reescrevia os 200 cartões. Agora cada cartão guarda uma chave (idioma, grupo, senha pendente e dados do jogo) e só é reescrito quando ela muda. Os concluídos recolhidos não entram no layout. O DOM ficou praticamente igual (9779 → 10026 elementos com 200 jogos, por causa dos cabeçalhos de grupo e da etiqueta de estado). No Windows, a lista agrupada não é recriada a cada tique (ver acima).

As Configurações ficaram mais longas em altura total (1693 → 3514 px no desktop), porque agora são uma coluna só com seções maiores. O índice leva direto a cada seção.

Validação

  • E2E web (servidor local, Chromium, pt-BR e en): 116 verificações, nenhuma falha (114 de antes + o teste novo nos dois idiomas). Relatórios e capturas em e2e_report_web_*.md e e2e/web/report/.
  • CI: Docker (E2E web na imagem) verde; Windows verde no commit do WPF, incluindo WPF idioma e bandeja e WPF energia.
  • Contratos de localização: 1859 verificações; as chaves novas existem em pt-BR e en.
  • tools/generate-tokens.py --check; WPF compila com EnableWindowsTargeting.
  • O teste WPF passou a abrir o grupo Concluídos antes de ler o cartão de instalação solicitada, e confere que o grupo começa recolhido.

Limites e desvios do plano

  • Não rodei o app Windows na tela. Aqui só compila; o E2E WPF roda na CI do Windows. Vale abrir o .exe do artefato Ferry-windows e olhar a Fila e as Configurações.
  • Concluído sem "enviado às HH:MM": o motor não guarda o horário de conclusão.
  • O aviso de senha não ganhou o botão "Digitar senha" porque o diálogo já abre sozinho; a correção foi juntar os avisos repetidos.
  • "Partes faltando há muito tempo" não entra em Precisa de você, porque o estado não tem o horário da última parte.
  • A seção Destinos/PKG ainda tem o fluxo DPI atual e vai mudar com o plano do PKG Manager.

Como revisar

  1. Compare as capturas acima.
  2. Leia por commit: tokens → web → Windows → desempenho e bugs → teste instável do Windows → relatórios.
  3. Para rodar a vitrine: dotnet build web -c Release && cd e2e/web && node showcase.mjs.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY

…om SIGKILL

tools/tokens.json gera o bloco :root de web/ui/app.css e as cores/medidas
de app/App.xaml (tools/generate-tokens.py). A CI falha se divergirem.

O E2E web em modo local parava o servidor com SIGTERM no teste de
reinício: o desligamento gracioso deixava o envio do IMGW terminar e o
webhook de conclusão se perdia, falhando 'webhook depois do reinício'.
O modo Docker já usa KILL pelo mesmo motivo; o local agora também.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY
@coderabbitai

coderabbitai Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 24bbd00a-5d02-4769-90df-d6803094e2d6
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

- Fila agrupada: Precisa de você (erro, PKG enviado, verifique no PS5,
  senha pendente) → Enviando → Na fila → Concluídos (recolhido por
  padrão, escolha lembrada no navegador; Limpar no cabeçalho do grupo).
- Números só quando dizem algo: o ativo mostra %, MB/s e restante; parado
  com progresso, só o %; aguardando partes, erro e concluído, nenhum.
  Barra só para quem está atravessando ou parado no meio.
- Título com tamanho fixo (22 px; o ativo, 26 px) com ou sem capa.
- Estado como etiqueta com ponto de cor; com erro, "Tentar de novo" vira
  botão com texto.
- Cabeçalho com progresso total da fila e término previsto (só quando
  todos os itens têm tamanho conhecido e há velocidade).
- Status do PS5 como selo no topo do conteúdo; "Achei um PS5" ao lado.
- Avisos: um por jogo e tipo (pedido de senha repetido renova o aviso em
  vez de empilhar); erro/PKG/verifique ganham "Ver", que leva ao cartão.
  O servidor passa a mandar o id do jogo no aviso.
- Configurações em seções (PS5, Destinos, Envio, Senhas, Avisos, Geral)
  com índice fixo que acompanha a rolagem; resultado de teste como linha
  de status.
- Celular: marca e abas numa linha, cartões compactos, botão Adicionar
  fixo no rodapé, alvos de 44 px, índice das Configurações em chips.
- Caminhos com prefixo \\?\ aparecem sem ele (só exibição).
- e2e/web/showcase.mjs: estado fixo com todos os casos para capturas
  comparáveis e medida de renderização.

E2E web (local, pt-BR e en): 114 verificações, nenhuma falha.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY
…olagem única

App Windows com a mesma estrutura da web:
- Fila agrupada (CollectionView com grupo e ordem do motor); Concluídos
  recolhido por padrão com Limpar no cabeçalho do grupo. A lista só se
  reorganiza quando um jogo muda de grupo ou posição, para não recriar
  cartões a cada tique (animação da barra e foco preservados).
- Cartão: título fixo (22/26 px), etiqueta de estado com ponto, números
  só quando dizem algo, compacto na fila e nos concluídos, fio de cor em
  'precisa de você', 'Tentar de novo' com texto quando há erro.
- Progresso total da fila e término previsto no cabeçalho.
- Status do PS5 e 'Achei um PS5' no topo de todas as páginas.
- Configurações com índice de seções (PS5, Destinos, Envio, Energia,
  Senhas, Avisos, Geral) que acompanha a rolagem.

Rolagem das Configurações (web e Windows): uma rolagem só, com a barra na
borda da janela. A caixa de senhas tinha barra própria no meio da tela;
agora cresce com o conteúdo. Hierarquia mais clara: título de seção
maior, subgrupos em versalete com fio.

Teste WPF: abre o grupo Concluídos antes de ler o cartão de instalação
solicitada e confere que ele começa recolhido.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY
… fica preso

Desempenho: o SSE manda a fila inteira a cada mudança e render() reescrevia
todos os cartões. Agora cada cartão guarda a chave (idioma, grupo, senha
pendente, dados do jogo) e só é reescrito quando ela muda. Com 200 jogos e
uma barra andando: ~13 ms → ~2,2 ms por atualização (mediana, Chromium,
e2e/web/showcase.mjs).

Bug (reproduzido antes da correção): com a requisição de 'Testar conexão'
ou 'Procurar na rede' falhando (rede caiu, servidor reiniciando), o
resultado ficava preso em 'Testando…'/'Procurando o PS5 na rede…' e o
erro escapava sem tratamento ('Failed to fetch' x2 no console). Agora a
linha de status diz que o servidor não respondeu. Novo teste no E2E web.

Docs: capturas antes/depois e medidas em docs/redesign/, changelog
(Não lançado), READMEs (status do PS5 no topo) e resultado no plano.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY
…ndows

A CI do Windows falhou em 'Recuperação FTP e retomada' (cancel-replay):
IOException 'being used by another process' em ResumeChecks.cs:76.
File.ReadAllLines abre com FileShare.Read, que conflita com o FTP falso
(Python) mantendo commands.txt aberto para escrita. Agora a leitura usa
FileShare.ReadWrite e, se mesmo assim o arquivo estiver ocupado, tenta de
novo. Sem mudança no produto; 44 verificações de retomada passam.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01BEiC6BEuxS2kyr9BuYYeJY
@bps2414
bps2414 marked this pull request as ready for review October 14, 2026 01:07
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-14T01:14:22.120009Z f223dba Draft marked ready
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

bps2414 commented Oct 14, 2026

Copy link
Copy Markdown
Owner Author

Status das falhas de CI desta PR:

  • windows em 9c4bbcc (Recuperação FTP e retomada): IOException ao ler commands.txt enquanto o FTP falso escrevia nele. Corrigido em 6e9b4ea (leitura com FileShare.ReadWrite e nova tentativa).
  • linux em 02057c7 (Contratos de PKG e DPI): PkgChecks.Scenario.Stop estourou 20 s (e2e/PkgChecks.cs:647, cenário de persistência e concorrência). Não é desta PR: o commit só mudou o app Windows, que o job Linux nem compila, e o mesmo passo passou no Linux em c0e6d8f e 6d6c232 com o mesmo código de core. Ainda não há correção; deixei uma tarefa para investigar se o motor ignora o cancelamento ou se o tempo do teste é que está curto.

Generated by Claude Code

@bps2414
bps2414 merged commit fe9b286 into main Oct 14, 2026
6 checks 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