feat: fully migrate to pnpm workspace
parent
663d3c22d1
commit
6239160d09
|
|
@ -7,3 +7,6 @@
|
|||
[submodule "external/revolt.js"]
|
||||
path = external/revolt.js
|
||||
url = https://github.com/revoltchat/revolt.js
|
||||
[submodule "packages/hast-util-table-cell-style"]
|
||||
path = packages/hast-util-table-cell-style
|
||||
url = https://github.com/revoltchat/hast-util-table-cell-style
|
||||
|
|
|
|||
9
.npmrc
9
.npmrc
|
|
@ -1 +1,8 @@
|
|||
auto-install-peers=true
|
||||
# Allow us to use the monorepo with client being the root
|
||||
ignore-workspace-root-check=true
|
||||
|
||||
# We cannot satisfy certain peer dependencies
|
||||
strict-peer-dependencies=false
|
||||
|
||||
# Required for Vite.js to resolve packages
|
||||
shamefully-hoist=true
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -4,10 +4,11 @@ WORKDIR /usr/src/app
|
|||
COPY . .
|
||||
COPY .env.build .env
|
||||
|
||||
RUN yarn install --frozen-lockfile
|
||||
RUN yarn typecheck
|
||||
RUN yarn build:highmem
|
||||
RUN yarn workspaces focus --production --all
|
||||
RUN pnpm install --frozen-lockfile
|
||||
RUN pnpm typecheck
|
||||
RUN pnpm build:highmem
|
||||
# wipe node_modules for all packages
|
||||
RUN pnpm install --prod
|
||||
|
||||
FROM node:16-alpine
|
||||
WORKDIR /usr/src/app
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ Get revite up and running locally.
|
|||
```
|
||||
git clone --recursive https://github.com/revoltchat/revite
|
||||
cd revite
|
||||
yarn
|
||||
yarn build:deps
|
||||
yarn dev
|
||||
pnpm i
|
||||
pnpm build:deps
|
||||
pnpm dev
|
||||
```
|
||||
|
||||
You can now access the client at http://local.revolt.chat:3000.
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit e79862b5972b57c016b4c08676ac1b90bd52ee83
|
||||
Subproject commit d314b2d191124f1b487ebd72409e748c1bfccb87
|
||||
166
package.json
166
package.json
|
|
@ -4,9 +4,9 @@
|
|||
"preinstall": "npx only-allow pnpm",
|
||||
"dev": "node scripts/setup_assets.js --check && vite",
|
||||
"pull": "node scripts/setup_assets.js",
|
||||
"build:deps": "cd external && cd components && yarn && yarn build:esm && cd .. && cd revolt.js && yarn && yarn build",
|
||||
"build": "yarn && rimraf build && node scripts/setup_assets.js --check && yarn build:deps && vite build",
|
||||
"build:highmem": "NODE_OPTIONS='--max-old-space-size=4096' yarn build",
|
||||
"build:deps": "pnpm run -r build",
|
||||
"build": "rimraf build && node scripts/setup_assets.js --check && vite build",
|
||||
"build:highmem": "NODE_OPTIONS='--max-old-space-size=4096' npm run build",
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint src/**/*.{js,jsx,ts,tsx}",
|
||||
"fmt": "prettier --write 'src/**/*.{js,jsx,ts,tsx}'",
|
||||
|
|
@ -45,123 +45,127 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.0.0",
|
||||
"fs-extra": "^10.1.0",
|
||||
"klaw": "^3.0.0",
|
||||
"sirv-cli": "^1.0.14",
|
||||
"vite": "^3.0.5"
|
||||
"vite": "^3.1.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-proposal-decorators": "^7.17.9",
|
||||
"@babel/plugin-proposal-decorators": "^7.19.1",
|
||||
"@babel/runtime": "^7.19.0",
|
||||
"@floating-ui/react-dom": "^1.0.0",
|
||||
"@floating-ui/react-dom-interactions": "^0.9.1",
|
||||
"@fontsource/atkinson-hyperlegible": "^4.4.5",
|
||||
"@fontsource/bitter": "^4.5.7",
|
||||
"@fontsource/comic-neue": "^4.4.5",
|
||||
"@fontsource/fira-code": "^4.4.5",
|
||||
"@fontsource/inter": "^4.4.5",
|
||||
"@fontsource/jetbrains-mono": "^4.4.5",
|
||||
"@fontsource/lato": "^4.4.5",
|
||||
"@fontsource/lexend": "^4.5.2",
|
||||
"@fontsource/montserrat": "^4.4.5",
|
||||
"@fontsource/noto-sans": "^4.4.5",
|
||||
"@fontsource/open-sans": "^4.5.2",
|
||||
"@fontsource/opendyslexic": "^4.5.2",
|
||||
"@fontsource/poppins": "^4.4.5",
|
||||
"@fontsource/raleway": "^4.4.5",
|
||||
"@fontsource/roboto": "^4.4.5",
|
||||
"@fontsource/roboto-mono": "^4.4.5",
|
||||
"@fontsource/source-code-pro": "^4.4.5",
|
||||
"@fontsource/space-mono": "^4.4.5",
|
||||
"@fontsource/ubuntu": "^4.4.5",
|
||||
"@fontsource/ubuntu-mono": "^4.4.5",
|
||||
"@hcaptcha/react-hcaptcha": "^0.3.6",
|
||||
"@floating-ui/react-dom-interactions": "^0.9.3",
|
||||
"@fontsource/atkinson-hyperlegible": "^4.5.9",
|
||||
"@fontsource/bitter": "^4.5.8",
|
||||
"@fontsource/comic-neue": "^4.5.9",
|
||||
"@fontsource/fira-code": "^4.5.11",
|
||||
"@fontsource/inter": "^4.5.12",
|
||||
"@fontsource/jetbrains-mono": "^4.5.10",
|
||||
"@fontsource/lato": "^4.5.9",
|
||||
"@fontsource/lexend": "^4.5.12",
|
||||
"@fontsource/montserrat": "^4.5.12",
|
||||
"@fontsource/noto-sans": "^4.5.11",
|
||||
"@fontsource/open-sans": "^4.5.11",
|
||||
"@fontsource/opendyslexic": "^4.5.4",
|
||||
"@fontsource/poppins": "^4.5.9",
|
||||
"@fontsource/raleway": "^4.5.10",
|
||||
"@fontsource/roboto": "^4.5.8",
|
||||
"@fontsource/roboto-mono": "^4.5.8",
|
||||
"@fontsource/source-code-pro": "^4.5.12",
|
||||
"@fontsource/space-mono": "^4.5.10",
|
||||
"@fontsource/ubuntu": "^4.5.11",
|
||||
"@fontsource/ubuntu-mono": "^4.5.11",
|
||||
"@hcaptcha/react-hcaptcha": "^0.3.10",
|
||||
"@insertish/vite-plugin-babel-macros": "^1.0.5",
|
||||
"@preact/preset-vite": "^2.0.0",
|
||||
"@revoltchat/ui": "workspace:*",
|
||||
"@mapbox/hast-util-table-cell-style": "workspace:0.2.0",
|
||||
"@preact/preset-vite": "^2.4.0",
|
||||
"@revoltchat/ui": "workspace:1.0.77",
|
||||
"@rollup/plugin-replace": "^2.4.2",
|
||||
"@styled-icons/boxicons-logos": "^10.38.0",
|
||||
"@styled-icons/boxicons-regular": "^10.38.0",
|
||||
"@styled-icons/boxicons-solid": "^10.38.0",
|
||||
"@styled-icons/simple-icons": "^10.33.0",
|
||||
"@styled-icons/boxicons-logos": "^10.46.0",
|
||||
"@styled-icons/boxicons-regular": "^10.46.0",
|
||||
"@styled-icons/boxicons-solid": "^10.46.0",
|
||||
"@styled-icons/simple-icons": "^10.46.0",
|
||||
"@tippyjs/react": "4.2.6",
|
||||
"@traptitech/markdown-it-katex": "^3.4.3",
|
||||
"@traptitech/markdown-it-katex": "^3.6.0",
|
||||
"@traptitech/markdown-it-spoiler": "^1.1.6",
|
||||
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
|
||||
"@types/lodash": "^4",
|
||||
"@types/lodash.defaultsdeep": "^4.6.6",
|
||||
"@types/lodash.isequal": "^4.5.5",
|
||||
"@types/node": "^15.12.4",
|
||||
"@types/preact-i18n": "^2.3.0",
|
||||
"@types/prismjs": "^1.16.5",
|
||||
"@types/react-beautiful-dnd": "^13",
|
||||
"@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",
|
||||
"@typescript-eslint/parser": "^4.27.0",
|
||||
"@vitejs/plugin-legacy": "^1.7.1",
|
||||
"classnames": "^2.3.1",
|
||||
"@trivago/prettier-plugin-sort-imports": "^2.0.4",
|
||||
"@types/lodash": "^4.14.185",
|
||||
"@types/lodash.defaultsdeep": "^4.6.7",
|
||||
"@types/lodash.isequal": "^4.5.6",
|
||||
"@types/node": "^15.14.9",
|
||||
"@types/preact-i18n": "^2.3.1",
|
||||
"@types/prismjs": "^1.26.0",
|
||||
"@types/react-beautiful-dnd": "^13.0.0",
|
||||
"@types/react-helmet": "^6.1.5",
|
||||
"@types/react-router-dom": "^5.3.3",
|
||||
"@types/react-scroll": "^1.8.4",
|
||||
"@types/semver": "^7.3.12",
|
||||
"@types/styled-components": "^5.1.26",
|
||||
"@types/twemoji": "^12.1.2",
|
||||
"@typescript-eslint/eslint-plugin": "^4.33.0",
|
||||
"@typescript-eslint/parser": "^4.33.0",
|
||||
"@vitejs/plugin-legacy": "^1.8.2",
|
||||
"classnames": "^2.3.2",
|
||||
"color-rgba": "^2.4.0",
|
||||
"dayjs": "^1.10.6",
|
||||
"detect-browser": "^5.2.0",
|
||||
"eslint": "^7.28.0",
|
||||
"eslint-config-preact": "^1.1.4",
|
||||
"eslint-plugin-jsdoc": "^39.3.2",
|
||||
"dayjs": "^1.11.5",
|
||||
"detect-browser": "^5.3.0",
|
||||
"eslint": "^7.32.0",
|
||||
"eslint-config-preact": "^1.3.0",
|
||||
"eslint-plugin-jsdoc": "^39.3.6",
|
||||
"eslint-plugin-mobx": "^0.0.8",
|
||||
"eventemitter3": "^4.0.7",
|
||||
"history": "4",
|
||||
"json-stringify-deterministic": "^1.0.2",
|
||||
"localforage": "^1.9.0",
|
||||
"history": "^4.10.1",
|
||||
"json-stringify-deterministic": "^1.0.7",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash.defaultsdeep": "^4.6.1",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"long": "^5.2.0",
|
||||
"mdast-util-to-hast": "^12.1.2",
|
||||
"mediasoup-client": "npm:@insertish/mediasoup-client@3.6.36-esnext",
|
||||
"mobx": "^6.6.0",
|
||||
"mdast-util-to-hast": "^12.2.2",
|
||||
"mediasoup-client": "npm:@insertish/mediasoup-client@^3.6.36-esnext",
|
||||
"mobx": "^6.6.2",
|
||||
"mobx-react-lite": "3.4.0",
|
||||
"preact": "^10.5.14",
|
||||
"preact": "^10.11.0",
|
||||
"preact-context-menu": "0.4.1",
|
||||
"preact-i18n": "^2.4.0-preactx",
|
||||
"prettier": "^2.3.1",
|
||||
"prismjs": "^1.28.0",
|
||||
"qrcode.react": "^3.0.2",
|
||||
"react-beautiful-dnd": "^13.1.0",
|
||||
"prettier": "^2.7.1",
|
||||
"prismjs": "^1.29.0",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-device-detect": "2.2.2",
|
||||
"react-helmet": "^6.1.0",
|
||||
"react-hook-form": "6.3.0",
|
||||
"react-overlapping-panels": "1.2.2",
|
||||
"react-router-dom": "^5.2.0",
|
||||
"react-scroll": "^1.8.2",
|
||||
"react-virtuoso": "^2.12.0",
|
||||
"react-router-dom": "^5.3.3",
|
||||
"react-scroll": "^1.8.7",
|
||||
"react-virtuoso": "^2.19.0",
|
||||
"rehype-katex": "^6.0.2",
|
||||
"rehype-prism": "^2.1.3",
|
||||
"rehype-react": "^7.1.1",
|
||||
"remark": "^14.0.2",
|
||||
"remark-breaks": "^3.0.2",
|
||||
"remark-gfm": "^3.0.1",
|
||||
"remark-math": "^5.1.1",
|
||||
"remark-parse": "^10.0.1",
|
||||
"remark-rehype": "^10.1.0",
|
||||
"revolt.js": "workspace:*",
|
||||
"revolt.js": "workspace:6.0.18",
|
||||
"rimraf": "^3.0.2",
|
||||
"sass": "^1.35.1",
|
||||
"sass": "^1.54.9",
|
||||
"semver": "^7.3.7",
|
||||
"shade-blend-color": "^1.0.0",
|
||||
"slate": "^0.81.1",
|
||||
"slate": "^0.81.3",
|
||||
"slate-history": "^0.66.0",
|
||||
"slate-react": "^0.81.0",
|
||||
"stacktrace-js": "^2.0.2",
|
||||
"styled-components": "^5.3.0",
|
||||
"typescript": "^4.4.2",
|
||||
"styled-components": "^5.3.5",
|
||||
"typescript": "^4.8.3",
|
||||
"ulid": "^2.3.0",
|
||||
"unified": "^10.1.2",
|
||||
"unist-util-visit": "^4.1.0",
|
||||
"use-resize-observer": "^7.0.0",
|
||||
"vite-plugin-pwa": "^0.12.3",
|
||||
"workbox-precaching": "^6.1.5"
|
||||
"unist-util-visit": "^4.1.1",
|
||||
"use-resize-observer": "^7.0.1",
|
||||
"vite-plugin-pwa": "^0.12.8",
|
||||
"workbox-precaching": "^6.5.4",
|
||||
"workbox-window": "^6.5.4"
|
||||
},
|
||||
"name": "client",
|
||||
"main": "index.js",
|
||||
|
|
|
|||
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 7803fa54410a7ef9fc3149c482253e74ca1d7d71
|
||||
5310
pnpm-lock.yaml
5310
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -1,3 +1,4 @@
|
|||
packages:
|
||||
- 'packages/**'
|
||||
- 'external/**'
|
||||
- '!external/lang'
|
||||
- '!external/lang'
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
import { XCircle, Plus, Share, X, File } from "@styled-icons/boxicons-regular";
|
||||
import styled from "styled-components/macro";
|
||||
|
||||
import { Fragment } from "preact";
|
||||
import { Text } from "preact-i18n";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
|
||||
|
|
@ -192,7 +193,6 @@ export default function FilePreview({ state, addFile, removeFile }: Props) {
|
|||
<Container>
|
||||
<Carousel>
|
||||
{state.files.map((file, index) => (
|
||||
// @ts-expect-error brokey
|
||||
// eslint-disable-next-line react/jsx-no-undef
|
||||
<Fragment key={file.name}>
|
||||
{index === CAN_UPLOAD_AT_ONCE && <Divider />}
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ import remarkRehype from "remark-rehype";
|
|||
import styled, { css } from "styled-components";
|
||||
import { unified } from "unified";
|
||||
|
||||
import { createElement } from "preact";
|
||||
import { memo } from "preact/compat";
|
||||
import { createElement, Fragment } from "preact";
|
||||
import { useLayoutEffect, useMemo, useState } from "preact/hooks";
|
||||
|
||||
import { MarkdownProps } from "./Markdown";
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ class ClientController {
|
|||
injectController("client", this);
|
||||
}
|
||||
|
||||
@action pickNextSession() {
|
||||
pickNextSession() {
|
||||
this.switchAccount(
|
||||
this.current ?? this.sessions.keys().next().value ?? null,
|
||||
);
|
||||
|
|
@ -69,7 +69,7 @@ class ClientController {
|
|||
* Hydrate sessions and start client lifecycles.
|
||||
* @param auth Authentication store
|
||||
*/
|
||||
@action hydrate(auth: Auth) {
|
||||
hydrate(auth: Auth) {
|
||||
for (const entry of auth.getAccounts()) {
|
||||
this.addSession(entry, "existing");
|
||||
}
|
||||
|
|
@ -81,7 +81,7 @@ class ClientController {
|
|||
* Get the currently selected session
|
||||
* @returns Active Session
|
||||
*/
|
||||
@computed getActiveSession() {
|
||||
getActiveSession() {
|
||||
return this.sessions.get(this.current!);
|
||||
}
|
||||
|
||||
|
|
@ -89,7 +89,7 @@ class ClientController {
|
|||
* Get the currently ready client
|
||||
* @returns Ready Client
|
||||
*/
|
||||
@computed getReadyClient() {
|
||||
getReadyClient() {
|
||||
const session = this.getActiveSession();
|
||||
return session && session.ready ? session.client! : undefined;
|
||||
}
|
||||
|
|
@ -98,7 +98,7 @@ class ClientController {
|
|||
* Get an unauthenticated instance of the Revolt.js Client
|
||||
* @returns API Client
|
||||
*/
|
||||
@computed getAnonymousClient() {
|
||||
getAnonymousClient() {
|
||||
return this.apiClient;
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +106,7 @@ class ClientController {
|
|||
* Get the next available client (either from session or API)
|
||||
* @returns Revolt.js Client
|
||||
*/
|
||||
@computed getAvailableClient() {
|
||||
getAvailableClient() {
|
||||
return this.getActiveSession()?.client ?? this.apiClient;
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ class ClientController {
|
|||
* Fetch server configuration
|
||||
* @returns Server Configuration
|
||||
*/
|
||||
@computed getServerConfig() {
|
||||
getServerConfig() {
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
|
|
@ -122,7 +122,7 @@ class ClientController {
|
|||
* Check whether we are logged in right now
|
||||
* @returns Whether we are logged in
|
||||
*/
|
||||
@computed isLoggedIn() {
|
||||
isLoggedIn() {
|
||||
return this.current !== null;
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +130,7 @@ class ClientController {
|
|||
* Check whether we are currently ready
|
||||
* @returns Whether we are ready to render
|
||||
*/
|
||||
@computed isReady() {
|
||||
isReady() {
|
||||
return this.getActiveSession()?.ready;
|
||||
}
|
||||
|
||||
|
|
@ -139,7 +139,7 @@ class ClientController {
|
|||
* @param entry Session Information
|
||||
* @param knowledge Whether the session is new or existing
|
||||
*/
|
||||
@action addSession(
|
||||
addSession(
|
||||
entry: { session: SessionPrivate; apiUrl?: string },
|
||||
knowledge: "new" | "existing",
|
||||
) {
|
||||
|
|
@ -262,7 +262,7 @@ class ClientController {
|
|||
* Log out of a specific user session
|
||||
* @param user_id Target User ID
|
||||
*/
|
||||
@action logout(user_id: string) {
|
||||
logout(user_id: string) {
|
||||
const session = this.sessions.get(user_id);
|
||||
if (session) {
|
||||
if (user_id === this.current) {
|
||||
|
|
@ -278,7 +278,7 @@ class ClientController {
|
|||
/**
|
||||
* Logout of the current session
|
||||
*/
|
||||
@action logoutCurrent() {
|
||||
logoutCurrent() {
|
||||
if (this.current) {
|
||||
this.logout(this.current);
|
||||
}
|
||||
|
|
@ -288,7 +288,7 @@ class ClientController {
|
|||
* Switch to another user session
|
||||
* @param user_id Target User ID
|
||||
*/
|
||||
@action switchAccount(user_id: string) {
|
||||
switchAccount(user_id: string) {
|
||||
this.current = user_id;
|
||||
|
||||
// This will allow account switching to work more seamlessly,
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ export default class Session {
|
|||
/**
|
||||
* Initiate logout and destroy client
|
||||
*/
|
||||
@action destroy() {
|
||||
destroy() {
|
||||
if (this.client) {
|
||||
this.client.logout(false);
|
||||
this.state = "Ready";
|
||||
|
|
@ -165,7 +165,7 @@ export default class Session {
|
|||
* Transition to a new state by a certain action
|
||||
* @param data Transition Data
|
||||
*/
|
||||
@action async emit(data: Transition) {
|
||||
async emit(data: Transition) {
|
||||
console.info(`[FSM ${this.user_id ?? "Anonymous"}]`, data);
|
||||
|
||||
switch (data.action) {
|
||||
|
|
@ -269,7 +269,7 @@ export default class Session {
|
|||
* Whether we are ready to render.
|
||||
* @returns Boolean
|
||||
*/
|
||||
@computed get ready() {
|
||||
get ready() {
|
||||
return !!this.client?.user;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export class ChannelRenderer {
|
|||
this.currentRenderer.delete(this, id);
|
||||
}
|
||||
|
||||
@action async init(message_id?: string) {
|
||||
async init(message_id?: string) {
|
||||
if (message_id) {
|
||||
if (this.state === "RENDER") {
|
||||
const message = this.messages.find((x) => x._id === message_id);
|
||||
|
|
@ -83,15 +83,15 @@ export class ChannelRenderer {
|
|||
this.currentRenderer.init(this, message_id);
|
||||
}
|
||||
|
||||
@action emitScroll(state: ScrollState) {
|
||||
emitScroll(state: ScrollState) {
|
||||
this.scrollState = state;
|
||||
}
|
||||
|
||||
@action markStale() {
|
||||
markStale() {
|
||||
this.stale = true;
|
||||
}
|
||||
|
||||
@action complete() {
|
||||
complete() {
|
||||
this.fetching = false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ class VoiceStateReference {
|
|||
|
||||
// This takes information from the voice
|
||||
// client and applies it to the state here.
|
||||
@action syncState() {
|
||||
syncState() {
|
||||
if (!this.client) return;
|
||||
this.roomId = toNullable(this.client.roomId);
|
||||
this.participants.clear();
|
||||
|
|
@ -54,7 +54,7 @@ class VoiceStateReference {
|
|||
}
|
||||
|
||||
// This imports and constructs the voice client.
|
||||
@action async loadVoice() {
|
||||
async loadVoice() {
|
||||
if (this.status !== VoiceStatus.UNLOADED) return;
|
||||
this.status = VoiceStatus.LOADING;
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ class VoiceStateReference {
|
|||
}
|
||||
|
||||
// Connect to a voice channel.
|
||||
@action async connect(channel: Channel) {
|
||||
async connect(channel: Channel) {
|
||||
if (!this.client?.supported()) throw new Error("RTC is unavailable");
|
||||
|
||||
this.connecting = true;
|
||||
|
|
@ -131,7 +131,7 @@ class VoiceStateReference {
|
|||
}
|
||||
|
||||
// Disconnect from current channel.
|
||||
@action disconnect() {
|
||||
disconnect() {
|
||||
this.connecting = false;
|
||||
this.status = VoiceStatus.READY;
|
||||
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ export default class State {
|
|||
* Consume packets from the client.
|
||||
* @param packet Inbound Packet
|
||||
*/
|
||||
@action onPacket(packet: ClientboundNotification) {
|
||||
onPacket(packet: ClientboundNotification) {
|
||||
if (packet.type === "UserSettingsUpdate") {
|
||||
try {
|
||||
this.sync.apply(packet.update);
|
||||
|
|
|
|||
|
|
@ -46,13 +46,13 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
return "auth";
|
||||
}
|
||||
|
||||
@action toJSON() {
|
||||
toJSON() {
|
||||
return {
|
||||
sessions: JSON.parse(JSON.stringify(mapToRecord(this.sessions))),
|
||||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (Array.isArray(data.sessions)) {
|
||||
data.sessions.forEach(([key, value]) =>
|
||||
this.sessions.set(key, value),
|
||||
|
|
@ -73,7 +73,7 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
* @param session Session
|
||||
* @param apiUrl Custom API URL
|
||||
*/
|
||||
@action setSession(session: Session, apiUrl?: string) {
|
||||
setSession(session: Session, apiUrl?: string) {
|
||||
this.sessions.set(session.user_id, { session, apiUrl });
|
||||
}
|
||||
|
||||
|
|
@ -81,7 +81,7 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
* Remove existing session by user ID.
|
||||
* @param user_id User ID tied to session
|
||||
*/
|
||||
@action removeSession(user_id: string) {
|
||||
removeSession(user_id: string) {
|
||||
this.sessions.delete(user_id);
|
||||
}
|
||||
|
||||
|
|
@ -89,14 +89,14 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
* Get all known accounts.
|
||||
* @returns Array of accounts
|
||||
*/
|
||||
@computed getAccounts() {
|
||||
getAccounts() {
|
||||
return [...this.sessions.values()];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove current session.
|
||||
*/
|
||||
/*@action logout() {
|
||||
/*logout() {
|
||||
this.current && this.removeSession(this.current);
|
||||
}*/
|
||||
|
||||
|
|
@ -104,7 +104,7 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
* Get current session.
|
||||
* @returns Current session
|
||||
*/
|
||||
/*@computed getSession() {
|
||||
/*getSession() {
|
||||
if (!this.current) return;
|
||||
return this.sessions.get(this.current)!.session;
|
||||
}*/
|
||||
|
|
@ -113,7 +113,7 @@ export default class Auth implements Store, Persistent<Data> {
|
|||
* Check whether we are currently logged in.
|
||||
* @returns Whether we are logged in
|
||||
*/
|
||||
@computed isLoggedIn() {
|
||||
isLoggedIn() {
|
||||
// ! FIXME: temp proxy info
|
||||
return clientController.getActiveSession()?.ready;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ export default class Changelog implements Store, Persistent<Data>, Syncable {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.viewed) {
|
||||
this.viewed = data.viewed;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default class Draft implements Store, Persistent<Data> {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
Object.keys(data.drafts).forEach((key) =>
|
||||
this.drafts.set(key, data.drafts[key]),
|
||||
);
|
||||
|
|
@ -43,7 +43,7 @@ export default class Draft implements Store, Persistent<Data> {
|
|||
* Get draft for a channel.
|
||||
* @param channel Channel ID
|
||||
*/
|
||||
@computed get(channel: string) {
|
||||
get(channel: string) {
|
||||
return this.drafts.get(channel);
|
||||
}
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ export default class Draft implements Store, Persistent<Data> {
|
|||
* Check whether a channel has a draft.
|
||||
* @param channel Channel ID
|
||||
*/
|
||||
@computed has(channel: string) {
|
||||
has(channel: string) {
|
||||
return this.drafts.has(channel) && this.drafts.get(channel)!.length > 0;
|
||||
}
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ export default class Draft implements Store, Persistent<Data> {
|
|||
* @param channel Channel ID
|
||||
* @param content Draft content
|
||||
*/
|
||||
@action set(channel: string, content?: string) {
|
||||
set(channel: string, content?: string) {
|
||||
if (typeof content === "undefined") {
|
||||
return this.clear(channel);
|
||||
}
|
||||
|
|
@ -72,14 +72,14 @@ export default class Draft implements Store, Persistent<Data> {
|
|||
* Clear draft from a channel.
|
||||
* @param channel Channel ID
|
||||
*/
|
||||
@action clear(channel: string) {
|
||||
clear(channel: string) {
|
||||
this.drafts.delete(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset and clear all drafts.
|
||||
*/
|
||||
@action reset() {
|
||||
reset() {
|
||||
this.drafts.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.enabled) {
|
||||
for (const experiment of data.enabled) {
|
||||
this.enable(experiment as Experiment);
|
||||
|
|
@ -89,7 +89,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
* Check if an experiment is enabled.
|
||||
* @param experiment Experiment
|
||||
*/
|
||||
@computed isEnabled(experiment: Experiment) {
|
||||
isEnabled(experiment: Experiment) {
|
||||
return this.enabled.has(experiment);
|
||||
}
|
||||
|
||||
|
|
@ -97,7 +97,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
* Enable an experiment.
|
||||
* @param experiment Experiment
|
||||
*/
|
||||
@action enable(experiment: Experiment) {
|
||||
enable(experiment: Experiment) {
|
||||
if (experiment === "offline_users") {
|
||||
setOfflineSkipEnabled(false);
|
||||
resetMemberSidebarFetched();
|
||||
|
|
@ -110,7 +110,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
* Disable an experiment.
|
||||
* @param experiment Experiment
|
||||
*/
|
||||
@action disable(experiment: Experiment) {
|
||||
disable(experiment: Experiment) {
|
||||
if (experiment === "offline_users") setOfflineSkipEnabled(true);
|
||||
|
||||
this.enabled.delete(experiment);
|
||||
|
|
@ -121,7 +121,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
* @param key Experiment
|
||||
* @param enabled Whether this experiment is enabled.
|
||||
*/
|
||||
@computed setEnabled(key: Experiment, enabled: boolean): void {
|
||||
setEnabled(key: Experiment, enabled: boolean): void {
|
||||
if (enabled) {
|
||||
this.enable(key);
|
||||
} else {
|
||||
|
|
@ -132,7 +132,7 @@ export default class Experiments implements Store, Persistent<Data> {
|
|||
/**
|
||||
* Reset and disable all experiments.
|
||||
*/
|
||||
@action reset() {
|
||||
reset() {
|
||||
this.enabled.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.lastSection) {
|
||||
this.lastSection = data.lastSection;
|
||||
}
|
||||
|
|
@ -103,7 +103,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Get the last 'major section' the user had open.
|
||||
* @returns Last open section
|
||||
*/
|
||||
@computed getLastSection() {
|
||||
getLastSection() {
|
||||
return this.lastSection;
|
||||
}
|
||||
|
||||
|
|
@ -111,7 +111,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Get last opened channel in a server.
|
||||
* @param server Server ID
|
||||
*/
|
||||
@computed getLastOpened(server: string) {
|
||||
getLastOpened(server: string) {
|
||||
return this.lastOpened.get(server);
|
||||
}
|
||||
|
||||
|
|
@ -120,7 +120,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* @param server Server ID
|
||||
* @returns Pathname
|
||||
*/
|
||||
@computed getServerPath(server: string) {
|
||||
getServerPath(server: string) {
|
||||
let path = `/server/${server}`;
|
||||
if (this.lastOpened.has(server)) {
|
||||
path += `/channel/${this.getLastOpened(server)}`;
|
||||
|
|
@ -134,7 +134,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* @param server Server ID
|
||||
* @param channel Channel ID
|
||||
*/
|
||||
@action setLastOpened(server: string, channel: string) {
|
||||
setLastOpened(server: string, channel: string) {
|
||||
this.lastOpened.set(server, channel);
|
||||
this.lastSection = server;
|
||||
}
|
||||
|
|
@ -143,7 +143,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Get the last path the user had open in the home tab.
|
||||
* @returns Last home path
|
||||
*/
|
||||
@computed getLastHomePath() {
|
||||
getLastHomePath() {
|
||||
return this.lastHomePath;
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Get the last path the user had open.
|
||||
* @returns Last path
|
||||
*/
|
||||
@computed getLastPath() {
|
||||
getLastPath() {
|
||||
return (
|
||||
(this.lastSection === "discover"
|
||||
? this.lastDiscoverPath
|
||||
|
|
@ -167,7 +167,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Set the last opened section.
|
||||
* @param section Section name
|
||||
*/
|
||||
@action setLastSection(section: string) {
|
||||
setLastSection(section: string) {
|
||||
this.lastSection = section;
|
||||
}
|
||||
|
||||
|
|
@ -175,7 +175,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Set the current path open in the home tab.
|
||||
* @param path Pathname
|
||||
*/
|
||||
@action setLastHomePath(path: string) {
|
||||
setLastHomePath(path: string) {
|
||||
if (path.startsWith("/bot")) return;
|
||||
if (path.startsWith("/invite")) return;
|
||||
|
||||
|
|
@ -187,7 +187,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* Set the last discover path.
|
||||
* @param path Pathname
|
||||
*/
|
||||
@action setLastDiscoverPath(path: string) {
|
||||
setLastDiscoverPath(path: string) {
|
||||
this.lastDiscoverPath = path;
|
||||
this.lastSection = "discover";
|
||||
}
|
||||
|
|
@ -198,7 +198,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* @returns Whether the section is open
|
||||
* @param def Default state value
|
||||
*/
|
||||
@computed getSectionState(id: string, def?: boolean) {
|
||||
getSectionState(id: string, def?: boolean) {
|
||||
return this.openSections.get(id) ?? def ?? false;
|
||||
}
|
||||
|
||||
|
|
@ -208,7 +208,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* @param value New state value
|
||||
* @param def Default state value
|
||||
*/
|
||||
@action setSectionState(id: string, value: boolean, def?: boolean) {
|
||||
setSectionState(id: string, value: boolean, def?: boolean) {
|
||||
if (value === def) {
|
||||
this.openSections.delete(id);
|
||||
} else {
|
||||
|
|
@ -221,7 +221,7 @@ export default class Layout implements Store, Persistent<Data> {
|
|||
* @param id Section ID
|
||||
* @param def Default state value
|
||||
*/
|
||||
@action toggleSectionState(id: string, def?: boolean) {
|
||||
toggleSectionState(id: string, def?: boolean) {
|
||||
this.setSectionState(id, !this.getSectionState(id, def), def);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,27 +79,27 @@ export default class LocaleOptions
|
|||
this.hydrate(data as Data);
|
||||
}
|
||||
|
||||
@computed toSyncable(): { [key: string]: object } {
|
||||
toSyncable(): { [key: string]: object } {
|
||||
return {
|
||||
locale: this.toJSON(),
|
||||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
this.setLanguage(data.lang);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current language.
|
||||
*/
|
||||
@computed getLanguage() {
|
||||
getLanguage() {
|
||||
return this.lang;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current language.
|
||||
*/
|
||||
@action setLanguage(language: Language) {
|
||||
setLanguage(language: Language) {
|
||||
if (typeof Languages[language] === "undefined") return;
|
||||
this.lang = language;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export default class MessageQueue implements Store {
|
|||
* @param channel Channel ID
|
||||
* @param data Message data
|
||||
*/
|
||||
@action add(id: string, channel: string, data: QueuedMessageData) {
|
||||
add(id: string, channel: string, data: QueuedMessageData) {
|
||||
this.messages.push({
|
||||
id,
|
||||
channel,
|
||||
|
|
@ -76,7 +76,7 @@ export default class MessageQueue implements Store {
|
|||
* @param id Nonce value
|
||||
* @param error Error string
|
||||
*/
|
||||
@action fail(id: string, error: string) {
|
||||
fail(id: string, error: string) {
|
||||
const entry = this.messages.find((x) => x.id === id)!;
|
||||
entry.status = QueueStatus.ERRORED;
|
||||
entry.error = error;
|
||||
|
|
@ -86,7 +86,7 @@ export default class MessageQueue implements Store {
|
|||
* Mark a queued message as sending.
|
||||
* @param id Nonce value
|
||||
*/
|
||||
@action start(id: string) {
|
||||
start(id: string) {
|
||||
const entry = this.messages.find((x) => x.id === id)!;
|
||||
entry.status = QueueStatus.SENDING;
|
||||
}
|
||||
|
|
@ -95,7 +95,7 @@ export default class MessageQueue implements Store {
|
|||
* Remove a queued message.
|
||||
* @param id Nonce value
|
||||
*/
|
||||
@action remove(id: string) {
|
||||
remove(id: string) {
|
||||
const entry = this.messages.find((x) => x.id === id)!;
|
||||
this.messages.remove(entry);
|
||||
}
|
||||
|
|
@ -105,7 +105,7 @@ export default class MessageQueue implements Store {
|
|||
* @param channel Channel ID
|
||||
* @returns Array of queued messages
|
||||
*/
|
||||
@computed get(channel: string) {
|
||||
get(channel: string) {
|
||||
return this.messages.filter((x) => x.channel === channel);
|
||||
}
|
||||
|
||||
|
|
@ -113,7 +113,7 @@ export default class MessageQueue implements Store {
|
|||
* Handle an incoming Message
|
||||
* @param message Message
|
||||
*/
|
||||
@action onMessage(message: Message) {
|
||||
onMessage(message: Message) {
|
||||
if (!message.nonce) return;
|
||||
if (!this.get(message.channel_id).find((x) => x.id === message.nonce))
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -104,7 +104,7 @@ export default class NotificationOptions
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.server) {
|
||||
Object.keys(data.server).forEach((key) =>
|
||||
this.server.set(key, data.server![key]),
|
||||
|
|
@ -493,11 +493,11 @@ export default class NotificationOptions
|
|||
}
|
||||
}
|
||||
|
||||
@action apply(_key: "notifications", data: unknown, _revision: number) {
|
||||
apply(_key: "notifications", data: unknown, _revision: number) {
|
||||
this.hydrate(data as Data);
|
||||
}
|
||||
|
||||
@computed toSyncable() {
|
||||
toSyncable() {
|
||||
return {
|
||||
notifications: this.toJSON(),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ export default class Ordering implements Store, Persistent<Data>, Syncable {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.servers) {
|
||||
this.servers = data.servers;
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ export default class Ordering implements Store, Persistent<Data>, Syncable {
|
|||
/**
|
||||
* All known servers with ordering applied
|
||||
*/
|
||||
@computed get orderedServers() {
|
||||
get orderedServers() {
|
||||
const client = clientController.getReadyClient();
|
||||
const known = new Set(client?.servers.keys() ?? []);
|
||||
const ordered = [...this.servers];
|
||||
|
|
@ -85,7 +85,7 @@ export default class Ordering implements Store, Persistent<Data>, Syncable {
|
|||
/**
|
||||
* Re-order a server
|
||||
*/
|
||||
@action reorderServer(source: number, dest: number) {
|
||||
reorderServer(source: number, dest: number) {
|
||||
this.servers = reorder(
|
||||
this.orderedServers.map((x) => x._id),
|
||||
source,
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
Object.keys(data["revite:plugins"]).forEach((key) =>
|
||||
this.plugins.set(key, data["revite:plugins"][key]),
|
||||
);
|
||||
|
|
@ -121,7 +121,7 @@ export default class Plugins implements Store, Persistent<Data> {
|
|||
* @param namespace Namespace
|
||||
* @param id Plugin Id
|
||||
*/
|
||||
@computed get(namespace: string, id: string) {
|
||||
get(namespace: string, id: string) {
|
||||
return this.plugins.get(`${namespace}/${id}`);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default class ServerConfig
|
|||
return JSON.parse(JSON.stringify(this.config));
|
||||
}
|
||||
|
||||
@action hydrate(data: API.RevoltConfig) {
|
||||
hydrate(data: API.RevoltConfig) {
|
||||
this.config = data ?? null;
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ export default class ServerConfig
|
|||
* Get server configuration.
|
||||
* @returns Server configuration
|
||||
*/
|
||||
@computed get() {
|
||||
get() {
|
||||
return this.config;
|
||||
}
|
||||
|
||||
|
|
@ -66,7 +66,7 @@ export default class ServerConfig
|
|||
* Set server configuration.
|
||||
* @param config Server configuration
|
||||
*/
|
||||
@action set(config: API.RevoltConfig) {
|
||||
set(config: API.RevoltConfig) {
|
||||
this.config = config;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ export default class Settings
|
|||
return JSON.parse(JSON.stringify(mapToRecord(this.data)));
|
||||
}
|
||||
|
||||
@action hydrate(data: ISettings) {
|
||||
hydrate(data: ISettings) {
|
||||
Object.keys(data).forEach(
|
||||
(key) =>
|
||||
typeof (data as any)[key] !== "undefined" &&
|
||||
|
|
@ -77,9 +77,9 @@ export default class Settings
|
|||
* @param key Colon-divided key
|
||||
* @param value Value
|
||||
*/
|
||||
@action set<T extends keyof ISettings>(key: T, value: ISettings[T]) {
|
||||
set<T extends keyof ISettings>(key: T, value: ISettings[T]) {
|
||||
// Emoji needs to be immediately applied.
|
||||
if (key === 'appearance:emoji') {
|
||||
if (key === "appearance:emoji") {
|
||||
setGlobalEmojiPack(value as EmojiPack);
|
||||
}
|
||||
|
||||
|
|
@ -92,14 +92,11 @@ export default class Settings
|
|||
* @param defaultValue Default value if not present
|
||||
* @returns Value at key
|
||||
*/
|
||||
@computed get<T extends keyof ISettings>(
|
||||
key: T,
|
||||
defaultValue?: ISettings[T],
|
||||
) {
|
||||
get<T extends keyof ISettings>(key: T, defaultValue?: ISettings[T]) {
|
||||
return (this.data.get(key) as ISettings[T] | undefined) ?? defaultValue;
|
||||
}
|
||||
|
||||
@action remove<T extends keyof ISettings>(key: T) {
|
||||
remove<T extends keyof ISettings>(key: T) {
|
||||
this.data.delete(key);
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +105,7 @@ export default class Settings
|
|||
* @param key Colon-divided key
|
||||
* @param value Value
|
||||
*/
|
||||
@action setUnchecked(key: string, value: unknown) {
|
||||
setUnchecked(key: string, value: unknown) {
|
||||
this.data.set(key, value);
|
||||
}
|
||||
|
||||
|
|
@ -117,15 +114,11 @@ export default class Settings
|
|||
* @param key Colon-divided key
|
||||
* @returns Value at key
|
||||
*/
|
||||
@computed getUnchecked(key: string) {
|
||||
getUnchecked(key: string) {
|
||||
return this.data.get(key);
|
||||
}
|
||||
|
||||
@action apply(
|
||||
key: "appearance" | "theme",
|
||||
data: unknown,
|
||||
_revision: number,
|
||||
) {
|
||||
apply(key: "appearance" | "theme", data: unknown, _revision: number) {
|
||||
if (key === "appearance") {
|
||||
this.remove("appearance:emoji");
|
||||
this.remove("appearance:seasonal");
|
||||
|
|
@ -143,7 +136,7 @@ export default class Settings
|
|||
this.hydrate(data as ISettings);
|
||||
}
|
||||
|
||||
@computed private pullKeys(keys: (keyof ISettings)[]) {
|
||||
private pullKeys(keys: (keyof ISettings)[]) {
|
||||
const obj: Partial<ISettings> = {};
|
||||
keys.forEach((key) => {
|
||||
const value = this.get(key);
|
||||
|
|
@ -154,7 +147,7 @@ export default class Settings
|
|||
return obj;
|
||||
}
|
||||
|
||||
@computed toSyncable() {
|
||||
toSyncable() {
|
||||
const data: Record<"appearance" | "theme", Partial<ISettings>> = {
|
||||
appearance: this.pullKeys([
|
||||
"appearance:emoji",
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ export default class Sync implements Store, Persistent<Data> {
|
|||
};
|
||||
}
|
||||
|
||||
@action hydrate(data: Data) {
|
||||
hydrate(data: Data) {
|
||||
if (data.disabled) {
|
||||
for (const key of data.disabled) {
|
||||
this.disabled.add(key as SyncKeys);
|
||||
|
|
@ -82,15 +82,15 @@ export default class Sync implements Store, Persistent<Data> {
|
|||
}
|
||||
}
|
||||
|
||||
@action enable(key: SyncKeys) {
|
||||
enable(key: SyncKeys) {
|
||||
this.disabled.delete(key);
|
||||
}
|
||||
|
||||
@action disable(key: SyncKeys) {
|
||||
disable(key: SyncKeys) {
|
||||
this.disabled.add(key);
|
||||
}
|
||||
|
||||
@action toggle(key: SyncKeys) {
|
||||
toggle(key: SyncKeys) {
|
||||
if (this.isEnabled(key)) {
|
||||
this.disable(key);
|
||||
} else {
|
||||
|
|
@ -98,20 +98,20 @@ export default class Sync implements Store, Persistent<Data> {
|
|||
}
|
||||
}
|
||||
|
||||
@computed isEnabled(key: SyncKeys) {
|
||||
isEnabled(key: SyncKeys) {
|
||||
return !this.disabled.has(key) && SYNC_KEYS.includes(key);
|
||||
}
|
||||
|
||||
@action setRevision(key: string, revision: number) {
|
||||
setRevision(key: string, revision: number) {
|
||||
if (revision < (this.getRevision(key) ?? 0)) return;
|
||||
this.revision.set(key, revision);
|
||||
}
|
||||
|
||||
@computed getRevision(key: string) {
|
||||
getRevision(key: string) {
|
||||
return this.revision.get(key);
|
||||
}
|
||||
|
||||
@action apply(data: Record<string, [number, string]>) {
|
||||
apply(data: Record<string, [number, string]>) {
|
||||
const tryRead = (key: string) => {
|
||||
if (key in data) {
|
||||
const revision = data[key][0];
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ export default class SAudio {
|
|||
setTimeout(() => this.loadCache(), 0);
|
||||
}
|
||||
|
||||
@action setEnabled(sound: Sounds, enabled: boolean) {
|
||||
setEnabled(sound: Sounds, enabled: boolean) {
|
||||
const obj = this.settings.get("notifications:sounds");
|
||||
this.settings.set("notifications:sounds", {
|
||||
...obj,
|
||||
|
|
@ -64,7 +64,7 @@ export default class SAudio {
|
|||
});
|
||||
}
|
||||
|
||||
@computed getSound(sound: Sounds, options?: SoundOptions): Sound {
|
||||
getSound(sound: Sounds, options?: SoundOptions): Sound {
|
||||
return {
|
||||
path: DefaultSoundPack[sound],
|
||||
enabled: DEFAULT_SOUNDS.includes(sound),
|
||||
|
|
@ -72,7 +72,7 @@ export default class SAudio {
|
|||
};
|
||||
}
|
||||
|
||||
@computed getState(): ({ id: Sounds } & Sound)[] {
|
||||
getState(): ({ id: Sounds } & Sound)[] {
|
||||
const options = this.settings.get("notifications:sounds");
|
||||
return ALL_SOUNDS.map((id) => {
|
||||
return { id, ...this.getSound(id, options) };
|
||||
|
|
@ -82,11 +82,10 @@ export default class SAudio {
|
|||
getAudio(path: string) {
|
||||
if (this.cache.has(path)) {
|
||||
return this.cache.get(path)!;
|
||||
}
|
||||
const el = new Audio(path);
|
||||
this.cache.set(path, el);
|
||||
return el;
|
||||
|
||||
}
|
||||
const el = new Audio(path);
|
||||
this.cache.set(path, el);
|
||||
return el;
|
||||
}
|
||||
|
||||
loadCache() {
|
||||
|
|
@ -100,7 +99,7 @@ export default class SAudio {
|
|||
try {
|
||||
audio.play();
|
||||
} catch (err) {
|
||||
console.error("Hit error while playing", `${sound }:`, err);
|
||||
console.error("Hit error while playing", `${sound}:`, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export default class SSecurity {
|
|||
makeAutoObservable(this);
|
||||
}
|
||||
|
||||
@action addTrustedOrigin(origin: string) {
|
||||
addTrustedOrigin(origin: string) {
|
||||
this.settings.set("security:trustedOrigins", [
|
||||
...(this.settings.get("security:trustedOrigins") ?? []).filter(
|
||||
(x) => x !== origin,
|
||||
|
|
@ -28,7 +28,7 @@ export default class SSecurity {
|
|||
]);
|
||||
}
|
||||
|
||||
@computed isTrustedOrigin(origin: string) {
|
||||
isTrustedOrigin(origin: string) {
|
||||
if (TRUSTED_DOMAINS.find((x) => origin.endsWith(x))) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ export default class STheme {
|
|||
this.reset = this.reset.bind(this);
|
||||
}
|
||||
|
||||
@computed toJSON() {
|
||||
toJSON() {
|
||||
return JSON.parse(
|
||||
JSON.stringify({
|
||||
...this.getVariables(),
|
||||
|
|
@ -46,7 +46,7 @@ export default class STheme {
|
|||
);
|
||||
}
|
||||
|
||||
@action hydrate(data: Partial<Theme>, resetCSS = false) {
|
||||
hydrate(data: Partial<Theme>, resetCSS = false) {
|
||||
if (resetCSS) this.setCSS();
|
||||
|
||||
for (const key of Object.keys(data)) {
|
||||
|
|
@ -74,7 +74,7 @@ export default class STheme {
|
|||
* Get the base theme used for this theme.
|
||||
* @returns Id of base theme
|
||||
*/
|
||||
@computed getBase() {
|
||||
getBase() {
|
||||
return this.settings.get("appearance:theme:base") ?? "dark";
|
||||
}
|
||||
|
||||
|
|
@ -82,7 +82,7 @@ export default class STheme {
|
|||
* Get whether the theme is light.
|
||||
* @returns True if the theme is light
|
||||
*/
|
||||
@computed isLight() {
|
||||
isLight() {
|
||||
return (
|
||||
this.settings.get("appearance:theme:light") ??
|
||||
this.getBase() === "light"
|
||||
|
|
@ -93,7 +93,7 @@ export default class STheme {
|
|||
* Get the current theme's CSS variables.
|
||||
* @returns Record of CSS variables
|
||||
*/
|
||||
@computed getVariables(): Theme {
|
||||
getVariables(): Theme {
|
||||
return {
|
||||
...PRESETS[this.getBase()],
|
||||
...this.settings.get("appearance:theme:overrides"),
|
||||
|
|
@ -101,7 +101,7 @@ export default class STheme {
|
|||
};
|
||||
}
|
||||
|
||||
@computed computeVariables(): ComputedVariables {
|
||||
computeVariables(): ComputedVariables {
|
||||
const variables = this.getVariables() as Record<
|
||||
string,
|
||||
string | boolean | number
|
||||
|
|
@ -110,7 +110,7 @@ export default class STheme {
|
|||
for (const key of Object.keys(variables)) {
|
||||
const value = variables[key];
|
||||
if (typeof value === "string") {
|
||||
variables[`${key }-contrast`] = getContrastingColour(value);
|
||||
variables[`${key}-contrast`] = getContrastingColour(value);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ export default class STheme {
|
|||
};
|
||||
}
|
||||
|
||||
@action setVariable(key: Variables, value: string) {
|
||||
setVariable(key: Variables, value: string) {
|
||||
this.settings.set("appearance:theme:overrides", {
|
||||
...this.settings.get("appearance:theme:overrides"),
|
||||
[key]: value,
|
||||
|
|
@ -138,7 +138,7 @@ export default class STheme {
|
|||
* @param key Variable
|
||||
* @returns Value of variable
|
||||
*/
|
||||
@computed getVariable(key: Variables) {
|
||||
getVariable(key: Variables) {
|
||||
return (this.settings.get("appearance:theme:overrides")?.[key] ??
|
||||
PRESETS[this.getBase()]?.[key])!;
|
||||
}
|
||||
|
|
@ -148,11 +148,11 @@ export default class STheme {
|
|||
* @param key Variable
|
||||
* @returns Contrasting value
|
||||
*/
|
||||
@computed getContrastingVariable(key: Variables, fallback?: string) {
|
||||
getContrastingVariable(key: Variables, fallback?: string) {
|
||||
return getContrastingColour(this.getVariable(key), fallback);
|
||||
}
|
||||
|
||||
@action setFont(font: Fonts) {
|
||||
setFont(font: Fonts) {
|
||||
this.settings.set("appearance:theme:font", font);
|
||||
}
|
||||
|
||||
|
|
@ -160,11 +160,11 @@ export default class STheme {
|
|||
* Get the current applied font.
|
||||
* @returns Current font
|
||||
*/
|
||||
@computed getFont() {
|
||||
getFont() {
|
||||
return this.settings.get("appearance:theme:font") ?? DEFAULT_FONT;
|
||||
}
|
||||
|
||||
@action setMonospaceFont(font: MonospaceFonts) {
|
||||
setMonospaceFont(font: MonospaceFonts) {
|
||||
this.settings.set("appearance:theme:monoFont", font);
|
||||
}
|
||||
|
||||
|
|
@ -172,13 +172,13 @@ export default class STheme {
|
|||
* Get the current applied monospace font.
|
||||
* @returns Current monospace font
|
||||
*/
|
||||
@computed getMonospaceFont() {
|
||||
getMonospaceFont() {
|
||||
return (
|
||||
this.settings.get("appearance:theme:monoFont") ?? DEFAULT_MONO_FONT
|
||||
);
|
||||
}
|
||||
|
||||
@action setCSS(value?: string) {
|
||||
setCSS(value?: string) {
|
||||
if (value && value.length > 0) {
|
||||
this.settings.set("appearance:theme:css", value);
|
||||
} else {
|
||||
|
|
@ -190,18 +190,18 @@ export default class STheme {
|
|||
* Get the currently applied CSS snippet.
|
||||
* @returns CSS string
|
||||
*/
|
||||
@computed getCSS() {
|
||||
getCSS() {
|
||||
return this.settings.get("appearance:theme:css");
|
||||
}
|
||||
|
||||
@computed isModified() {
|
||||
isModified() {
|
||||
return (
|
||||
Object.keys(this.settings.get("appearance:theme:overrides") ?? {})
|
||||
.length > 0
|
||||
);
|
||||
}
|
||||
|
||||
@action setBase(base?: "light" | "dark") {
|
||||
setBase(base?: "light" | "dark") {
|
||||
if (base) {
|
||||
this.settings.set("appearance:theme:base", base);
|
||||
} else {
|
||||
|
|
@ -209,7 +209,7 @@ export default class STheme {
|
|||
}
|
||||
}
|
||||
|
||||
@action reset() {
|
||||
reset() {
|
||||
this.settings.remove("appearance:theme:overrides");
|
||||
this.settings.remove("appearance:theme:css");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -128,4 +128,7 @@ export default defineConfig({
|
|||
resolve: {
|
||||
preserveSymlinks: true,
|
||||
},
|
||||
define: {
|
||||
"process.env": {},
|
||||
},
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in New Issue