Four owner requests in one pass. Rename: the PATCH /api/channels/:id route already accepted a name and a topic, and the API client already exposed it — the only thing missing was a way to reach it. The channel settings Overview tab now edits both, gated on MANAGE_CHANNELS like the server is, with Save/Discard appearing only when the form is dirty. The server's lowercase-and-hyphenate rule moved to @backspace/shared so the field can show what a name will actually become instead of letting it change shape on save; one copy of the rule, used by both sides. Stream volume: someone else's screen share now starts at 50 instead of 100 (DEFAULT_STREAM_VOLUME). The publisher boosts system audio before sending, so the old default arrived far too loud for a viewer who never touched the slider. Only the default moves — the slider still covers the full range and a value the user set is still persisted. Sound effects: SFX_BASE_VOLUME 0.8 -> 0.4, halving every cue. The .ogg files were left alone; they already peak below full scale, so the harshness was level, not recorded distortion. Every SFX playback path goes through getSfxVolume(), so this is the single knob. Translations: channel settings (including the override editor's permission labels), the friends page end to end — tabs, lists, requests, the add tab and discovery cards — the invite modal including its per-invite failure reasons, and the group-DM member actions. Failure reasons are carried as translation keys rather than finished text, so results already on screen re-label when the language changes. Verified: web build (tsc + vite), server typecheck, 490 web tests, 804 server tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
9.7 KiB
Roadmap — fork Resenha
Plano de features próprias desta instância. Arquivo exclusivo do fork (nome com sufixo para não colidir com arquivos do upstream em merges).
Escrito em português por ser documento de planejamento do dono do fork; o código e os commits seguem em inglês, como o resto do repositório.
Entregue
| Feature | Commit | Nota |
|---|---|---|
| Ir para a call clicando no nome do canal | c70b0095 |
Exigiu o voiceStore passar a guardar o espaço da call — antes ele não sabia onde a call estava assim que o usuário navegava para outro servidor |
| Botão de GIF redesenhado | 20526e1b |
Contorno vazado com letras cheias, no lugar do bloco sólido |
| Explorador de GIF no banner | 20526e1b |
Sem upload: banner já aceita URL absoluta no cliente e no servidor |
| Teste de microfone com retorno | bfe62d70 |
AudioManager.startMicTest/stopMicTest; devolve o microfone ao parar, com duas travas independentes |
| Bloco de atividade no perfil | d7da0ff2 |
ProfileActivity; inclui correção de validação de assets no servidor |
| Favoritar GIFs + categorias (#6) | fb662bfe |
Favoritos no servidor, por conta; guarda o resultado inteiro porque o provedor não busca por id |
| Registro de auditoria (#9) | bbb190cb |
Tabela append-only genérica; 8 ganchos; sair ≠ ser expulso |
| Estatísticas do grupo | 18300517 |
Tabela própria de sessões de voz; ganchos no ponto único de entrada/saída |
| Spotify por OAuth (atividade com capa e progresso) | 75316b08 |
Token só no servidor; state assinado; atividades por fonte para não brigar com o detector do Electron |
| Menu do próprio nome | f5451e1b |
Perfil, status e copiar ID. Sem Clips/trocar conta — não existem aqui |
| Cronômetro da call | f5451e1b |
startedAt do servidor; zera sozinho porque sala vazia é destruída |
| Correções do Spotify (sincronia, sumiço, barra) | c899253e |
Pausa virou estado; horário do servidor no ready corrige relógio |
| Soundboard no app desktop | c899253e |
window.prompt não existe no Electron; campo inline no lugar |
| Áudio do sistema sem eco | d525bbb8 5b848432 |
Módulo nativo com isolamento por processo + ganho e preset de música |
| Instaladores publicados pelo Gitea | ce6bba05 |
GitHub compila, Gitea distribui; atualização automática ligada |
| Fixar mensagens no canal | 4ceb5cd6 |
Estado na própria mensagem; painel no cabeçalho; limite de 50 |
| Busca: filtros embutidos e tradução | 50a8f12c |
Os filtros já existiam; faltava de:fulano e descoberta |
| Emojis e figurinhas do servidor | 7d003021 |
:nome: no markdown sem plugin; figurinha como mensagem inteira |
| Fundação de i18n (en + pt-BR) | 688a1335 |
src/i18n/; pt-BR é parcial e cai para inglês. Aba Idioma nas configurações |
| Renomear canal (nome e tópico) | (ver git log) | Rota PATCH /api/channels/:id já existia; faltava interface. Normalização em shared/constants para servidor e web usarem a mesma regra |
| Volume da tela em 50% por padrão | (ver git log) | DEFAULT_STREAM_VOLUME; o publicador reforça o áudio do sistema, então o padrão anterior chegava alto demais |
| Sons 50% mais baixos | (ver git log) | Só SFX_BASE_VOLUME (0.8 → 0.4); os .ogg não foram regerados |
| Preview de perfil nos participantes da call | (ver git log) | O popout já existia e era aberto de 11 lugares; nenhum era de voz. Ligado nas linhas da lista de voz e no nome dos tiles da grade |
Já existia no código (verificado, não construir de novo)
-
Busca com filtros — servidor (
q,from,has,before,after), client de API e painel noSearchPopoverjá existiam completos. Só faltava tradução, sintaxe embutida (de:fulano) e descoberta. -
Animação de digitação —
TypingIndicator.tsx, três pontosanimate-bounceescalonados em 0/150/300ms. -
Sons de call/stream —
SoundController.tsx, montado noAppLayout: stream started/ended, alguém entra/sai da tela, entra/sai da call, câmera, mute, ringing. Os.oggestão emweb/public/sounds/. -
Preview de perfil ancorado —
uiStore.openUserProfile(user, anchor, placement)guardauserProfilePopout; popout posicionado no desktop, tela cheia no mobile. Já era aberto por mensagens, menções, avatares, lista de membros, DMs e painel de atividade. O que faltava era só a voz — agora ligado. Continua faltando o bloco de atividade do print do Discord, que é a #8.
Se qualquer um dos dois não se manifestar em uso, o trabalho é depuração, não implementação.
Pendente — pedido original
Ordem sugerida: as pequenas primeiro, as grandes uma de cada vez.
| # | Feature | Tamanho | Observação técnica |
|---|
Pendente — ideias aprovadas
| Feature | Tamanho | Observação técnica |
|---|---|---|
| Watch party | Grande | O screen share do LiveKit já existe; falta sincronizar posição de reprodução entre participantes |
Regra de idioma (a partir de 2026-08-31)
Funcionalidade nova sai com interface em pt-BR, e a cada update um sistema existente é traduzido. Os dois idiomas coexistem. Código, comentários e commits seguem em inglês.
A fundação está pronta (src/i18n/). Para traduzir um sistema: adicione as
chaves em locales/en.ts, traduza em locales/pt-BR.ts e troque as strings
fixas por t('chave'). O que faltar cai para o inglês sozinho.
Sistemas já traduzidos
- Configurações → navegação e aba Idioma
- Configurações → Voz (dispositivo de entrada, volume, teste de microfone)
- Cartão de perfil (sobre mim, membro desde, enviar mensagem, atividade)
- Configurações → Privacidade
- Configurações → Conexões (nasceu bilíngue)
- Seletor de GIF
- Chat: composer e mensagens (placeholder, anexos, responder, reações)
- Barra lateral: servidores, canais e menus de contexto
- Lista de membros (grupos por cargo, carregamento)
- Busca (rótulos, filtros e sintaxe embutida)
- Registro de auditoria e Estatísticas (nasceram bilíngues)
- Configurações do canal (visão geral, privacidade, exclusão e rótulos de permissão)
- Amigos: abas, listas, pedidos, aba de adicionar e cartões de descoberta
- Modal de convite (incluindo os motivos de falha por convite)
- Lista de membros da DM em grupo (remover e transferir propriedade)
Fila sugerida de tradução
Configurações restantes (conta, vídeo, atalhos, instância) · configurações do
servidor e cargos · telas de erro · explorar servidores · DMs em grupo
(GroupDmSettings, AddDmMemberModal)
Correções pendentes
| Problema | Causa provável | Correção |
|---|
App desktop — já existia (verificado 2026-08-31)
As três pedidas já estão implementadas e ligadas de ponta a ponta. Não construir de novo.
- Bandeja —
createTray()emdesktop/src/main.ts, chamada na inicialização; fechar a janela esconde em vez de sair (mainWindow.on('close')). - Notificações nativas —
showNotification()no processo principal, canal IPCshow-notification, e o web já chama porplatform/notifications.ts. - Áudio do sistema no compartilhamento —
setDisplayMediaRequestHandlerdevolveaudio: 'loopback'; existe caixa de seleção noScreenSharePickerligada ascreenShareConfig.shareAudio, que atravessa o IPC.
Se algum não se manifestar em uso, o trabalho é depuração, não construção.
Aprovadas, a fazer depois (2026-08-31)
Escolhidas pelo dono, inspiradas no Discord. Nenhuma iniciada.
| Feature | Tamanho | Observação técnica |
|---|---|---|
| Resposta rápida de voz (soundboard por atalho) | Pequena | O soundboard já está pronto; falta só marcar favoritos e ligar a atalhos de teclado, sem abrir painel. Cuidado: o limite de repetição do servidor continua valendo e é o que impede virar metralhadora |
| Cargos com ícone e exibição separada | Média | Cargos e cores já existem; falta ícone, o campo "exibir separadamente" e o agrupamento na lista de membros |
Ideias novas — a avaliar
Ordenadas por relação valor/custo para um servidor de grupo fechado.
| Sistema | Tamanho | Por que faz sentido aqui |
|---|---|---|
| Backup fora da VPS | Pequena | Hoje app, banco, uploads, backups e as três cópias do repositório morrem no mesmo evento. Um envio periódico para fora resolve |
| Aniversários e lembretes | Pequena | Alto retorno afetivo, custo baixo: campo de data + verificação diária + mensagem no canal |
| Perfis por servidor | Média | Apelido e avatar diferentes por espaço, como no Discord. O modelo já tem membro por espaço |
| Eventos agendados com presença | Média | "Sexta 21h" com confirmação. Encaixa nas notificações e no PWA já instalado |
| Notificações push de verdade | Média | O vite-plugin-pwa e o service worker já estão lá; falta Web Push (VAPID) e o registro no servidor |
| Níveis e conquistas | Média | Gamificação por tempo em call e mensagens. Mesmo registro de eventos da auditoria e das estatísticas — três features, um mecanismo |
| Clipes de call | Grande | "Salvar os últimos 30 segundos" depois de alguém falar besteira. O LiveKit tem egress; exige buffer contínuo e armazenamento |
| Fila de música compartilhada | Grande | Um participante-robô publicando faixa de áudio na sala LiveKit. É o que mais muda o uso de um servidor de amigos, e o mais caro |
| Autenticação em duas etapas | Média | Só faz sentido depois de decidir o modelo de cadastro |
Dependência que vale respeitar
Auditoria (#9) e Estatísticas compartilham o mesmo mecanismo: uma tabela de eventos append-only no servidor. Construir a auditoria primeiro e as estatísticas como leitura agregada dessa mesma tabela evita escrever dois sistemas de registro paralelos que divergem com o tempo.