diff --git a/emain/preload.ts b/emain/preload.ts index e92972923..96881a369 100644 --- a/emain/preload.ts +++ b/emain/preload.ts @@ -27,6 +27,7 @@ contextBridge.exposeInMainWorld("api", { ipcRenderer.on("fullscreen-change", (_event, isFullScreen) => callback(isFullScreen)), onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)), getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"), + getUpdaterChannel: () => ipcRenderer.sendSync("get-updater-channel"), installAppUpdate: () => ipcRenderer.send("install-app-update"), onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback), updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect), diff --git a/emain/updater.ts b/emain/updater.ts index f9784d933..83ebc2336 100644 --- a/emain/updater.ts +++ b/emain/updater.ts @@ -29,7 +29,7 @@ export class Updater { autoUpdater.autoInstallOnAppQuit = settings["autoupdate:installonquit"]; - // Only update the release channel if it's specified, otherwise use the one configured in the artifact. + // Only update the release channel if it's specified, otherwise use the one configured in the updater. const channel = settings["autoupdate:channel"]; if (channel) { autoUpdater.channel = channel; @@ -180,6 +180,9 @@ ipcMain.on("install-app-update", () => fireAndForget(() => updater?.promptToInst ipcMain.on("get-app-update-status", (event) => { event.returnValue = updater?.status; }); +ipcMain.on("get-updater-channel", (event) => { + event.returnValue = isDev() ? "dev" : (autoUpdater.channel ?? "latest"); +}); let autoUpdateLock = false; diff --git a/frontend/app/modals/about.tsx b/frontend/app/modals/about.tsx index 589df36b0..df697935f 100644 --- a/frontend/app/modals/about.tsx +++ b/frontend/app/modals/about.tsx @@ -16,6 +16,7 @@ interface AboutModalProps {} const AboutModal = ({}: AboutModalProps) => { const currentDate = new Date(); const [details] = useState(() => getApi().getAboutModalDetails()); + const [updaterChannel] = useState(() => getApi().getUpdaterChannel()); return ( modalsModel.popModal()}> @@ -32,6 +33,8 @@ const AboutModal = ({}: AboutModalProps) => {
Client Version {details.version} ({isDev() ? "dev-" : ""} {details.buildTime}) +
+ Update Channel: {updaterChannel}
{ const isFullScreen = useAtomValue(atoms.isFullScreen); - const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom); - let prevDelta: number; let prevDragDirection: string; @@ -477,24 +475,6 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
) : undefined; - function onUpdateAvailableClick() { - getApi().installAppUpdate(); - } - - let updateAvailableLabel: React.ReactNode = null; - if (appUpdateStatus === "ready") { - updateAvailableLabel = ( - - ); - } - return (
@@ -527,7 +507,7 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
- {updateAvailableLabel} + ); }); diff --git a/frontend/app/tab/updatestatus.less b/frontend/app/tab/updatestatus.less new file mode 100644 index 000000000..8b99c3265 --- /dev/null +++ b/frontend/app/tab/updatestatus.less @@ -0,0 +1,11 @@ +.update-available-button { + height: 80%; + margin: auto 4px; + color: black; + background-color: var(--accent-color); + flex: 0 0 fit-content; + + &:disabled { + opacity: unset !important; + } +} diff --git a/frontend/app/tab/updatestatus.tsx b/frontend/app/tab/updatestatus.tsx new file mode 100644 index 000000000..7ca33a958 --- /dev/null +++ b/frontend/app/tab/updatestatus.tsx @@ -0,0 +1,49 @@ +import { Button } from "@/element/button"; +import { atoms, getApi } from "@/store/global"; +import { useAtomValue } from "jotai"; +import { memo } from "react"; +import "./updatestatus.less"; + +const UpdateStatusBannerComponent = ({ buttonRef }: { buttonRef: React.RefObject }) => { + const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom); + function onClick() { + if (appUpdateStatus === "ready") getApi().installAppUpdate(); + } + + let buttonText: string; + switch (appUpdateStatus) { + case "ready": + buttonText = "Update Available"; + break; + case "checking": + buttonText = "Checking for Updates"; + break; + case "downloading": + buttonText = "Downloading Update"; + break; + case "installing": + buttonText = "Installing Update"; + break; + case "error": + buttonText = "Updater Error: Try Checking Again"; + break; + default: + break; + } + + if (buttonText) { + return ( + + ); + } +}; + +export const UpdateStatusBanner = memo(UpdateStatusBannerComponent) as typeof UpdateStatusBannerComponent; diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index e751e55ac..be830c0d6 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -67,6 +67,7 @@ declare global { onFullScreenChange: (callback: (isFullScreen: boolean) => void) => void; onUpdaterStatusChange: (callback: (status: UpdaterStatus) => void) => void; getUpdaterStatus: () => UpdaterStatus; + getUpdaterChannel: () => string; installAppUpdate: () => void; onMenuItemAbout: (callback: () => void) => void; updateWindowControlsOverlay: (rect: Dimensions) => void;