diff --git a/packages/web/src/components/layout/AppLayout.tsx b/packages/web/src/components/layout/AppLayout.tsx index e9263c80..ff82fa6e 100644 --- a/packages/web/src/components/layout/AppLayout.tsx +++ b/packages/web/src/components/layout/AppLayout.tsx @@ -1,4 +1,5 @@ import React, { useEffect } from 'react'; +import { UpdateBanner } from '../ui/UpdateBanner'; import { useExpressionStore } from '../../stores/expressionStore'; import { useParams, useNavigate } from 'react-router-dom'; import { SpaceSidebar } from './SpaceSidebar'; @@ -428,6 +429,7 @@ export function AppLayout() { (e.g. immediately after Join, or after popping voice-full back to the root). */} + diff --git a/packages/web/src/components/ui/UpdateBanner.tsx b/packages/web/src/components/ui/UpdateBanner.tsx new file mode 100644 index 00000000..37ec960b --- /dev/null +++ b/packages/web/src/components/ui/UpdateBanner.tsx @@ -0,0 +1,53 @@ +import { useEffect, useState } from 'react'; +import { isElectron } from '../../platform/platform'; +import { useT } from '../../i18n'; + +/** + * Aviso de que uma atualização já baixou e só falta reiniciar. + * + * O processo principal já mostrava uma notificação do sistema, que some sozinha + * e passa despercebida se a pessoa não estiver olhando. Este aviso fica na + * janela até ser atendido ou dispensado. + */ +export function UpdateBanner() { + const t = useT(); + const [version, setVersion] = useState(null); + const [dismissed, setDismissed] = useState(false); + + useEffect(() => { + if (!isElectron() || !window.backspace?.onUpdateDownloaded) return; + window.backspace.onUpdateDownloaded((info) => { + setVersion(info.version); + // Uma atualização nova reabre o aviso mesmo se a anterior foi dispensada: + // dispensar significa "agora não", não "nunca mais". + setDismissed(false); + }); + }, []); + + if (!version || dismissed) return null; + + return ( +
+
{t('update.ready')}
+

+ {t('update.readyVersion', { version })} +

+
+ + +
+
+ ); +} diff --git a/packages/web/src/i18n/locales/en.ts b/packages/web/src/i18n/locales/en.ts index e14917ba..c8e8d7a3 100644 --- a/packages/web/src/i18n/locales/en.ts +++ b/packages/web/src/i18n/locales/en.ts @@ -56,6 +56,12 @@ export const en = { 'accountMenu.copyId': 'Copy User ID', 'accountMenu.copied': 'Copied', + // Desktop update + 'update.ready': 'Update ready', + 'update.readyVersion': 'Version {version} is ready to install.', + 'update.restart': 'Restart to update', + 'update.later': 'Later', + // Custom emojis and stickers 'expressions.title': 'Emojis & Stickers', 'expressions.emojis': 'Emojis', diff --git a/packages/web/src/i18n/locales/pt-BR.ts b/packages/web/src/i18n/locales/pt-BR.ts index 9cfeab21..c1fa8ca2 100644 --- a/packages/web/src/i18n/locales/pt-BR.ts +++ b/packages/web/src/i18n/locales/pt-BR.ts @@ -55,6 +55,12 @@ export const ptBR: Partial = { 'accountMenu.copyId': 'Copiar ID do usuário', 'accountMenu.copied': 'Copiado', + // Atualização do app + 'update.ready': 'Atualização pronta', + 'update.readyVersion': 'A versão {version} está pronta para instalar.', + 'update.restart': 'Reiniciar para atualizar', + 'update.later': 'Depois', + // Emojis e figurinhas 'expressions.title': 'Emojis e figurinhas', 'expressions.emojis': 'Emojis',