129 lines
4.9 KiB
TypeScript
129 lines
4.9 KiB
TypeScript
|
import gitHash from "git-hash";
|
||
|
import { changes, checkForUpdates, getRepo, rebuild, update, UpdateLogger } from "../utils/updater";
|
||
|
import { React, Forms, Button, Margins, Alerts, Card, Parser } from '../webpack/common';
|
||
|
import { Flex } from "./Flex";
|
||
|
import { useAwaiter } from '../utils/misc';
|
||
|
import { Link } from "./Link";
|
||
|
|
||
|
interface Props {
|
||
|
setIsOutdated(b: boolean): void;
|
||
|
}
|
||
|
|
||
|
function withDispatcher(dispatcher: React.Dispatch<React.SetStateAction<boolean>>, action: () => any) {
|
||
|
return async () => {
|
||
|
dispatcher(true);
|
||
|
try {
|
||
|
await action();
|
||
|
} catch (e: any) {
|
||
|
UpdateLogger.error("Failed to update", e);
|
||
|
if (!e) {
|
||
|
var err = "An unknown error occurred (error is undefined).\nPlease try again.";
|
||
|
} else if (e.code && e.cmd) {
|
||
|
const { code, path, cmd, stderr } = e;
|
||
|
|
||
|
if (code === "ENOENT")
|
||
|
var err = `Command \`${path}\` not found.\nPlease install it and try again`;
|
||
|
else {
|
||
|
var err = `An error occured while running \`${cmd}\`:\n`;
|
||
|
err += stderr || `Code \`${code}\`. See the console for more info`;
|
||
|
}
|
||
|
|
||
|
} else {
|
||
|
var err = "An unknown error occurred. See the console for more info.";
|
||
|
}
|
||
|
Alerts.show({
|
||
|
title: "Oops!",
|
||
|
body: err.split("\n").map(line => <div>{Parser.parse(line)}</div>)
|
||
|
});
|
||
|
}
|
||
|
finally {
|
||
|
dispatcher(false);
|
||
|
}
|
||
|
};
|
||
|
};
|
||
|
|
||
|
export function Updater(p: Props) {
|
||
|
const [repo, err, repoPending] = useAwaiter(getRepo, "Loading...");
|
||
|
const [isChecking, setIsChecking] = React.useState(false);
|
||
|
const [isUpdating, setIsUpdating] = React.useState(false);
|
||
|
const [updates, setUpdates] = React.useState(changes);
|
||
|
|
||
|
React.useEffect(() => {
|
||
|
if (err)
|
||
|
UpdateLogger.error("Failed to retrieve repo", err);
|
||
|
}, [err]);
|
||
|
|
||
|
return (
|
||
|
<>
|
||
|
<Forms.FormText>Repo: {repoPending ? repo : err ? "Failed to retrieve - check console" : (
|
||
|
<Link href={repo}>
|
||
|
{repo.split("/").slice(-2).join("/")}
|
||
|
</Link>
|
||
|
)} ({gitHash})</Forms.FormText>
|
||
|
|
||
|
<Forms.FormText className={Margins.marginBottom8}>
|
||
|
There are {updates.length} Updates
|
||
|
</Forms.FormText>
|
||
|
|
||
|
<Card style={{ padding: ".5em" }}>
|
||
|
{updates.map(({ hash, author, message }) => (
|
||
|
<div>
|
||
|
<Link href={`${repo}/commit/${hash}`} disabled={repoPending}>
|
||
|
<code>{hash}</code>
|
||
|
</Link>
|
||
|
<span style={{
|
||
|
marginLeft: "0.5em",
|
||
|
color: "var(--text-normal)"
|
||
|
}}>{message} - {author}</span>
|
||
|
</div>
|
||
|
))}
|
||
|
</Card>
|
||
|
|
||
|
<Flex className={`${Margins.marginBottom8} ${Margins.marginTop8}`}>
|
||
|
<Button
|
||
|
size={Button.Sizes.SMALL}
|
||
|
disabled={isUpdating || isChecking}
|
||
|
onClick={withDispatcher(setIsUpdating, async () => {
|
||
|
if (await update()) {
|
||
|
p.setIsOutdated(false);
|
||
|
const needFullRestart = await rebuild();
|
||
|
await new Promise<void>(r => {
|
||
|
Alerts.show({
|
||
|
title: "Update Success!",
|
||
|
body: "Successfully updated. Restart now to apply the changes?",
|
||
|
confirmText: "Restart",
|
||
|
cancelText: "Not now!",
|
||
|
onConfirm() {
|
||
|
if (needFullRestart)
|
||
|
window.DiscordNative.app.relaunch();
|
||
|
else
|
||
|
location.reload();
|
||
|
r();
|
||
|
},
|
||
|
onCancel: r
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
})}
|
||
|
>
|
||
|
Update
|
||
|
</Button>
|
||
|
<Button
|
||
|
size={Button.Sizes.SMALL}
|
||
|
disabled={isUpdating || isChecking}
|
||
|
onClick={withDispatcher(setIsChecking, async () => {
|
||
|
const res = await checkForUpdates();
|
||
|
if (res) {
|
||
|
setUpdates(changes);
|
||
|
} else {
|
||
|
p.setIsOutdated(false);
|
||
|
}
|
||
|
})}
|
||
|
>
|
||
|
Refresh
|
||
|
</Button>
|
||
|
</Flex>
|
||
|
</>
|
||
|
);
|
||
|
}
|