mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-25 08:30:58 -05:00
feat: add auto-update and out-of-date indicator
This commit is contained in:
parent
7680931f5f
commit
a404ff7fe0
10 changed files with 145 additions and 28 deletions
|
@ -53,7 +53,7 @@ You can now access the client at http://local.revolt.chat:3000.
|
|||
## CLI Commands
|
||||
|
||||
| Command | Description |
|
||||
| ------------------- | -------------------------------------------- |
|
||||
| --------------------------------------- | -------------------------------------------- |
|
||||
| `yarn pull` | Setup assets required for Revite. |
|
||||
| `yarn dev` | Start the Revolt client in development mode. |
|
||||
| `yarn build` | Build the Revolt client. |
|
||||
|
@ -63,6 +63,7 @@ You can now access the client at http://local.revolt.chat:3000.
|
|||
| `yarn typecheck` | Run TypeScript type checking on the client. |
|
||||
| `yarn start` | Start a local sirv server with built client. |
|
||||
| `yarn start:inject` | Inject a given API URL and start server. |
|
||||
| `yarn lint \| egrep "no-literals" -B 1` | Scan for untranslated strings. |
|
||||
|
||||
## License
|
||||
|
||||
|
|
2
external/lang
vendored
2
external/lang
vendored
|
@ -1 +1 @@
|
|||
Subproject commit a38d0dc72a39ea2b5a6f54c1c999f2021b899e50
|
||||
Subproject commit 309648592801a3bb5c1fa1702753f8dadde56cae
|
|
@ -38,7 +38,8 @@
|
|||
{
|
||||
"varsIgnorePattern": "^_"
|
||||
}
|
||||
]
|
||||
],
|
||||
"react/jsx-no-literals": "warn"
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -92,6 +93,7 @@
|
|||
"@types/react-helmet": "^6.1.1",
|
||||
"@types/react-router-dom": "^5.1.7",
|
||||
"@types/react-scroll": "^1.8.2",
|
||||
"@types/semver": "^7",
|
||||
"@types/styled-components": "^5.1.10",
|
||||
"@types/twemoji": "^12.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.27.0",
|
||||
|
@ -132,6 +134,7 @@
|
|||
"revolt.js": "6.0.3",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "^1.35.1",
|
||||
"semver": "^7.3.7",
|
||||
"shade-blend-color": "^1.0.0",
|
||||
"stacktrace-js": "^2.0.2",
|
||||
"styled-components": "^5.3.0",
|
||||
|
|
|
@ -9,7 +9,7 @@ import { internalSubscribe } from "../../lib/eventEmitter";
|
|||
|
||||
import { useApplicationState } from "../../mobx/State";
|
||||
|
||||
import { updateSW } from "../../main";
|
||||
import { updateSW } from "../../updateWorker";
|
||||
import Tooltip from "./Tooltip";
|
||||
|
||||
let pendingUpdate = false;
|
||||
|
|
47
src/context/modals/components/OutOfDate.tsx
Normal file
47
src/context/modals/components/OutOfDate.tsx
Normal file
|
@ -0,0 +1,47 @@
|
|||
import { Text } from "preact-i18n";
|
||||
|
||||
import { Modal } from "@revoltchat/ui";
|
||||
|
||||
import { noop, noopTrue } from "../../../lib/js";
|
||||
|
||||
import { APP_VERSION } from "../../../version";
|
||||
import { ModalProps } from "../types";
|
||||
|
||||
export default function OutOfDate({
|
||||
onClose,
|
||||
version,
|
||||
}: ModalProps<"out_of_date">) {
|
||||
return (
|
||||
<Modal
|
||||
title={<Text id="app.special.modals.out_of_date.title" />}
|
||||
description={
|
||||
<>
|
||||
<Text id="app.special.modals.out_of_date.description" />
|
||||
<br />
|
||||
<Text
|
||||
id="app.special.modals.out_of_date.version"
|
||||
fields={{ client: APP_VERSION, server: version }}
|
||||
/>
|
||||
</>
|
||||
}
|
||||
actions={[
|
||||
{
|
||||
palette: "plain",
|
||||
onClick: noop,
|
||||
children: (
|
||||
<Text id="app.special.modals.out_of_date.attempting" />
|
||||
),
|
||||
},
|
||||
{
|
||||
palette: "plain-secondary",
|
||||
onClick: noopTrue,
|
||||
children: (
|
||||
<Text id="app.special.modals.out_of_date.ignore" />
|
||||
),
|
||||
},
|
||||
]}
|
||||
onClose={onClose}
|
||||
nonDismissable
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -11,6 +11,7 @@ import { ulid } from "ulid";
|
|||
import MFAEnableTOTP from "./components/MFAEnableTOTP";
|
||||
import MFAFlow from "./components/MFAFlow";
|
||||
import MFARecovery from "./components/MFARecovery";
|
||||
import OutOfDate from "./components/OutOfDate";
|
||||
import Test from "./components/Test";
|
||||
import { Modal } from "./types";
|
||||
|
||||
|
@ -120,5 +121,6 @@ export const modalController = new ModalControllerExtended({
|
|||
mfa_flow: MFAFlow,
|
||||
mfa_recovery: MFARecovery,
|
||||
mfa_enable_totp: MFAEnableTOTP,
|
||||
out_of_date: OutOfDate,
|
||||
test: Test,
|
||||
});
|
||||
|
|
|
@ -24,6 +24,10 @@ export type Modal = {
|
|||
secret: string;
|
||||
callback: (code?: string) => void;
|
||||
}
|
||||
| {
|
||||
type: "out_of_date";
|
||||
version: string;
|
||||
}
|
||||
| {
|
||||
type: "test";
|
||||
}
|
||||
|
|
15
src/main.tsx
15
src/main.tsx
|
@ -1,21 +1,8 @@
|
|||
import { registerSW } from "virtual:pwa-register";
|
||||
|
||||
import "./styles/index.scss";
|
||||
import { render } from "preact";
|
||||
|
||||
import { internalEmit } from "./lib/eventEmitter";
|
||||
|
||||
import { App } from "./pages/app";
|
||||
|
||||
export const updateSW = registerSW({
|
||||
onNeedRefresh() {
|
||||
internalEmit("PWA", "update");
|
||||
},
|
||||
onOfflineReady() {
|
||||
console.info("Ready to work offline.");
|
||||
// show a ready to work offline to user
|
||||
},
|
||||
});
|
||||
import "./updateWorker";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
render(<App />, document.getElementById("app")!);
|
||||
|
|
64
src/updateWorker.ts
Normal file
64
src/updateWorker.ts
Normal file
|
@ -0,0 +1,64 @@
|
|||
import semver from "semver";
|
||||
import { ulid } from "ulid";
|
||||
import { registerSW } from "virtual:pwa-register";
|
||||
|
||||
import { internalEmit } from "./lib/eventEmitter";
|
||||
|
||||
import { modalController } from "./context/modals";
|
||||
|
||||
import { APP_VERSION } from "./version";
|
||||
|
||||
const INTERVAL_HOUR = 36e5;
|
||||
|
||||
let forceUpdate = false;
|
||||
let registration: ServiceWorkerRegistration | undefined;
|
||||
|
||||
export const updateSW = registerSW({
|
||||
onNeedRefresh() {
|
||||
if (forceUpdate) {
|
||||
updateSW(true);
|
||||
} else {
|
||||
internalEmit("PWA", "update");
|
||||
}
|
||||
},
|
||||
onOfflineReady() {
|
||||
console.info("Ready to work offline.");
|
||||
// show a ready to work offline to user
|
||||
},
|
||||
onRegistered(r) {
|
||||
registration = r;
|
||||
|
||||
// Check for updates every hour
|
||||
setInterval(() => r!.update(), INTERVAL_HOUR);
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Check whether the client is out of date
|
||||
*/
|
||||
async function checkVersion() {
|
||||
const { version } = (await fetch("https://api.revolt.chat/release").then(
|
||||
(res) => res.json(),
|
||||
)) as { version: string };
|
||||
|
||||
if (!semver.satisfies(APP_VERSION, version)) {
|
||||
// Let the worker know we should immediately refresh
|
||||
forceUpdate = true;
|
||||
|
||||
// Prompt service worker to update
|
||||
registration?.update();
|
||||
|
||||
// Push information that the client is out of date
|
||||
modalController.push({
|
||||
key: ulid(),
|
||||
type: "out_of_date",
|
||||
version,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.env.VITE_API_URL === "https://api.revolt.chat") {
|
||||
// Check for critical updates hourly
|
||||
checkVersion();
|
||||
setInterval(checkVersion, INTERVAL_HOUR);
|
||||
}
|
|
@ -2730,6 +2730,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/semver@npm:^7":
|
||||
version: 7.3.9
|
||||
resolution: "@types/semver@npm:7.3.9"
|
||||
checksum: 60bfcfdfa7f937be2c6f4b37ddb6714fb0f27b05fe4cbdfdd596a97d35ed95d13ee410efdd88e72a66449d0384220bf20055ab7d6b5df10de4990fbd20e5cbe0
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@types/styled-components@npm:^5.1.10":
|
||||
version: 5.1.13
|
||||
resolution: "@types/styled-components@npm:5.1.13"
|
||||
|
@ -3551,6 +3558,7 @@ __metadata:
|
|||
"@types/react-helmet": ^6.1.1
|
||||
"@types/react-router-dom": ^5.1.7
|
||||
"@types/react-scroll": ^1.8.2
|
||||
"@types/semver": ^7
|
||||
"@types/styled-components": ^5.1.10
|
||||
"@types/twemoji": ^12.1.1
|
||||
"@typescript-eslint/eslint-plugin": ^4.27.0
|
||||
|
@ -3593,6 +3601,7 @@ __metadata:
|
|||
revolt.js: 6.0.3
|
||||
rimraf: ^3.0.2
|
||||
sass: ^1.35.1
|
||||
semver: ^7.3.7
|
||||
shade-blend-color: ^1.0.0
|
||||
sirv-cli: ^1.0.14
|
||||
stacktrace-js: ^2.0.2
|
||||
|
|
Loading…
Reference in a new issue