Make the linter happy.

This commit is contained in:
Paul
2021-08-05 14:47:00 +01:00
parent 1be8bdfa9b
commit 872b710bc4
106 changed files with 1083 additions and 5554 deletions

View File

@@ -5,7 +5,7 @@ import update from "dayjs/plugin/updateLocale";
import defaultsDeep from "lodash.defaultsdeep";
import { IntlProvider } from "preact-i18n";
import { useEffect, useState } from "preact/hooks";
import { useCallback, useEffect, useState } from "preact/hooks";
import { connectState } from "../redux/connector";
@@ -165,12 +165,14 @@ export interface Dictionary {
}
function Locale({ children, locale }: Props) {
const [defns, setDefinition] = useState<Dictionary>(definition as any);
const [defns, setDefinition] = useState<Dictionary>(
definition as Dictionary,
);
// Load relevant language information, fallback to English if invalid.
const lang = Languages[locale] ?? Languages.en;
function transformLanguage(source: { [key: string]: any }) {
function transformLanguage(source: Dictionary) {
// Fallback untranslated strings to English (UK)
const obj = defaultsDeep(source, definition);
@@ -216,43 +218,46 @@ function Locale({ children, locale }: Props) {
return obj;
}
function loadLanguage(locale: string) {
if (locale === "en") {
// If English, make sure to restore everything to defaults.
// Use what we already have.
const defn = transformLanguage(definition);
setDefinition(defn);
dayjs.locale("en");
dayjs.updateLocale("en", { calendar: defn.dayjs });
return;
}
import(`../../external/lang/${lang.i18n}.json`).then(
async (lang_file) => {
// Transform the definitions data.
const defn = transformLanguage(lang_file.default);
// Determine and load dayjs locales.
const target = lang.dayjs ?? lang.i18n;
const dayjs_locale = await import(
`../../node_modules/dayjs/esm/locale/${target}.js`
);
// Load dayjs locales.
dayjs.locale(target, dayjs_locale.default);
if (defn.dayjs) {
// Override dayjs calendar locales with our own.
dayjs.updateLocale(target, { calendar: defn.dayjs });
}
// Apply definition to app.
const loadLanguage = useCallback(
(locale: string) => {
if (locale === "en") {
// If English, make sure to restore everything to defaults.
// Use what we already have.
const defn = transformLanguage(definition as Dictionary);
setDefinition(defn);
},
);
}
dayjs.locale("en");
dayjs.updateLocale("en", { calendar: defn.dayjs });
return;
}
useEffect(() => loadLanguage(locale), [locale, lang]);
import(`../../external/lang/${lang.i18n}.json`).then(
async (lang_file) => {
// Transform the definitions data.
const defn = transformLanguage(lang_file.default);
// Determine and load dayjs locales.
const target = lang.dayjs ?? lang.i18n;
const dayjs_locale = await import(
`../../node_modules/dayjs/esm/locale/${target}.js`
);
// Load dayjs locales.
dayjs.locale(target, dayjs_locale.default);
if (defn.dayjs) {
// Override dayjs calendar locales with our own.
dayjs.updateLocale(target, { calendar: defn.dayjs });
}
// Apply definition to app.
setDefinition(defn);
},
);
},
[lang.dayjs, lang.i18n],
);
useEffect(() => loadLanguage(locale), [locale, lang, loadLanguage]);
useEffect(() => {
// Apply RTL language format.

View File

@@ -4,8 +4,6 @@ import { createGlobalStyle } from "styled-components";
import { createContext } from "preact";
import { useEffect } from "preact/hooks";
import { isTouchscreenDevice } from "../lib/isTouchscreenDevice";
import { connectState } from "../redux/connector";
import { Children } from "../types/Preact";
@@ -311,17 +309,17 @@ function Theme({ children, options }: Props) {
const font = theme.font ?? DEFAULT_FONT;
root.setProperty("--font", `"${font}"`);
FONTS[font].load();
}, [theme.font]);
}, [root, theme.font]);
useEffect(() => {
const font = theme.monospaceFont ?? DEFAULT_MONO_FONT;
root.setProperty("--monospace-font", `"${font}"`);
MONOSPACE_FONTS[font].load();
}, [theme.monospaceFont]);
}, [root, theme.monospaceFont]);
useEffect(() => {
root.setProperty("--ligatures", options?.ligatures ? "normal" : "none");
}, [options?.ligatures]);
}, [root, options?.ligatures]);
useEffect(() => {
const resize = () =>
@@ -330,7 +328,7 @@ function Theme({ children, options }: Props) {
window.addEventListener("resize", resize);
return () => window.removeEventListener("resize", resize);
}, []);
}, [root]);
return (
<ThemeContext.Provider value={theme}>

View File

@@ -1,14 +1,20 @@
import { Channel } from "revolt.js/dist/maps/Channels";
import { createContext } from "preact";
import { useContext, useEffect, useMemo, useRef, useState } from "preact/hooks";
import {
useCallback,
useContext,
useEffect,
useMemo,
useRef,
useState,
} from "preact/hooks";
import type { ProduceType, VoiceUser } from "../lib/vortex/Types";
import type VoiceClient from "../lib/vortex/VoiceClient";
import { Children } from "../types/Preact";
import { SoundContext } from "./Settings";
import { AppContext } from "./revoltjs/RevoltClient";
export enum VoiceStatus {
LOADING = 0,
@@ -45,20 +51,22 @@ type Props = {
};
export default function Voice({ children }: Props) {
const revoltClient = useContext(AppContext);
const [client, setClient] = useState<VoiceClient | undefined>(undefined);
const [state, setState] = useState<VoiceState>({
status: VoiceStatus.LOADING,
participants: new Map(),
});
function setStatus(status: VoiceStatus, roomId?: string) {
setState({
status,
roomId: roomId ?? client?.roomId,
participants: client?.participants ?? new Map(),
});
}
const setStatus = useCallback(
(status: VoiceStatus, roomId?: string) => {
setState({
status,
roomId: roomId ?? client?.roomId,
participants: client?.participants ?? new Map(),
});
},
[client?.participants, client?.roomId],
);
useEffect(() => {
import("../lib/vortex/VoiceClient")
@@ -76,7 +84,7 @@ export default function Voice({ children }: Props) {
console.error("Failed to load voice library!", err);
setStatus(VoiceStatus.UNAVAILABLE);
});
}, []);
}, [setStatus]);
const isConnecting = useRef(false);
const operations: VoiceOperations = useMemo(() => {
@@ -158,7 +166,7 @@ export default function Voice({ children }: Props) {
return client?.stopProduce(type);
},
};
}, [client]);
}, [client, setStatus]);
const playSound = useContext(SoundContext);
@@ -200,7 +208,7 @@ export default function Voice({ children }: Props) {
client.removeListener("userStopProduce", stateUpdate);
client.removeListener("close", stateUpdate);
};
}, [client, state]);
}, [client, state, playSound, setStatus]);
return (
<VoiceContext.Provider value={state}>

View File

@@ -89,13 +89,16 @@ export type Screen =
};
export const IntermediateContext = createContext({
screen: { id: "none" } as Screen,
screen: { id: "none" },
focusTaken: false,
});
export const IntermediateActionsContext = createContext({
openScreen: (screen: Screen) => {},
writeClipboard: (text: string) => {},
export const IntermediateActionsContext = createContext<{
openScreen: (screen: Screen) => void;
writeClipboard: (text: string) => void;
}>({
openScreen: null!,
writeClipboard: null!,
});
interface Props {
@@ -130,12 +133,20 @@ export default function Intermediate(props: Props) {
const navigate = (path: string) => history.push(path);
const subs = [
internalSubscribe("Intermediate", "openProfile", openProfile),
internalSubscribe("Intermediate", "navigate", navigate),
internalSubscribe(
"Intermediate",
"openProfile",
openProfile as (...args: unknown[]) => void,
),
internalSubscribe(
"Intermediate",
"navigate",
navigate as (...args: unknown[]) => void,
),
];
return () => subs.map((unsub) => unsub());
}, []);
}, [history]);
return (
<IntermediateContext.Provider value={value}>

View File

@@ -12,7 +12,7 @@ import { SignedOutModal } from "./modals/SignedOut";
export interface Props {
screen: Screen;
openScreen: (id: any) => void;
openScreen: (screen: Screen) => void;
}
export default function Modals({ screen, openScreen }: Props) {

View File

@@ -29,7 +29,7 @@ export function OnboardingModal({ onClose, callback }: Props) {
setLoading(true);
callback(username, true)
.then(() => onClose())
.catch((err: any) => {
.catch((err: unknown) => {
setError(takeError(err));
setLoading(false);
});

View File

@@ -238,7 +238,7 @@ export const SpecialPromptModal = observer((props: SpecialProps) => {
.then((code) => setCode(code))
.catch((err) => setError(takeError(err)))
.finally(() => setProcessing(false));
}, []);
}, [props.target]);
return (
<PromptModal

View File

@@ -1,3 +1,4 @@
/* eslint-disable react-hooks/rules-of-hooks */
import { Attachment, AttachmentMetadata } from "revolt-api/types/Autumn";
import { EmbedImage } from "revolt-api/types/January";

View File

@@ -85,11 +85,13 @@ export function ModifyAccountModal({ onClose, field }: Props) {
]}>
{/* Preact / React typing incompatabilities */}
<form
onSubmit={
onSubmit={(e) => {
e.preventDefault();
handleSubmit(
onSubmit,
) as JSX.GenericEventHandler<HTMLFormElement>
}>
// eslint-disable-next-line @typescript-eslint/no-explicit-any
)(e as any);
}}>
{field === "email" && (
<FormField
type="email"

View File

@@ -42,6 +42,7 @@ export function UserPicker(props: Props) {
)
.map((x) => (
<UserCheckbox
key={x._id}
user={x}
checked={selected.includes(x._id)}
onChange={(v) => {

View File

@@ -20,7 +20,6 @@ import Preloader from "../../../components/ui/Preloader";
import Markdown from "../../../components/markdown/Markdown";
import {
AppContext,
ClientStatus,
StatusContext,
useClient,
@@ -30,7 +29,7 @@ import { useIntermediate } from "../Intermediate";
interface Props {
user_id: string;
dummy?: boolean;
onClose: () => void;
onClose?: () => void;
dummyProfile?: Profile;
}
@@ -60,7 +59,7 @@ export const UserProfile = observer(
const user = client.users.get(user_id);
if (!user) {
useEffect(onClose, []);
if (onClose) useEffect(onClose, []);
return null;
}
@@ -76,7 +75,7 @@ export const UserProfile = observer(
if (!user_id) return;
if (typeof profile !== "undefined") setProfile(undefined);
if (typeof mutual !== "undefined") setMutual(undefined);
}, [user_id]);
}, [user_id, mutual, profile]);
if (dummy) {
useLayoutEffect(() => {
@@ -93,7 +92,7 @@ export const UserProfile = observer(
setMutual(null);
user.fetchMutual().then(setMutual);
}
}, [mutual, status]);
}, [mutual, status, dummy, user]);
useEffect(() => {
if (dummy) return;
@@ -104,12 +103,10 @@ export const UserProfile = observer(
setProfile(null);
if (user.permission & UserPermission.ViewProfile) {
user.fetchProfile()
.then(setProfile)
.catch(() => {});
user.fetchProfile().then(setProfile);
}
}
}, [profile, status]);
}, [profile, status, dummy, user]);
const backgroundURL =
profile &&
@@ -157,7 +154,7 @@ export const UserProfile = observer(
}>
<IconButton
onClick={() => {
onClose();
onClose?.();
history.push(`/open/${user_id}`);
}}>
<Envelope size={30} />
@@ -168,7 +165,7 @@ export const UserProfile = observer(
{user.relationship === RelationshipStatus.User && (
<IconButton
onClick={() => {
onClose();
onClose?.();
if (dummy) return;
history.push(`/settings/profile`);
}}>

View File

@@ -1,4 +1,4 @@
import { Plus, X, XCircle } from "@styled-icons/boxicons-regular";
import { Plus } from "@styled-icons/boxicons-regular";
import { Pencil } from "@styled-icons/boxicons-solid";
import Axios, { AxiosRequestConfig } from "axios";
@@ -147,6 +147,7 @@ export function FileUploader(props: Props) {
}
if (props.behaviour === "multi" && props.append) {
// eslint-disable-next-line
useEffect(() => {
// File pasting.
function paste(e: ClipboardEvent) {
@@ -210,7 +211,7 @@ export function FileUploader(props: Props) {
document.removeEventListener("dragover", dragover);
document.removeEventListener("drop", drop);
};
}, [props.append]);
}, [openScreen, props, props.append]);
}
if (props.style === "icon" || props.style === "banner") {

View File

@@ -1,4 +1,3 @@
import { autorun, reaction } from "mobx";
import { Route, Switch, useHistory, useParams } from "react-router-dom";
import { Presence, RelationshipStatus } from "revolt-api/types/Users";
import { SYSTEM_USER_ID } from "revolt.js";
@@ -6,7 +5,7 @@ import { Message } from "revolt.js/dist/maps/Messages";
import { User } from "revolt.js/dist/maps/Users";
import { decodeTime } from "ulid";
import { useContext, useEffect } from "preact/hooks";
import { useCallback, useContext, useEffect } from "preact/hooks";
import { useTranslation } from "../../lib/i18n";
@@ -52,191 +51,206 @@ function Notifier({ options, notifs }: Props) {
const history = useHistory();
const playSound = useContext(SoundContext);
async function message(msg: Message) {
if (msg.author_id === client.user!._id) return;
if (msg.channel_id === channel_id && document.hasFocus()) return;
if (client.user!.status?.presence === Presence.Busy) return;
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
const message = useCallback(
async (msg: Message) => {
if (msg.author_id === client.user!._id) return;
if (msg.channel_id === channel_id && document.hasFocus()) return;
if (client.user!.status?.presence === Presence.Busy) return;
if (msg.author?.relationship === RelationshipStatus.Blocked) return;
const notifState = getNotificationState(notifs, msg.channel!);
if (!shouldNotify(notifState, msg, client.user!._id)) return;
const notifState = getNotificationState(notifs, msg.channel!);
if (!shouldNotify(notifState, msg, client.user!._id)) return;
playSound("message");
if (!showNotification) return;
playSound("message");
if (!showNotification) return;
let title;
switch (msg.channel?.channel_type) {
case "SavedMessages":
return;
case "DirectMessage":
title = `@${msg.author?.username}`;
break;
case "Group":
if (msg.author?._id === SYSTEM_USER_ID) {
title = msg.channel.name;
} else {
title = `@${msg.author?.username} - ${msg.channel.name}`;
let title;
switch (msg.channel?.channel_type) {
case "SavedMessages":
return;
case "DirectMessage":
title = `@${msg.author?.username}`;
break;
case "Group":
if (msg.author?._id === SYSTEM_USER_ID) {
title = msg.channel.name;
} else {
title = `@${msg.author?.username} - ${msg.channel.name}`;
}
break;
case "TextChannel":
title = `@${msg.author?.username} (#${msg.channel.name}, ${msg.channel.server?.name})`;
break;
default:
title = msg.channel?._id;
break;
}
let image;
if (msg.attachments) {
const imageAttachment = msg.attachments.find(
(x) => x.metadata.type === "Image",
);
if (imageAttachment) {
image = client.generateFileURL(imageAttachment, {
max_side: 720,
});
}
break;
case "TextChannel":
title = `@${msg.author?.username} (#${msg.channel.name}, ${msg.channel.server?.name})`;
break;
default:
title = msg.channel?._id;
break;
}
let image;
if (msg.attachments) {
const imageAttachment = msg.attachments.find(
(x) => x.metadata.type === "Image",
);
if (imageAttachment) {
image = client.generateFileURL(imageAttachment, {
max_side: 720,
});
}
}
let body, icon;
if (typeof msg.content === "string") {
body = client.markdownToText(msg.content);
icon = msg.author?.generateAvatarURL({ max_side: 256 });
} else {
const users = client.users;
switch (msg.content.type) {
case "user_added":
case "user_remove":
{
let user = users.get(msg.content.id);
body = translate(
`app.main.channel.system.${
msg.content.type === "user_added"
? "added_by"
: "removed_by"
}`,
{
user: user?.username,
other_user: users.get(msg.content.by)?.username,
},
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
case "user_joined":
case "user_left":
case "user_kicked":
case "user_banned":
{
let user = users.get(msg.content.id);
body = translate(
`app.main.channel.system.${msg.content.type}`,
{ user: user?.username },
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
case "channel_renamed":
{
let user = users.get(msg.content.by);
body = translate(
`app.main.channel.system.channel_renamed`,
{
user: users.get(msg.content.by)?.username,
name: msg.content.name,
},
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
case "channel_description_changed":
case "channel_icon_changed":
{
let user = users.get(msg.content.by);
body = translate(
`app.main.channel.system.${msg.content.type}`,
{ user: users.get(msg.content.by)?.username },
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
}
}
const notif = await createNotification(title!, {
icon,
image,
body,
timestamp: decodeTime(msg._id),
tag: msg.channel?._id,
badge: "/assets/icons/android-chrome-512x512.png",
silent: true,
});
if (notif) {
notif.addEventListener("click", () => {
window.focus();
const id = msg.channel_id;
if (id !== channel_id) {
const channel = client.channels.get(id);
if (channel) {
if (channel.channel_type === "TextChannel") {
history.push(
`/server/${channel.server_id}/channel/${id}`,
let body, icon;
if (typeof msg.content === "string") {
body = client.markdownToText(msg.content);
icon = msg.author?.generateAvatarURL({ max_side: 256 });
} else {
const users = client.users;
switch (msg.content.type) {
case "user_added":
case "user_remove":
{
const user = users.get(msg.content.id);
body = translate(
`app.main.channel.system.${
msg.content.type === "user_added"
? "added_by"
: "removed_by"
}`,
{
user: user?.username,
other_user: users.get(msg.content.by)
?.username,
},
);
} else {
history.push(`/channel/${id}`);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
}
break;
case "user_joined":
case "user_left":
case "user_kicked":
case "user_banned":
{
const user = users.get(msg.content.id);
body = translate(
`app.main.channel.system.${msg.content.type}`,
{ user: user?.username },
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
case "channel_renamed":
{
const user = users.get(msg.content.by);
body = translate(
`app.main.channel.system.channel_renamed`,
{
user: users.get(msg.content.by)?.username,
name: msg.content.name,
},
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
case "channel_description_changed":
case "channel_icon_changed":
{
const user = users.get(msg.content.by);
body = translate(
`app.main.channel.system.${msg.content.type}`,
{ user: users.get(msg.content.by)?.username },
);
icon = user?.generateAvatarURL({
max_side: 256,
});
}
break;
}
}
const notif = await createNotification(title!, {
icon,
image,
body,
timestamp: decodeTime(msg._id),
tag: msg.channel?._id,
badge: "/assets/icons/android-chrome-512x512.png",
silent: true,
});
notifications[msg.channel_id] = notif;
notif.addEventListener(
"close",
() => delete notifications[msg.channel_id],
);
}
}
async function relationship(user: User) {
if (client.user?.status?.presence === Presence.Busy) return;
if (!showNotification) return;
let event;
switch (user.relationship) {
case RelationshipStatus.Incoming:
event = translate("notifications.sent_request", {
person: user.username,
if (notif) {
notif.addEventListener("click", () => {
window.focus();
const id = msg.channel_id;
if (id !== channel_id) {
const channel = client.channels.get(id);
if (channel) {
if (channel.channel_type === "TextChannel") {
history.push(
`/server/${channel.server_id}/channel/${id}`,
);
} else {
history.push(`/channel/${id}`);
}
}
}
});
break;
case RelationshipStatus.Friend:
event = translate("notifications.now_friends", {
person: user.username,
});
break;
default:
return;
}
const notif = await createNotification(event, {
icon: user.generateAvatarURL({ max_side: 256 }),
badge: "/assets/icons/android-chrome-512x512.png",
timestamp: +new Date(),
});
notifications[msg.channel_id] = notif;
notif.addEventListener(
"close",
() => delete notifications[msg.channel_id],
);
}
},
[
history,
showNotification,
translate,
channel_id,
client,
notifs,
playSound,
],
);
notif?.addEventListener("click", () => {
history.push(`/friends`);
});
}
const relationship = useCallback(
async (user: User) => {
if (client.user?.status?.presence === Presence.Busy) return;
if (!showNotification) return;
let event;
switch (user.relationship) {
case RelationshipStatus.Incoming:
event = translate("notifications.sent_request", {
person: user.username,
});
break;
case RelationshipStatus.Friend:
event = translate("notifications.now_friends", {
person: user.username,
});
break;
default:
return;
}
const notif = await createNotification(event, {
icon: user.generateAvatarURL({ max_side: 256 }),
badge: "/assets/icons/android-chrome-512x512.png",
timestamp: +new Date(),
});
notif?.addEventListener("click", () => {
history.push(`/friends`);
});
},
[client.user?.status?.presence, history, showNotification, translate],
);
useEffect(() => {
client.addListener("message", message);
@@ -246,7 +260,16 @@ function Notifier({ options, notifs }: Props) {
client.removeListener("message", message);
client.removeListener("user/relationship", relationship);
};
}, [client, playSound, guild_id, channel_id, showNotification, notifs]);
}, [
client,
playSound,
guild_id,
channel_id,
showNotification,
notifs,
message,
relationship,
]);
useEffect(() => {
function visChange() {

View File

@@ -1,5 +1,4 @@
import { openDB } from "idb";
import { useHistory } from "react-router-dom";
/* eslint-disable react-hooks/rules-of-hooks */
import { Client } from "revolt.js";
import { Route } from "revolt.js/dist/api/routes";
@@ -58,29 +57,6 @@ function Context({ auth, children }: Props) {
useEffect(() => {
(async () => {
let db;
try {
// Match sw.ts#L23
db = await openDB("state", 3, {
upgrade(db) {
for (const store of [
"channels",
"servers",
"users",
"members",
]) {
db.createObjectStore(store, {
keyPath: "_id",
});
}
},
});
} catch (err) {
console.error(
"Failed to open IndexedDB store, continuing without.",
);
}
const client = new Client({
autoReconnect: false,
apiURL: import.meta.env.VITE_API_URL,
@@ -146,11 +122,11 @@ function Context({ auth, children }: Props) {
ready: () =>
operations.loggedIn() && typeof client.user !== "undefined",
};
}, [client, auth.active]);
}, [client, auth.active, openScreen]);
useEffect(
() => registerEvents({ operations }, setStatus, client),
[client],
[client, operations],
);
useEffect(() => {
@@ -203,6 +179,7 @@ function Context({ auth, children }: Props) {
setStatus(ClientStatus.READY);
}
})();
// eslint-disable-next-line
}, []);
if (status === ClientStatus.LOADING) {

View File

@@ -37,7 +37,7 @@ function StateMonitor(props: Props) {
client.addListener("message", add);
return () => client.removeListener("message", add);
}, [props.messages]);
}, [client, props.messages]);
return null;
}

View File

@@ -5,7 +5,7 @@ import isEqual from "lodash.isequal";
import { UserSettings } from "revolt-api/types/Sync";
import { ClientboundNotification } from "revolt.js/dist/websocket/notifications";
import { useContext, useEffect } from "preact/hooks";
import { useCallback, useContext, useEffect, useMemo } from "preact/hooks";
import { dispatch } from "../../redux";
import { connectState } from "../../redux/connector";
@@ -28,7 +28,7 @@ type Props = {
notifications: Notifications;
};
const lastValues: { [key in SyncKeys]?: any } = {};
const lastValues: { [key in SyncKeys]?: unknown } = {};
export function mapSync(
packet: UserSettings,
@@ -78,31 +78,38 @@ function SyncManager(props: Props) {
.syncFetchUnreads()
.then((unreads) => dispatch({ type: "UNREADS_SET", unreads }));
}
}, [status]);
}, [client, props.sync?.disabled, status]);
function syncChange(key: SyncKeys, data: any) {
const timestamp = +new Date();
dispatch({
type: "SYNC_SET_REVISION",
key,
timestamp,
});
const syncChange = useCallback(
(key: SyncKeys, data: unknown) => {
const timestamp = +new Date();
dispatch({
type: "SYNC_SET_REVISION",
key,
timestamp,
});
client.syncSetSettings(
{
[key]: data,
},
timestamp,
);
}
client.syncSetSettings(
{
[key]: data as string,
},
timestamp,
);
},
[client],
);
const disabled = props.sync.disabled ?? [];
const disabled = useMemo(
() => props.sync.disabled ?? [],
[props.sync.disabled],
);
for (const [key, object] of [
["appearance", props.settings.appearance],
["theme", props.settings.theme],
["locale", props.locale],
["notifications", props.notifications],
] as [SyncKeys, any][]) {
] as [SyncKeys, unknown][]) {
// eslint-disable-next-line react-hooks/rules-of-hooks
useEffect(() => {
if (disabled.indexOf(key) === -1) {
if (typeof lastValues[key] !== "undefined") {
@@ -113,7 +120,7 @@ function SyncManager(props: Props) {
}
lastValues[key] = object;
}, [disabled, object]);
}, [key, syncChange, disabled, object]);
}
useEffect(() => {
@@ -131,7 +138,7 @@ function SyncManager(props: Props) {
client.addListener("packet", onPacket);
return () => client.removeListener("packet", onPacket);
}, [disabled, props.sync]);
}, [client, disabled, props.sync]);
return null;
}

View File

@@ -8,7 +8,7 @@ import { dispatch } from "../../redux";
import { ClientOperations, ClientStatus } from "./RevoltClient";
export var preventReconnect = false;
export let preventReconnect = false;
let preventUntil = 0;
export function setReconnectDisallowed(allowed: boolean) {
@@ -34,6 +34,7 @@ export function registerEvents(
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
let listeners: Record<string, (...args: any[]) => void> = {
connecting: () =>
operations.ready() && setStatus(ClientStatus.CONNECTING),
@@ -74,7 +75,7 @@ export function registerEvents(
if (import.meta.env.DEV) {
listeners = new Proxy(listeners, {
get:
(target, listener, receiver) =>
(target, listener) =>
(...args: unknown[]) => {
console.debug(`Calling ${listener.toString()} with`, args);
Reflect.get(target, listener)(...args);
@@ -87,10 +88,6 @@ export function registerEvents(
client.addListener(listener, listeners[listener]);
}
function logMutation(target: string, key: string) {
console.log("(o) Object mutated", target, "\nChanged:", key);
}
const online = () => {
if (operations.ready()) {
setStatus(ClientStatus.RECONNECTING);

View File

@@ -1,10 +1,10 @@
import { Client } from "revolt.js";
import { Channel } from "revolt.js/dist/maps/Channels";
import { Text } from "preact-i18n";
import { Children } from "../../types/Preact";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function takeError(error: any): string {
const type = error?.response?.data?.type;
const id = type;