Skip to content

Redesenha a interface para desktop, com sons e profundidade - #1

Open
arturseixas wants to merge 10 commits into
mainfrom
desktop-ui-sons-gradientes
Open

arturseixas wants to merge 10 commits into
mainfrom
desktop-ui-sons-gradientes

Conversation

@arturseixas

Copy link
Copy Markdown
Owner

A interface era um layout de celular esticado numa janela. Troca o esqueleto mobile por padroes de desktop, liga os efeitos sonoros que ja estavam no repositorio mas nunca eram tocados, e substitui as superficies chapadas por um sistema de gradientes e sombras.

Layout de desktop

  • Biblioteca: barra de ferramentas no lugar do FloatingActionButton, com busca, sons, tema e "Novo livro" numa linha so. Atalhos Ctrl+N e Ctrl+F.
  • Livro aberto: TabBar vira barra lateral de navegacao (Ctrl+1/Ctrl+2/ Ctrl+W). Usa IndexedStack para nao desmontar o editor Quill ao alternar.
  • Nucleo do livro: duas colunas acima de 1000px.
  • Escrita: coluna de texto limitada a 760px e centralizada. Texto corrido ocupando a largura de um monitor grande e ilegivel.
  • VisualDensity.compact, barras de rolagem visiveis, hover e cursor de mao em tudo que e clicavel, largura de conteudo limitada.

Som

  • sound_service.dart: pool de 4 players em rodizio, volume relativo por som, preferencia persistida e throttle de 70ms no hover. Falha de audio desliga o som em vez de derrubar o app.

Profundidade

  • app_surfaces.dart centraliza gradientes e sombras sob uma regra unica: a luz vem de cima. Aplicado a fundo, cartoes, barras, botoes e progresso.

Corrige tambem a familia de fonte da UI, que apontava para "Anthropic Sans" depois de os arquivos dessa fonte terem sido removidos: a interface inteira estava caindo no fallback do sistema. Agora usa Source Sans 3, que e o que o pubspec declara.

terminalimproved and others added 10 commits July 30, 2026 19:37
A interface era um layout de celular esticado numa janela. Troca o
esqueleto mobile por padroes de desktop, liga os efeitos sonoros que ja
estavam no repositorio mas nunca eram tocados, e substitui as superficies
chapadas por um sistema de gradientes e sombras.

Layout de desktop
- Biblioteca: barra de ferramentas no lugar do FloatingActionButton, com
  busca, sons, tema e "Novo livro" numa linha so. Atalhos Ctrl+N e Ctrl+F.
- Livro aberto: TabBar vira barra lateral de navegacao (Ctrl+1/Ctrl+2/
  Ctrl+W). Usa IndexedStack para nao desmontar o editor Quill ao alternar.
- Nucleo do livro: duas colunas acima de 1000px.
- Escrita: coluna de texto limitada a 760px e centralizada. Texto corrido
  ocupando a largura de um monitor grande e ilegivel.
- VisualDensity.compact, barras de rolagem visiveis, hover e cursor de mao
  em tudo que e clicavel, largura de conteudo limitada.

Som
- sound_service.dart: pool de 4 players em rodizio, volume relativo por
  som, preferencia persistida e throttle de 70ms no hover. Falha de audio
  desliga o som em vez de derrubar o app.

Profundidade
- app_surfaces.dart centraliza gradientes e sombras sob uma regra unica:
  a luz vem de cima. Aplicado a fundo, cartoes, barras, botoes e progresso.

