diff --git a/assets/jsons/translations/de.json b/assets/jsons/translations/de.json index 202810d7..03d88495 100644 --- a/assets/jsons/translations/de.json +++ b/assets/jsons/translations/de.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "veraltet" + "outdated": "veraltet", + "update-text": "BSManager {version} ist verfügbar!", + "update-button": "Aktualisieren und neu starten", + "see-changelog": "Änderungen ansehen" }, "nav-bar": { "add-version": "Version hinzufügen", @@ -337,6 +340,13 @@ "error-notification": { "message": "Es ist ein Fehler aufgetreten, die Systemproxyeinstellungen können nicht geändert werden." } + }, + "auto-update": { + "title": "Automatische Aktualisierung", + "description": "BSManager wird beim Start der Anwendung automatisch aktualisiert.", + "error-notification": { + "message": "Ein Fehler ist aufgetreten, die Einstellungen für die automatische Aktualisierung können nicht geändert werden." + } } } } diff --git a/assets/jsons/translations/en.json b/assets/jsons/translations/en.json index 4ae373b0..fb33467b 100644 --- a/assets/jsons/translations/en.json +++ b/assets/jsons/translations/en.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "outdated" + "outdated": "outdated", + "update-text": "BSManager {version} is available!", + "update-button": "Update and Restart", + "see-changelog": "See changelog" }, "nav-bar": { "add-version": "Add a version", @@ -337,6 +340,13 @@ "error-notification": { "message": "An error occurred, unable to change system proxy settings." } + }, + "auto-update": { + "title": "Auto Update", + "description": "BSManager will automatically update when you launch the application.", + "error-notification": { + "message": "An error occurred, unable to change auto update settings." + } } } } diff --git a/assets/jsons/translations/es.json b/assets/jsons/translations/es.json index 507b3be5..18d87f1f 100644 --- a/assets/jsons/translations/es.json +++ b/assets/jsons/translations/es.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "obsoleto" + "outdated": "obsoleto", + "update-text": "¡BSManager {version} está disponible!", + "update-button": "Actualizar y reiniciar", + "see-changelog": "Ver los cambios" }, "nav-bar": { "add-version": "Agregar una versión", @@ -337,6 +340,13 @@ "error-notification": { "message": "Ocurrió un error, no se pueden cambiar los ajustes del proxy del sistema." } + }, + "auto-update": { + "title": "Actualización automática", + "description": "BSManager se actualizará automáticamente al iniciar la aplicación.", + "error-notification": { + "message": "Ocurrió un error, no se pudo cambiar la configuración de actualización automática." + } } } } diff --git a/assets/jsons/translations/fr.json b/assets/jsons/translations/fr.json index 5bdac340..40d05cd6 100644 --- a/assets/jsons/translations/fr.json +++ b/assets/jsons/translations/fr.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "obsolète" + "outdated": "obsolète", + "update-text": "BSManager {version} est disponible!", + "update-button": "Mettre à jour et redémarrer", + "see-changelog": "Voir les changements" }, "nav-bar": { "add-version": "Ajouter une version", @@ -337,6 +340,13 @@ "error-notification": { "message": "Une erreur est survenue, impossible de modifier les paramètres du proxy système." } + }, + "auto-update": { + "title": "Mise à jour automatique", + "description": "BSManager se mettra automatiquement à jour au lancement de l'application.", + "error-notification": { + "message": "Une erreur est survenue, impossible de modifier les paramètres de mise à jour automatique." + } } } } diff --git a/assets/jsons/translations/it.json b/assets/jsons/translations/it.json index a0e51c9c..c7e542b4 100644 --- a/assets/jsons/translations/it.json +++ b/assets/jsons/translations/it.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "obsoleta" + "outdated": "obsoleta", + "update-text": "BSManager {version} è disponibile!", + "update-button": "Aggiorna e riavvia", + "see-changelog": "Vedi i cambiamenti" }, "nav-bar": { "add-version": "Aggiungi una versione", @@ -337,6 +340,13 @@ "error-notification": { "message": "C'è stato un errore, impossibile cambiare le impostazioni del proxy di sistema." } + }, + "auto-update": { + "title": "Aggiornamento automatico", + "description": "BSManager si aggiornerà automaticamente all'avvio dell'applicazione.", + "error-notification": { + "message": "Si è verificato un errore, impossibile modificare le impostazioni di aggiornamento automatico." + } } } } diff --git a/assets/jsons/translations/ja.json b/assets/jsons/translations/ja.json index 47600eb5..d2d05150 100644 --- a/assets/jsons/translations/ja.json +++ b/assets/jsons/translations/ja.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "時代遅れ" + "outdated": "時代遅れ", + "update-text": "BSManager {version} が利用可能です!", + "update-button": "更新して再起動", + "see-changelog": "変更点を確認" }, "nav-bar": { "add-version": "バージョンを追加", @@ -337,6 +340,13 @@ "error-notification": { "message": "エラーが発生しました。システムプロキシ設定を変更できません。" } + }, + "auto-update": { + "title": "自動更新", + "description": "アプリケーション起動時にBSManagerが自動的に更新されます。", + "error-notification": { + "message": "エラーが発生し、自動更新の設定を変更できませんでした。" + } } } } diff --git a/assets/jsons/translations/ko.json b/assets/jsons/translations/ko.json index d051216d..24dc70e5 100644 --- a/assets/jsons/translations/ko.json +++ b/assets/jsons/translations/ko.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "구식" + "outdated": "구식", + "update-text": "BSManager {version} 가 사용 가능합니다!", + "update-button": "업데이트 후 재시작", + "see-changelog": "변경 사항 보기" }, "nav-bar": { "add-version": "버전 추가", @@ -337,6 +340,13 @@ "error-notification": { "message": "오류가 발생했습니다. 시스템 프록시 설정을 변경할 수 없습니다." } + }, + "auto-update": { + "title": "자동 업데이트", + "description": "애플리케이션을 실행할 때 BSManager가 자동으로 업데이트됩니다.", + "error-notification": { + "message": "오류가 발생하여 자동 업데이트 설정을 변경할 수 없습니다." + } } } } diff --git a/assets/jsons/translations/pt-br.json b/assets/jsons/translations/pt-br.json index 36a86561..76921b70 100644 --- a/assets/jsons/translations/pt-br.json +++ b/assets/jsons/translations/pt-br.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "Desatualizado" + "outdated": "Desatualizado", + "update-text": "BSManager {version} está disponível!", + "update-button": "Atualizar e reiniciar", + "see-changelog": "Ver os changelogs" }, "nav-bar": { "add-version": "Adicionar uma versão", @@ -337,6 +340,13 @@ "error-notification": { "message": "Um erro aconteceu, não foi possível alterar a configuração de proxy de sistema." } + }, + "auto-update": { + "title": "Atualização automática", + "description": "O BSManager será atualizado automaticamente ao iniciar o aplicativo.", + "error-notification": { + "message": "Ocorreu um erro, não foi possível alterar as configurações de atualização automática." + } } } } diff --git a/assets/jsons/translations/ru.json b/assets/jsons/translations/ru.json index 5ba36e17..ce71eeda 100644 --- a/assets/jsons/translations/ru.json +++ b/assets/jsons/translations/ru.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "устаревший" + "outdated": "устаревший", + "update-text": "BSManager {version} доступен!", + "update-button": "Обновить и перезапустить", + "see-changelog": "Смотреть изменения" }, "nav-bar": { "add-version": "Добавить версию игры", @@ -337,6 +340,13 @@ "error-notification": { "message": "Произошла ошибка, не удалось изменить настройки системного прокси." } + }, + "auto-update": { + "title": "Автообновление", + "description": "BSManager будет автоматически обновляться при запуске приложения.", + "error-notification": { + "message": "Произошла ошибка, не удалось изменить настройки автообновления." + } } } } diff --git a/assets/jsons/translations/tl.json b/assets/jsons/translations/tl.json index 42ea75c4..748bcd43 100644 --- a/assets/jsons/translations/tl.json +++ b/assets/jsons/translations/tl.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "lipas na" + "outdated": "lipas na", + "update-text": "Ang BSManager {version} ay available!", + "update-button": "I-update at i-restart", + "see-changelog": "Tingnan ang mga pagbabago" }, "nav-bar": { "add-version": "Magdagdag ng bersyon", @@ -337,6 +340,13 @@ "error-notification": { "message": "Nagkaroon ng error, hindi ma-bago ang setting ng system proxy." } + }, + "auto-update": { + "title": "Awtomatikong Pag-update", + "description": "Ang BSManager ay awtomatikong mag-uupdate kapag binuksan mo ang aplikasyon.", + "error-notification": { + "message": "Nagkaroon ng error, hindi mababago ang mga setting ng awtomatikong pag-update." + } } } } diff --git a/assets/jsons/translations/uk.json b/assets/jsons/translations/uk.json index 260e831c..903d9824 100644 --- a/assets/jsons/translations/uk.json +++ b/assets/jsons/translations/uk.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "застарілий" + "outdated": "застарілий", + "update-text": "BSManager {version} доступний!", + "update-button": "Оновити та перезапустити", + "see-changelog": "Переглянути зміни" }, "nav-bar": { "add-version": "Додати версію", @@ -337,6 +340,13 @@ "error-notification": { "message": "Сталася помилка, неможливо змінити налаштування системного проксі." } + }, + "auto-update": { + "title": "Автоматичне оновлення (Avtomatychne onovlennya)", + "description": "BSManager автоматично оновлюватиметься, коли ви запустите програму.", + "error-notification": { + "message": "Сталася помилка, неможливо змінити налаштування автоматичного оновлення." + } } } } diff --git a/assets/jsons/translations/zh-tw.json b/assets/jsons/translations/zh-tw.json index 6d3553f9..84985291 100644 --- a/assets/jsons/translations/zh-tw.json +++ b/assets/jsons/translations/zh-tw.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "過時" + "outdated": "過時", + "update-text": "BSManager {version} 可用!", + "update-button": "更新並重新啟動", + "see-changelog": "查看變更" }, "nav-bar": { "add-version": "新增版本", @@ -337,6 +340,13 @@ "error-notification": { "message": "發生錯誤,無法更改系統代理設置。" } + }, + "auto-update": { + "title": "自動更新", + "description": "啟動應用程式時,BSManager 將自動更新。", + "error-notification": { + "message": "發生錯誤,無法更改自動更新設定。" + } } } } diff --git a/assets/jsons/translations/zh.json b/assets/jsons/translations/zh.json index f6ee41f0..5f171a95 100644 --- a/assets/jsons/translations/zh.json +++ b/assets/jsons/translations/zh.json @@ -37,7 +37,10 @@ } }, "title-bar": { - "outdated": "过时" + "outdated": "过时", + "update-text": "BSManager {version} 可用!", + "update-button": "更新并重新启动", + "see-changelog": "查看变更" }, "nav-bar": { "add-version": "添加版本", @@ -337,6 +340,13 @@ "error-notification": { "message": "发生错误,无法启用系统代理。" } + }, + "auto-update": { + "title": "自动更新", + "description": "启动应用程序时,BSManager 将自动更新。", + "error-notification": { + "message": "发生错误,无法更改自动更新设置。" + } } } } diff --git a/src/main/ipcs/launcher-ipcs.ts b/src/main/ipcs/launcher-ipcs.ts index 1091cbf7..ee92cdd2 100644 --- a/src/main/ipcs/launcher-ipcs.ts +++ b/src/main/ipcs/launcher-ipcs.ts @@ -14,6 +14,11 @@ ipc.on("check-update", (_, reply) => { reply(from(updaterService.isUpdateAvailable())); }); +ipc.on("get-available-update", (_, reply) => { + const updaterService = AutoUpdaterService.getInstance(); + reply(from(updaterService.getAvailableUpdate())); +}); + ipc.on("install-update", (_, reply) => { const updaterService = AutoUpdaterService.getInstance(); reply(of(updaterService.quitAndInstall())); diff --git a/src/main/main.ts b/src/main/main.ts index 60d4bd92..40c9e9d3 100644 --- a/src/main/main.ts +++ b/src/main/main.ts @@ -28,6 +28,7 @@ import { StaticConfigurationService } from "./services/static-configuration.serv import { configureProxy } from './helpers/proxy.helpers'; import { deleteFileSync, deleteFolderSync } from "./helpers/fs.helpers"; import { tryit } from "shared/helpers/error.helpers"; +import { AutoUpdate } from "shared/models/config"; const isDebug = process.env.NODE_ENV === "development" || process.env.DEBUG_PROD === "true"; const staticConfig = StaticConfigurationService.getInstance(); @@ -121,8 +122,6 @@ if (!gotTheLock) { app.whenReady().then(() => { - - app.setAppUserModelId(APP_NAME); initServicesMustBeInitialized(); @@ -134,10 +133,18 @@ if (!gotTheLock) { DeepLinkService.getInstance().dispatchLinkOpened(deepLink); } else if (associatedFile) { FileAssociationService.getInstance().handleFileAssociation(associatedFile); + } else if (process.platform === "linux") { + createWindow("index.html"); } else { - createWindow(process.platform === "linux" - ? "index.html" : "launcher.html" - ); + const configService = StaticConfigurationService.getInstance(); + const autoUpdate = configService.get("auto-update", AutoUpdate.ALWAYS); + const update = autoUpdate !== AutoUpdate.NEVER; + if (autoUpdate === AutoUpdate.ONCE) { + configService.set("auto-update", AutoUpdate.NEVER); + } + + // Skip launcher only if autoUpdate is strictly false + createWindow(update ? "launcher.html" : "index.html"); } SteamLauncherService.getInstance().restoreSteamVR(); diff --git a/src/main/services/auto-updater.service.ts b/src/main/services/auto-updater.service.ts index 9a054115..fd8a6a4f 100644 --- a/src/main/services/auto-updater.service.ts +++ b/src/main/services/auto-updater.service.ts @@ -1,8 +1,9 @@ -import { autoUpdater, CancellationToken, ProgressInfo } from "electron-updater"; +import { autoUpdater, CancellationToken, ProgressInfo, UpdateInfo } from "electron-updater"; import log from "electron-log"; import { gt } from "semver"; import { Progression } from "main/helpers/fs.helpers"; import { Observable } from "rxjs"; +import { safeGt } from "shared/helpers/semver.helpers"; export class AutoUpdaterService { private static instance: AutoUpdaterService; @@ -31,6 +32,18 @@ export class AutoUpdaterService { }); } + public async getAvailableUpdate(): Promise { + return autoUpdater.checkForUpdates().then(info => { + if (info?.updateInfo && safeGt(info.updateInfo.version, autoUpdater.currentVersion.version)) { + return info.updateInfo; + } + return null; + }).catch((error: Error): UpdateInfo | null => { + log.error("Could not get update", error); + return null; + }); + } + public downloadUpdate(): Observable { return new Observable(observer => { diff --git a/src/main/services/static-configuration.service.ts b/src/main/services/static-configuration.service.ts index 47e99245..4244f5a2 100644 --- a/src/main/services/static-configuration.service.ts +++ b/src/main/services/static-configuration.service.ts @@ -5,6 +5,7 @@ import { PROTON_BINARY_PREFIX, WINE_BINARY_PREFIX } from "main/constants"; import { Observable, Subject } from "rxjs"; import { CustomError } from "shared/models/exceptions/custom-error.class"; import { BSVersion } from "shared/bs-version.interface"; +import { AutoUpdate } from "shared/models/config"; export class StaticConfigurationService { private static instance: StaticConfigurationService; @@ -30,8 +31,8 @@ export class StaticConfigurationService { return this.store.has(key); } - public get(key: K): StaticConfigKeyValues[K] { - return this.store.get(key) as StaticConfigKeyValues[K]; + public get(key: K, defaultValue?: StaticConfigKeyValues[K]): StaticConfigKeyValues[K] { + return this.store.get(key, defaultValue) as StaticConfigKeyValues[K]; } public take(key: K, cb: (val: StaticConfigKeyValues[K]) => void): void { @@ -90,6 +91,7 @@ export interface StaticConfigKeyValues { "use-symlinks": boolean; "use-system-proxy": boolean; "last-version-launched": BSVersion; + "auto-update": AutoUpdate; // Linux Specific static configs "proton-folder": string; diff --git a/src/renderer/components/title-bar/title-bar.component.tsx b/src/renderer/components/title-bar/title-bar.component.tsx index b17647e6..73ef4401 100644 --- a/src/renderer/components/title-bar/title-bar.component.tsx +++ b/src/renderer/components/title-bar/title-bar.component.tsx @@ -12,36 +12,47 @@ import { useService } from "renderer/hooks/use-service.hook"; import { lastValueFrom } from "rxjs"; import { useWindowControls } from "renderer/hooks/use-window-controls.hook"; import { useTranslationV2 } from "renderer/hooks/use-translation.hook"; +import Tippy from "@tippyjs/react"; +import { StaticConfigurationService } from "renderer/services/static-configuration.service"; +import { AutoUpdate } from "shared/models/config"; +import { UpdateInfo } from "electron-updater"; -function TitleBarTags() { +function useVersion() { const ipcService = useService(IpcService); - const t = useTranslationV2(); - const [previewVersion, setPreviewVersion] = useState(""); - const [outdated, setOutdated] = useState(false); + const [currentVersion, setCurrentVersion] = useState(""); + const [latestVersion, setLatestVersion] = useState(null); useEffect(() => { - const requests: Promise[] = [ - lastValueFrom(ipcService.sendV2("current-version")) - ]; - if (window.electron.platform === "linux") { - requests.push(lastValueFrom(ipcService.sendV2("check-update"))); - } - - Promise.all(requests).then(([ currentVersion, outdated ]) => { - handlePrerelease(currentVersion); - setOutdated(outdated); + Promise.all([ + lastValueFrom(ipcService.sendV2("current-version")), + lastValueFrom(ipcService.sendV2("get-available-update")) + ]).then(([ currentVersion, latestVersion ]) => { + setCurrentVersion(currentVersion); + setLatestVersion(latestVersion); }); }, []); - const handlePrerelease = (version: string) => { + return { currentVersion, latestVersion }; +} + +function TitleBarTags({ version, latestVersion }: Readonly<{ + version: string; + latestVersion: UpdateInfo | null; +}>) { + const t = useTranslationV2(); + + const previewVersion = (() => { if (version.toLowerCase().includes("alpha")) { - return setPreviewVersion("ALPHA"); + return "ALPHA"; } + if (version.toLowerCase().includes("beta")) { - return setPreviewVersion("BETA"); + return "BETA"; } - } + + return ""; + })(); return <> {previewVersion && @@ -49,7 +60,7 @@ function TitleBarTags() { {previewVersion} } - {outdated && + {latestVersion && {t.text("title-bar.outdated")} @@ -57,12 +68,65 @@ function TitleBarTags() { ; } +function AutoUpdateButton({ latestVersion }: Readonly<{ + latestVersion: UpdateInfo | null; +}>) { + const configService = useService(StaticConfigurationService); + const ipcService = useService(IpcService); + const { text: t } = useTranslationV2(); + + const isLinux = window.electron.platform === "linux"; + + const updateAndRestart = async () => { + await configService.set("auto-update", AutoUpdate.ONCE); + await lastValueFrom(ipcService.sendV2("restart-app")); + }; + + + const renderTippyContent = () => { + return ( +
+
{t("title-bar.update-text", { version: latestVersion.version })}
+ {latestVersion?.version ? ( + {t("title-bar.see-changelog")} + ) : null} + {!isLinux && + updateAndRestart()} + /> + } +
+ ) + } + + return latestVersion && ( + + + + ); +} + export default function TitleBar({ template = "index.html" }: { template: AppWindow }) { const audio = useService(AudioPlayerService); const windowControls = useWindowControls(); const volume = useObservable(() => audio.volume$, audio.volume); const color = useThemeColor("first-color"); + const { currentVersion, latestVersion } = useVersion(); const [maximized, setMaximized] = useState(false); @@ -107,7 +171,7 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin
BSManager - +
@@ -117,6 +181,7 @@ export default function TitleBar({ template = "index.html" }: { template: AppWin
audio.toggleMute()} /> +