diff --git a/docs/roadmap-resenha.md b/docs/roadmap-resenha.md index db2d78a4..1e3e8b08 100644 --- a/docs/roadmap-resenha.md +++ b/docs/roadmap-resenha.md @@ -32,6 +32,7 @@ código e os commits seguem em inglês, como o resto do repositório. | 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 | +| Atualização do desktop verificada com mais frequência | (ver git log) | Era só na abertura e de 4 em 4 horas; agora a cada 30 min e ao focar a janela, com trava de 5 min | | 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) @@ -94,12 +95,16 @@ fixas por `t('chave')`. O que faltar cai para o inglês sozinho. - 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) +- Configurações → Área de trabalho (início automático, atualizações, instância) +- Configurações → Voz: dispositivo de saída (completa a aba, junto com a entrada) +- Configurações → Atalhos (incluindo os nomes das ações e o aviso de conflito) +- Configurações → Conta (perfil, senha, conta desligada da origem, zona de perigo) +- Explorar servidores (cartões, entrar, pedir para entrar) ### 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`) +Configurações → Vídeo · Configurações → Instância · configurações do servidor e +cargos · telas de erro · DMs em grupo (`GroupDmSettings`, `AddDmMemberModal`) ## Correções pendentes diff --git a/packages/desktop/src/main.ts b/packages/desktop/src/main.ts index fee93871..3598e57b 100644 --- a/packages/desktop/src/main.ts +++ b/packages/desktop/src/main.ts @@ -814,7 +814,14 @@ function initAutoUpdater(): void { let updateConfirmed = false; + // Cadence state. `lastCheckAt` is stamped from the event rather than from + // the callers, so a manual "check for updates" from the settings panel + // counts too and a focus arriving right after it doesn't check twice. + let lastCheckAt = 0; + let downloaded = false; + autoUpdater.on('checking-for-update', () => { + lastCheckAt = Date.now(); recoveryStore.update({ updateState: 'checking', lastCheckResult: null }); updateConfirmed = false; }); @@ -836,6 +843,7 @@ function initAutoUpdater(): void { }); autoUpdater.on('update-downloaded', (info: { version: string }) => { + downloaded = true; const version = info.version.slice(0, 32); recoveryStore.update({ updateState: 'downloaded', updateVersion: version }); mainWindow?.webContents.send('update-downloaded', { version }); @@ -875,17 +883,28 @@ function initAutoUpdater(): void { } }); - // Initial check with 10s delay (existing behavior) - setTimeout(() => { - updateConfirmed = false; - autoUpdater.checkForUpdates().catch(() => {}); - }, 10_000); + // A release published while the app sits open used to go unnoticed until + // the next poll — the startup check had long since run, and four hours is + // a long time to look at a stale version. Poll more often, and also check + // when the user comes back to the window, which is exactly when they would + // notice an update anyway. + const POLL_INTERVAL_MS = 30 * 60 * 1000; + const MIN_GAP_MS = 5 * 60 * 1000; // keeps alt-tabbing off the feed - // Periodic check every 4 hours (existing behavior) - setInterval(() => { + const maybeCheck = (): void => { + if (downloaded) return; // already staged; nothing left to look for + if (Date.now() - lastCheckAt < MIN_GAP_MS) return; updateConfirmed = false; autoUpdater.checkForUpdates().catch(() => {}); - }, 4 * 60 * 60 * 1000); + }; + + setTimeout(maybeCheck, 10_000); + setInterval(maybeCheck, POLL_INTERVAL_MS); + + // App-level rather than mainWindow-level: the window is destroyed and + // recreated when closed to tray and reopened, and a listener bound to the + // old instance would go quiet after the first close. + app.on('browser-window-focus', maybeCheck); } catch { // Auto-updater unavailable — recovery surface still functions, just // without update affordances. autoUpdaterRef stays null; recovery action diff --git a/packages/web/src/components/chat/ExplorePage.tsx b/packages/web/src/components/chat/ExplorePage.tsx index 875cd914..0b14a8e1 100644 --- a/packages/web/src/components/chat/ExplorePage.tsx +++ b/packages/web/src/components/chat/ExplorePage.tsx @@ -8,8 +8,10 @@ import { getSpaceGradient } from '../../utils/gradients'; import { extractDominantColors, colorsToGradient } from '../../utils/colorExtractor'; import { MemberListToggleButton } from '../layout/MemberListToggleButton'; import { useSpaceJoin } from '../../hooks/useSpaceJoin'; +import { useT } from '../../i18n'; export function ExplorePage() { + const t = useT(); const navigate = useNavigate(); const setCurrentSpace = useSpaceStore((s) => s.setCurrentSpace); @@ -73,7 +75,7 @@ export function ExplorePage() { - Explore + {t('explore.title')}
@@ -81,7 +83,7 @@ export function ExplorePage() {
handleSearchChange(e.target.value)} className="input-search w-full" @@ -107,7 +109,7 @@ export function ExplorePage() {
{!discoveryEnabled && (
- Space discovery is disabled by the instance administrator. + {t('explore.disabled')}
)} @@ -124,9 +126,7 @@ export function ExplorePage() {

- {searchQuery - ? 'No spaces match your search.' - : 'No discoverable spaces yet.'} + {searchQuery ? t('explore.empty.search') : t('explore.empty.none')}

) : ( @@ -138,7 +138,7 @@ export function ExplorePage() { - You're in all discoverable spaces + {t('explore.allJoined')}
)} @@ -173,7 +173,7 @@ export function ExplorePage() { - Joined + {t('explore.joined')} {joinedSpaces.length} @@ -207,6 +207,7 @@ function SpaceCard({ space: TaggedExploreSpace; onJoinSuccess: (spaceId: string) => void; }) { + const t = useT(); const { isJoined, isPublic, @@ -297,7 +298,7 @@ function SpaceCard({ ? 'bg-accent-mint/20 text-accent-mint' : 'bg-accent-amber/20 text-accent-amber' }`}> - {isPublic ? 'Public' : 'Request'} + {isPublic ? t('explore.badge.public') : t('explore.badge.request')}
@@ -330,7 +331,7 @@ function SpaceCard({ {space.description}

) : ( -

No description

+

{t('explore.noDescription')}

)}
@@ -338,7 +339,7 @@ function SpaceCard({ - {space.memberCount} {space.memberCount === 1 ? 'member' : 'members'} + {space.memberCount} {t(space.memberCount === 1 ? 'explore.member' : 'explore.members')} {originLabel && ( @@ -360,7 +361,7 @@ function SpaceCard({ onClick={handleViewSpace} className="w-full py-2 bg-accent-mint/15 hover:bg-accent-mint/25 text-accent-mint text-sm font-medium rounded transition-colors" > - View Space + {t('explore.view')} ) : isPublic ? ( ) : isPending ? ( @@ -382,14 +383,14 @@ function SpaceCard({ disabled className="w-full py-2 bg-interactive-muted text-txt-tertiary text-sm font-medium rounded cursor-default" > - Request Pending + {t('explore.requestPending')} ) : showRequestForm ? (