Show updater status banner for all statuses (#396)

Also adds updater channel to about modal
This commit is contained in:
Evan Simkowitz 2024-09-18 14:25:52 -07:00 committed by GitHub
parent 3ade98879b
commit e5e6259dec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 71 additions and 32 deletions

View File

@ -27,6 +27,7 @@ contextBridge.exposeInMainWorld("api", {
ipcRenderer.on("fullscreen-change", (_event, isFullScreen) => callback(isFullScreen)), ipcRenderer.on("fullscreen-change", (_event, isFullScreen) => callback(isFullScreen)),
onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)), onUpdaterStatusChange: (callback) => ipcRenderer.on("app-update-status", (_event, status) => callback(status)),
getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"), getUpdaterStatus: () => ipcRenderer.sendSync("get-app-update-status"),
getUpdaterChannel: () => ipcRenderer.sendSync("get-updater-channel"),
installAppUpdate: () => ipcRenderer.send("install-app-update"), installAppUpdate: () => ipcRenderer.send("install-app-update"),
onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback), onMenuItemAbout: (callback) => ipcRenderer.on("menu-item-about", callback),
updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect), updateWindowControlsOverlay: (rect) => ipcRenderer.send("update-window-controls-overlay", rect),

View File

@ -29,7 +29,7 @@ export class Updater {
autoUpdater.autoInstallOnAppQuit = settings["autoupdate:installonquit"]; 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"]; const channel = settings["autoupdate:channel"];
if (channel) { if (channel) {
autoUpdater.channel = channel; autoUpdater.channel = channel;
@ -180,6 +180,9 @@ ipcMain.on("install-app-update", () => fireAndForget(() => updater?.promptToInst
ipcMain.on("get-app-update-status", (event) => { ipcMain.on("get-app-update-status", (event) => {
event.returnValue = updater?.status; event.returnValue = updater?.status;
}); });
ipcMain.on("get-updater-channel", (event) => {
event.returnValue = isDev() ? "dev" : (autoUpdater.channel ?? "latest");
});
let autoUpdateLock = false; let autoUpdateLock = false;

View File

@ -16,6 +16,7 @@ interface AboutModalProps {}
const AboutModal = ({}: AboutModalProps) => { const AboutModal = ({}: AboutModalProps) => {
const currentDate = new Date(); const currentDate = new Date();
const [details] = useState(() => getApi().getAboutModalDetails()); const [details] = useState(() => getApi().getAboutModalDetails());
const [updaterChannel] = useState(() => getApi().getUpdaterChannel());
return ( return (
<Modal className="about-modal" onClose={() => modalsModel.popModal()}> <Modal className="about-modal" onClose={() => modalsModel.popModal()}>
@ -32,6 +33,8 @@ const AboutModal = ({}: AboutModalProps) => {
<div className="section text-standard"> <div className="section text-standard">
Client Version {details.version} ({isDev() ? "dev-" : ""} Client Version {details.version} ({isDev() ? "dev-" : ""}
{details.buildTime}) {details.buildTime})
<br />
Update Channel: {updaterChannel}
</div> </div>
<div className="section"> <div className="section">
<LinkButton <LinkButton

View File

@ -97,13 +97,4 @@
--os-handle-interactive-area-offset: 0px; --os-handle-interactive-area-offset: 0px;
--os-handle-border-radius: 2px; --os-handle-border-radius: 2px;
} }
.update-available-button {
height: 80%;
opacity: 0.7;
margin: auto 4px;
color: black;
background-color: var(--accent-color);
flex: 0 0 fit-content;
}
} }

View File

@ -9,9 +9,9 @@ import { useAtomValue } from "jotai";
import { OverlayScrollbars } from "overlayscrollbars"; import { OverlayScrollbars } from "overlayscrollbars";
import React, { createRef, useCallback, useEffect, useRef, useState } from "react"; import React, { createRef, useCallback, useEffect, useRef, useState } from "react";
import { debounce } from "throttle-debounce"; import { debounce } from "throttle-debounce";
import { Button } from "../element/button";
import { Tab } from "./tab"; import { Tab } from "./tab";
import "./tabbar.less"; import "./tabbar.less";
import { UpdateStatusBanner } from "./updatestatus";
const TAB_DEFAULT_WIDTH = 130; const TAB_DEFAULT_WIDTH = 130;
const TAB_MIN_WIDTH = 100; const TAB_MIN_WIDTH = 100;
@ -74,8 +74,6 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
const isFullScreen = useAtomValue(atoms.isFullScreen); const isFullScreen = useAtomValue(atoms.isFullScreen);
const appUpdateStatus = useAtomValue(atoms.updaterStatusAtom);
let prevDelta: number; let prevDelta: number;
let prevDragDirection: string; let prevDragDirection: string;
@ -477,24 +475,6 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
</div> </div>
) : undefined; ) : undefined;
function onUpdateAvailableClick() {
getApi().installAppUpdate();
}
let updateAvailableLabel: React.ReactNode = null;
if (appUpdateStatus === "ready") {
updateAvailableLabel = (
<Button
ref={updateStatusButtonRef}
className="update-available-button"
title="Click to Install Update"
onClick={onUpdateAvailableClick}
>
Update Available
</Button>
);
}
return ( return (
<div ref={tabbarWrapperRef} className="tab-bar-wrapper"> <div ref={tabbarWrapperRef} className="tab-bar-wrapper">
<WindowDrag ref={draggerLeftRef} className="left" /> <WindowDrag ref={draggerLeftRef} className="left" />
@ -527,7 +507,7 @@ const TabBar = React.memo(({ workspace }: TabBarProps) => {
<i className="fa fa-solid fa-plus fa-fw" /> <i className="fa fa-solid fa-plus fa-fw" />
</div> </div>
<WindowDrag ref={draggerRightRef} className="right" /> <WindowDrag ref={draggerRightRef} className="right" />
{updateAvailableLabel} <UpdateStatusBanner buttonRef={updateStatusButtonRef} />
</div> </div>
); );
}); });

View File

@ -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;
}
}

View File

@ -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<HTMLButtonElement> }) => {
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 (
<Button
ref={buttonRef}
className="update-available-button"
title={appUpdateStatus === "ready" ? "Click to Install Update" : buttonText}
onClick={onClick}
disabled={appUpdateStatus !== "ready"}
>
{buttonText}
</Button>
);
}
};
export const UpdateStatusBanner = memo(UpdateStatusBannerComponent) as typeof UpdateStatusBannerComponent;

View File

@ -67,6 +67,7 @@ declare global {
onFullScreenChange: (callback: (isFullScreen: boolean) => void) => void; onFullScreenChange: (callback: (isFullScreen: boolean) => void) => void;
onUpdaterStatusChange: (callback: (status: UpdaterStatus) => void) => void; onUpdaterStatusChange: (callback: (status: UpdaterStatus) => void) => void;
getUpdaterStatus: () => UpdaterStatus; getUpdaterStatus: () => UpdaterStatus;
getUpdaterChannel: () => string;
installAppUpdate: () => void; installAppUpdate: () => void;
onMenuItemAbout: (callback: () => void) => void; onMenuItemAbout: (callback: () => void) => void;
updateWindowControlsOverlay: (rect: Dimensions) => void; updateWindowControlsOverlay: (rect: Dimensions) => void;