Corrige tambem a familia de fonte da UI, que apontava para "Anthropic
Sans" depois de os arquivos dessa fonte terem sido removidos: a interface
inteira estava caindo no fallback do sistema. Agora usa Source Sans 3,
que e o que o pubspec declara.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Troca a identidade visual inteira: a paleta creme/terracota sai e entram
grafite (#1C1B1A) e papel off-white frio (#EDECE8), com um acento unico em
azul petroleo (#2B5C63) reservado a acao primaria, ao estado ativo e ao
cursor.

Camada de tema:
- app_surfaces deixa de expor gradientes e sombras de cartao e passa a
  expor cores chapadas e hairlines; sobra uma sombra so, em dialogos e menus
- tres papeis tipograficos sem sobreposicao: serifada para nomes de
  livro/capitulo/pagina e corpo do editor, sans para a UI, mono para
  contadores e atalhos
- raios de 3/5/6px em toda parte; movimento entre 110 e 190ms, sem overshoot

Telas:
- botao "Novo livro" vira retangulo ancorado no header, sem pill nem FAB
- cartoes de livro sem sombra: borda de 1px e espacamento
- barra de progresso fina e chapada
- barra lateral com hairlines no lugar de blocos de fundo; estado ativo e um
  marcador de 2px mais tinte de acento a 10%
- barra do editor reescrita sobre a API do QuillController, com alvo e glifo
  iguais em todos os botoes e separadores verticais entre os grupos

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
O desenvolvimento acontece sem Flutter SDK na maquina local, entao o CI e o
unico lugar onde o codigo e compilado. Disparar so na main significava
descobrir erro de compilacao depois do merge.

O job de analyze roda em ~2 minutos contra os ~15 dos tres builds de
release, e pega erro de Dart antes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
O build de Linux falha em "flutter build linux" desde ca2d9b8, o commit que
adicionou os sons: audioplayers_linux depende de GStreamer e o apt-get do
workflow so instalava GTK, clang, cmake e ninja. Windows e macOS nunca
foram afetados porque usam backends de audio proprios.

O analyze passa a rodar com --no-fatal-infos: erro e warning continuam
reprovando, info nao. Do jeito anterior o job reprovava por
prefer_const_constructors espalhado pelo codigo, escondendo justamente o
que ele existe para pegar.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
QuillEditor.basic() cria um FocusNode e um ScrollController novos toda vez
que e chamado sem receber os seus. Como _WritingSurface.build roda a cada
notificacao do EditorProvider — e o QuillController notifica tambem em
mudanca de selecao — cada clique disparava um rebuild que trocava o no de
foco por um recem-criado. O foco morria no mesmo frame em que nascia e a
pagina ficava impossivel de escrever.

_WritingSurface vira StatefulWidget e passa a ser dona dos dois objetos,
criados uma vez e liberados no dispose.

De quebra, as margens da folha passam a ser padding do proprio editor em
vez de um Padding em volta dele: clicar na margem agora cai na area
editavel e posiciona o cursor, como em qualquer processador de texto.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Criar pagina existia so no menu "..." de cada capitulo, enquanto criar
capitulo tem um "+" no topo da coluna. A assimetria fazia parecer que
paginas nao podiam ser criadas.

Agora cada capitulo expandido termina com uma linha "+ Nova pagina", no
lugar onde a pagina vai de fato aparecer. O item do menu continua existindo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Os sons anteriores soavam de brinquedo por duas razoes, e a primeira era
dominante: duracao. Um clique de 160ms e quatro vezes o que se percebe como
resposta imediata, e o "sucesso" tinha 950ms — fanfarra, nao confirmacao.
Brilho era o fator secundario, real em tap (1013Hz de centroide) e hover
(1473Hz), faixa onde o ouvido e mais sensivel.

Os novos sao sintetizados: senoide grave com transiente curtissimo, filtro
de dois polos, envelope exponencial e fade-out obrigatorio no fim (forma de
onda cortada no meio do ciclo estala, e o estalo e o que soa barato). Sem
onda quadrada e sem glissando — quando precisa de duas alturas, sao duas
notas discretas separadas por uma quinta.

  tap      160ms 1013Hz -> 46ms  179Hz
  toggle   180ms  866Hz -> 38ms  261Hz
  hover     70ms 1473Hz -> 16ms  553Hz
  page     300ms 3565Hz -> 95ms 1836Hz
  open     500ms  893Hz -> 190ms 427Hz
  close    420ms  810Hz -> 160ms 415Hz
  success  950ms  532Hz -> 265ms 587Hz
  delete   400ms  206Hz -> 140ms  87Hz
  blocked  340ms  399Hz -> 125ms 135Hz

tools/gen_sounds.js e a fonte dos arquivos, versionado junto: sem ele os
WAVs seriam binarios que ninguem consegue ajustar. O PRNG e deterministico,
entao rodar de novo gera exatamente os mesmos arquivos.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Os dois dialogos (ConfirmDialog, TextPromptDialog) passavam os botoes como
tres itens soltos na lista `actions` do AlertDialog. O Flutter embrulha essa
lista num OverflowBar que decide, por conta propria, se os botoes cabem
lado a lado — e com um titulo curto essa conta erra e empilha os dois,
esticando o primeiro (Cancelar) para a largura inteira do dialogo.

A correcao entrega os botoes como um Row unico dentro de `actions`: com um
so filho, o OverflowBar nao tem decisao nenhuma a tomar.

De quebra: ConfirmDialog ganha largura fixa de 340px (igual ao
TextPromptDialog) em vez de variar com o tamanho da mensagem — um
"Excluir 'A'?" de titulo curto nao gera mais um dialogo estreito demais — e
os dois dialogos passam a usar o mesmo ritmo de espacamento entre titulo,
conteudo e acoes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
O artefato de cada build era so a pasta de release crua — no Windows, o
.exe ao lado de uma duzia de DLLs soltas, sem atalho nem desinstalador; no
Mac e no Linux, a mesma coisa em formato de pasta. Nada disso e algo que se
entrega para alguem instalar.

Windows: WrooteSetup.exe via Inno Setup (instalado no job por Chocolatey).
A versao vem do pubspec.yaml, lida num passo de PowerShell e passada ao
ISCC via /D, para as duas nunca se desalinharem.

macOS: Wroote.dmg via hdiutil, ja embutido no macOS — sem ferramenta de
terceiros. Um atalho simbolico para /Applications dentro da imagem da o
gesto padrao de instalar um app Mac (arrastar o icone).

Linux: Wroote-x86_64.AppImage via appimagetool, baixado no job (com
--appimage-extract-and-run, ja que os runners nao tem FUSE). Precisa de um
icone para o build passar; sem um proprio (assets/icon esta vazio), uso um
quadrado solido na cor de acento do app como placeholder.

Os tres viram artefatos novos (wroote-windows-installer,
wroote-macos-installer, wroote-linux-installer) ao lado dos artefatos de
pasta crua existentes, que continuam existindo.

Nenhum dos tres esta assinado (nem Authenticode no Windows, nem Developer
ID + notarizacao no Mac) — assinatura exige certificado pago e fica fora
do escopo disto. Sem assinatura, o instalador do Windows aciona o aviso do
SmartScreen e o .app do Mac aciona o Gatekeeper na primeira abertura; e o
comportamento esperado para software sem certificado, nao um bug daqui.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
assets/icon/icon.png (o "Wr" em serifada branca sobre azul marinho,
3000x3000) estava solto na raiz do repo — move para dentro da pasta que ja
existia vazia para isso, e liga ele no build.

As pastas nativas (windows/, macos/, linux/) nao sao versionadas: o
workflow as recria do zero a cada execucao via `flutter create`, sempre com
o icone padrao do Flutter. Por isso o icone e aplicado depois de gerar
essas pastas e antes de compilar, nao commitado dentro delas — commitar ali
seria apagado no proximo `flutter create`.

Windows: ICO multi-resolucao (256/128/64/48/32/16) via ImageMagick
(`magick convert -define icon:auto-resize=...`), sobrescrevendo
windows/runner/resources/app_icon.ico.

macOS: os 7 PNGs que o Contents.json do asset catalog espera
(app_icon_16.png ate app_icon_1024.png), gerados via `sips` (nativo do
macOS, sem instalar nada).

Linux: o quadrado solido placeholder do AppImage vira o icone de verdade,
reduzido para 256x256.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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