Pular para o conteúdo
Development

Ensinando o Greenhouse a pré-visualizar áudio do vault dentro do app

Por Victor Da Luz
taurirustaudiodev-loggreenhouse

O Greenhouse é um app desktop que impõe uma cadência de processo criativo: capturar uma ideia, deixá-la amadurecer, trabalhar nela, tocá-la, e por fim guardar no vault ou lançar. Uma lacuna me incomodava - quando uma ideia ou projeto tem um bounce de áudio parado na sua pasta, o único jeito de ouvir é clicar em “Show in Finder” e ir procurar você mesmo. Eu queria algo mais parecido com o Quick Look do macOS: aperta um botão, ouve o rascunho, decide.

Antes de escrever qualquer código de UI, escrevi uma investigação exploratória (spike). O Greenhouse é um app Tauri v2, e eu não sabia de fato como uma webview do Tauri tem permissão para tocar arquivos locais - presumi que estaria bloqueada por padrão, mas queria descobrir exatamente o quanto bloqueada, e quanto custaria abrir uma fresta na porta.

A fiação de segurança era greenfield

Descobri que o app não expunha nenhum byte de arquivo para a webview. Nenhum asset protocol, nenhum plugin de filesystem, e uma Content-Security-Policy travada em default-src 'self'. A única coisa que tocava o filesystem a partir do frontend era um botão “abrir esta pasta no Finder”, que apenas entrega um caminho para o sistema operacional - a webview em si nunca vê o conteúdo dos arquivos.

Isso é na verdade um bom sinal para um app preocupado com segurança, mas significava que renderizar áudio dentro do app não era um ajuste pequeno. Eu precisaria alargar a CSP, o que era desconfortável logo depois de ter terminado uma passada de hardening de segurança nesse mesmo app.

Provando antes de construir

Em vez de debater a troca no abstrato, construí uma prova de conceito descartável. O Tauri tem um “asset protocol” embutido - habilita uma feature do Cargo, vira uma flag de config, e a webview pode requisitar arquivos locais através de um esquema de URL especial em vez de um fetch de rede. A parte interessante é o escopo: você não quer dar à webview acesso ao filesystem inteiro, só às pastas que ela realmente precisa.

Como a localização do vault no Greenhouse é escolhida pelo usuário durante o onboarding - não é um caminho fixo embutido no build - a abordagem usual de “listar pastas permitidas no arquivo de config” não se encaixa muito bem. O Tauri tem uma API em tempo de execução para isso: você concede acesso a um diretório específico em código, exatamente no momento em que descobre qual é esse diretório. Então a raiz do vault entra no escopo do asset protocol exatamente uma vez, no momento em que é definida ou carregada na inicialização - nunca mais amplo do que isso.

Também alarguei a Content-Security-Policy, mas de forma estreita: só toquei nas duas diretivas que carregam mídia (img-src, media-src), e deixei a política padrão exatamente tão restritiva quanto era. Um diff pequeno e explicável.

Então eu de fato conduzi o app para provar que funcionava - não só “compilou,” mas um script que abre o app de verdade, captura uma ideia real pela mesma camada de IPC que a UI usa, solta um arquivo WAV real na sua pasta a partir de fora da webview (simulando um usuário salvando um bounce ali), e clica até chegar na pré-visualização. Depois perguntei ao elemento de áudio ao vivo em que estado ele estava: totalmente carregado, duração correta, sem erros, servido através do próprio esquema de URL do asset protocol. Uma coisa que só aprendi testando no build real do macOS: a URL de fato que o Tauri usa no macOS (asset://localhost/...) não bate com o que a maior parte da documentação que encontrei mostra, que descreve a forma usada em Windows/Linux. Coisa pequena, mas é exatamente o tipo de detalhe que você não pega lendo documentação - você pega rodando a coisa.

Da investigação exploratória à feature em produção

Com a abordagem já validada, construí a versão real: um painel “Files” na tela de detalhe do projeto, um botão Preview ao lado de qualquer coisa que parece áudio, e um player leve que abre num overlay. Mantive o “Show in Finder” como estava em vez de substituí-lo - algumas pessoas ainda vão querer o arquivo real, não uma pré-visualização.

Um bug pequeno e satisfatório: meu primeiro rascunho fazia o áudio tocar automaticamente assim que você abria a pré-visualização. Meus testes automatizados de acessibilidade começaram a travar naquela tela, e desvendar o motivo me levou a uma regra que eu já meio que sabia e nunca tinha internalizado direito: não toque áudio automaticamente. É uma diretriz real de acessibilidade, não só um incômodo de teste. Tirar o autoplay corrigiu o teste e deixou a feature melhor ao mesmo tempo - o tipo de coincidência que não é bem uma coincidência.

Limitei essa primeira versão só a áudio, de propósito. Imagens e PDFs reaproveitariam a mesma infraestrutura, mas eu não tinha testado com eles, e a razão de existir do Greenhouse é justamente proteger o processo criativo das pessoas do feature creep - incluindo o meu próprio.

Leitura relacionada

Development

O scan que se ofereceu para importar a si mesmo

Um scanner de importação que encontrou a própria estrutura interna do app, e depois voltou a oferecer uma pasta que tinha acabado de importar, duas versões da mesma conversa que faltava entre camadas.

Ler
Development

A pasta que ficou parada

Uma revisão de código encontrou um invariante que a feature de adotar/importar do Greenhouse quebrava silenciosamente, e a correção que tornou tudo chato de novo.

Ler
Development

Três portas que nunca foram trancadas

Um CSP nulo, um valor de config unido a um caminho de arquivo sem checagem, e um seletor de vault que aceitaria seu diretório home, nada quebrado ainda, tudo destrancado.

Ler

Você também pode achar útil

AdGuard

AdGuard para iOS

Bloqueio de anúncios e rastreadores em todo o sistema no iOS, sem necessidade de um servidor DNS separado.

Como afiliado da AdGuard, ganho com compras qualificadas.

Saiba mais
Proton

Proton Mail

E-mail criptografado de ponta a ponta, com arquitetura de acesso zero.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais
Proton

Proton Drive

Armazenamento em nuvem criptografado, da equipe por trás do Proton Mail.

Como parceiro da Proton, ganho com compras qualificadas dos serviços de privacidade e segurança da Proton (Pass, Mail, VPN, Drive).

Saiba mais