mirror of
https://github.com/revoltchat/revite.git
synced 2024-11-13 18:59:22 -05:00
feat: handle system alerts and poll rate changes
This commit is contained in:
parent
03e177f865
commit
f185dec461
4 changed files with 87 additions and 20 deletions
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "0.5.3-7",
|
"version": "1.0.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "node scripts/setup_assets.js --check && vite",
|
"dev": "node scripts/setup_assets.js --check && vite",
|
||||||
"pull": "node scripts/setup_assets.js",
|
"pull": "node scripts/setup_assets.js",
|
||||||
|
|
|
@ -31,3 +31,4 @@ export function internalEmit(ns: string, event: string, ...args: unknown[]) {
|
||||||
// - PWA/update
|
// - PWA/update
|
||||||
// - NewMessages/hide
|
// - NewMessages/hide
|
||||||
// - NewMessages/mark
|
// - NewMessages/mark
|
||||||
|
// - System/alert
|
||||||
|
|
|
@ -2,14 +2,11 @@ import { Docked, OverlappingPanels, ShowIf } from "react-overlapping-panels";
|
||||||
import { Switch, Route, useLocation, Link } from "react-router-dom";
|
import { Switch, Route, useLocation, Link } from "react-router-dom";
|
||||||
import styled, { css } from "styled-components/macro";
|
import styled, { css } from "styled-components/macro";
|
||||||
|
|
||||||
import { useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
import ContextMenus from "../lib/ContextMenus";
|
import ContextMenus from "../lib/ContextMenus";
|
||||||
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
|
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
|
||||||
|
|
||||||
import { useApplicationState } from "../mobx/State";
|
|
||||||
import { SIDEBAR_CHANNELS } from "../mobx/stores/Layout";
|
|
||||||
|
|
||||||
import Popovers from "../context/intermediate/Popovers";
|
import Popovers from "../context/intermediate/Popovers";
|
||||||
import Notifications from "../context/revoltjs/Notifications";
|
import Notifications from "../context/revoltjs/Notifications";
|
||||||
import StateMonitor from "../context/revoltjs/StateMonitor";
|
import StateMonitor from "../context/revoltjs/StateMonitor";
|
||||||
|
@ -18,6 +15,7 @@ import { Titlebar } from "../components/native/Titlebar";
|
||||||
import BottomNavigation from "../components/navigation/BottomNavigation";
|
import BottomNavigation from "../components/navigation/BottomNavigation";
|
||||||
import LeftSidebar from "../components/navigation/LeftSidebar";
|
import LeftSidebar from "../components/navigation/LeftSidebar";
|
||||||
import RightSidebar from "../components/navigation/RightSidebar";
|
import RightSidebar from "../components/navigation/RightSidebar";
|
||||||
|
import { useSystemAlert } from "../updateWorker";
|
||||||
import Open from "./Open";
|
import Open from "./Open";
|
||||||
import Channel from "./channels/Channel";
|
import Channel from "./channels/Channel";
|
||||||
import Developer from "./developer/Developer";
|
import Developer from "./developer/Developer";
|
||||||
|
@ -112,22 +110,35 @@ export default function App() {
|
||||||
path.startsWith("/invite") ||
|
path.startsWith("/invite") ||
|
||||||
path.includes("/settings");
|
path.includes("/settings");
|
||||||
|
|
||||||
|
const alert = useSystemAlert();
|
||||||
const [statusBar, setStatusBar] = useState(false);
|
const [statusBar, setStatusBar] = useState(false);
|
||||||
|
useEffect(() => setStatusBar(true), [alert]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{statusBar && (
|
{alert && statusBar && (
|
||||||
<StatusBar>
|
<StatusBar>
|
||||||
<div className="title">Partial outage: CDN</div>
|
<div className="title">{alert.text}</div>
|
||||||
<div className="actions">
|
<div className="actions">
|
||||||
<Link to="/invite/Testers">
|
{alert.actions?.map((action) =>
|
||||||
<a>
|
action.type === "internal" ? (
|
||||||
<div className="button">Updates</div>
|
<Link to={action.href}>
|
||||||
</a>
|
<div className="button">{action.text}</div>
|
||||||
</Link>
|
</Link>
|
||||||
|
) : action.type === "external" ? (
|
||||||
|
<a
|
||||||
|
href={action.href}
|
||||||
|
target="_blank"
|
||||||
|
rel="noreferrer">
|
||||||
|
<div className="button">{action.text}</div>{" "}
|
||||||
|
</a>
|
||||||
|
) : null,
|
||||||
|
)}
|
||||||
|
{alert.dismissable !== false && (
|
||||||
<a onClick={() => setStatusBar(false)}>
|
<a onClick={() => setStatusBar(false)}>
|
||||||
<div className="button">Dismiss</div>
|
<div className="button">Dismiss</div>
|
||||||
</a>
|
</a>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</StatusBar>
|
</StatusBar>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
import isEqual from "lodash.isequal";
|
||||||
import semver from "semver";
|
import semver from "semver";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { registerSW } from "virtual:pwa-register";
|
import { registerSW } from "virtual:pwa-register";
|
||||||
|
|
||||||
import { internalEmit } from "./lib/eventEmitter";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
|
||||||
|
import { internalEmit, internalSubscribe } from "./lib/eventEmitter";
|
||||||
|
|
||||||
import { modalController } from "./context/modals";
|
import { modalController } from "./context/modals";
|
||||||
|
|
||||||
|
@ -33,15 +36,67 @@ export const updateSW = registerSW({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let currentPollRate: number;
|
||||||
|
let scheduledTask: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schedule version checker
|
||||||
|
* @param poll_rate Set poll rate in milliseconds
|
||||||
|
*/
|
||||||
|
function schedule(poll_rate = INTERVAL_HOUR) {
|
||||||
|
if (poll_rate !== currentPollRate) {
|
||||||
|
currentPollRate = poll_rate;
|
||||||
|
clearInterval(scheduledTask);
|
||||||
|
scheduledTask = setInterval(
|
||||||
|
checkVersion,
|
||||||
|
poll_rate,
|
||||||
|
) as unknown as number;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentAlert: SystemAlert | undefined;
|
||||||
|
type SystemAlert = {
|
||||||
|
text: string;
|
||||||
|
dismissable?: boolean;
|
||||||
|
actions?: {
|
||||||
|
text: string;
|
||||||
|
type: "internal" | "external";
|
||||||
|
href: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current system alert
|
||||||
|
*/
|
||||||
|
export function useSystemAlert() {
|
||||||
|
const [alert, setAlert] = useState(currentAlert);
|
||||||
|
useEffect(() => internalSubscribe("System", "alert", setAlert as any), []);
|
||||||
|
return alert;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the client is out of date
|
* Check whether the client is out of date
|
||||||
*/
|
*/
|
||||||
async function checkVersion() {
|
async function checkVersion() {
|
||||||
const { version } = (await fetch("https://api.revolt.chat/release").then(
|
const { version, poll_rate, alert } = (await fetch(
|
||||||
(res) => res.json(),
|
"https://api.revolt.chat/release",
|
||||||
)) as { version: string };
|
).then((res) => res.json())) as {
|
||||||
|
version: string;
|
||||||
|
poll_rate?: number;
|
||||||
|
alert?: SystemAlert;
|
||||||
|
};
|
||||||
|
|
||||||
if (!semver.satisfies(APP_VERSION, version) && APP_VERSION !== version) {
|
// Re-schedule if necessary
|
||||||
|
schedule(poll_rate);
|
||||||
|
|
||||||
|
// Apply any active alerts
|
||||||
|
if (!isEqual(alert, currentAlert)) {
|
||||||
|
currentAlert = alert;
|
||||||
|
internalEmit("System", "alert", alert);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need to update
|
||||||
|
if (version !== "0.5.3-7" && !semver.satisfies(APP_VERSION, version)) {
|
||||||
// Let the worker know we should immediately refresh
|
// Let the worker know we should immediately refresh
|
||||||
forceUpdate = true;
|
forceUpdate = true;
|
||||||
|
|
||||||
|
@ -59,6 +114,6 @@ async function checkVersion() {
|
||||||
|
|
||||||
if (import.meta.env.VITE_API_URL === "https://api.revolt.chat") {
|
if (import.meta.env.VITE_API_URL === "https://api.revolt.chat") {
|
||||||
// Check for critical updates hourly
|
// Check for critical updates hourly
|
||||||
|
schedule();
|
||||||
checkVersion();
|
checkVersion();
|
||||||
setInterval(checkVersion, INTERVAL_HOUR);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue