mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-04 21:00:58 -05:00
feat: add "ordering" data store
This commit is contained in:
parent
a9e4839727
commit
4d996deb1e
6 changed files with 129 additions and 17 deletions
|
@ -90,13 +90,13 @@
|
||||||
"@hcaptcha/react-hcaptcha": "^0.3.6",
|
"@hcaptcha/react-hcaptcha": "^0.3.6",
|
||||||
"@insertish/vite-plugin-babel-macros": "^1.0.5",
|
"@insertish/vite-plugin-babel-macros": "^1.0.5",
|
||||||
"@preact/preset-vite": "^2.0.0",
|
"@preact/preset-vite": "^2.0.0",
|
||||||
"@revoltchat/ui": "^1.0.32",
|
"@revoltchat/ui": "1.0.33",
|
||||||
"@rollup/plugin-replace": "^2.4.2",
|
"@rollup/plugin-replace": "^2.4.2",
|
||||||
"@styled-icons/boxicons-logos": "^10.38.0",
|
"@styled-icons/boxicons-logos": "^10.38.0",
|
||||||
"@styled-icons/boxicons-regular": "^10.38.0",
|
"@styled-icons/boxicons-regular": "^10.38.0",
|
||||||
"@styled-icons/boxicons-solid": "^10.38.0",
|
"@styled-icons/boxicons-solid": "^10.38.0",
|
||||||
"@styled-icons/simple-icons": "^10.33.0",
|
"@styled-icons/simple-icons": "^10.33.0",
|
||||||
"@tippyjs/react": "npm:4.2.5",
|
"@tippyjs/react": "4.2.6",
|
||||||
"@traptitech/markdown-it-katex": "^3.4.3",
|
"@traptitech/markdown-it-katex": "^3.4.3",
|
||||||
"@traptitech/markdown-it-spoiler": "^1.1.6",
|
"@traptitech/markdown-it-spoiler": "^1.1.6",
|
||||||
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
|
"@trivago/prettier-plugin-sort-imports": "^2.0.2",
|
||||||
|
@ -138,14 +138,14 @@
|
||||||
"prettier": "^2.3.1",
|
"prettier": "^2.3.1",
|
||||||
"prismjs": "^1.23.0",
|
"prismjs": "^1.23.0",
|
||||||
"react-beautiful-dnd": "^13.1.0",
|
"react-beautiful-dnd": "^13.1.0",
|
||||||
"react-device-detect": "npm:2.2.2",
|
"react-device-detect": "2.2.2",
|
||||||
"react-helmet": "^6.1.0",
|
"react-helmet": "^6.1.0",
|
||||||
"react-hook-form": "6.3.0",
|
"react-hook-form": "6.3.0",
|
||||||
"react-overlapping-panels": "1.2.2",
|
"react-overlapping-panels": "1.2.2",
|
||||||
"react-router-dom": "^5.2.0",
|
"react-router-dom": "^5.2.0",
|
||||||
"react-scroll": "^1.8.2",
|
"react-scroll": "^1.8.2",
|
||||||
"react-virtuoso": "^2.12.0",
|
"react-virtuoso": "^2.12.0",
|
||||||
"revolt.js": "npm:6.0.1",
|
"revolt.js": "6.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.35.1",
|
"sass": "^1.35.1",
|
||||||
"shade-blend-color": "^1.0.0",
|
"shade-blend-color": "^1.0.0",
|
||||||
|
|
|
@ -35,6 +35,8 @@ export default observer(() => {
|
||||||
createServer={createServer}
|
createServer={createServer}
|
||||||
permit={state.notifications}
|
permit={state.notifications}
|
||||||
home={state.layout.getLastHomePath}
|
home={state.layout.getLastHomePath}
|
||||||
|
servers={state.ordering.orderedServers}
|
||||||
|
reorder={state.ordering.reorderServer}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,6 +17,7 @@ import Layout from "./stores/Layout";
|
||||||
import LocaleOptions from "./stores/LocaleOptions";
|
import LocaleOptions from "./stores/LocaleOptions";
|
||||||
import MessageQueue from "./stores/MessageQueue";
|
import MessageQueue from "./stores/MessageQueue";
|
||||||
import NotificationOptions from "./stores/NotificationOptions";
|
import NotificationOptions from "./stores/NotificationOptions";
|
||||||
|
import Ordering from "./stores/Ordering";
|
||||||
import Plugins from "./stores/Plugins";
|
import Plugins from "./stores/Plugins";
|
||||||
import ServerConfig from "./stores/ServerConfig";
|
import ServerConfig from "./stores/ServerConfig";
|
||||||
import Settings from "./stores/Settings";
|
import Settings from "./stores/Settings";
|
||||||
|
@ -41,6 +42,7 @@ export default class State {
|
||||||
settings: Settings;
|
settings: Settings;
|
||||||
sync: Sync;
|
sync: Sync;
|
||||||
plugins: Plugins;
|
plugins: Plugins;
|
||||||
|
ordering: Ordering;
|
||||||
|
|
||||||
private persistent: [string, Persistent<unknown>][] = [];
|
private persistent: [string, Persistent<unknown>][] = [];
|
||||||
private disabled: Set<string> = new Set();
|
private disabled: Set<string> = new Set();
|
||||||
|
@ -62,6 +64,7 @@ export default class State {
|
||||||
this.settings = new Settings();
|
this.settings = new Settings();
|
||||||
this.sync = new Sync(this);
|
this.sync = new Sync(this);
|
||||||
this.plugins = new Plugins(this);
|
this.plugins = new Plugins(this);
|
||||||
|
this.ordering = new Ordering(this);
|
||||||
|
|
||||||
makeAutoObservable(this, {
|
makeAutoObservable(this, {
|
||||||
client: false,
|
client: false,
|
||||||
|
@ -280,6 +283,7 @@ export default class State {
|
||||||
this.queue = new MessageQueue();
|
this.queue = new MessageQueue();
|
||||||
this.settings = new Settings();
|
this.settings = new Settings();
|
||||||
this.sync = new Sync(this);
|
this.sync = new Sync(this);
|
||||||
|
this.ordering = new Ordering(this);
|
||||||
|
|
||||||
this.save();
|
this.save();
|
||||||
|
|
||||||
|
|
93
src/mobx/stores/Ordering.ts
Normal file
93
src/mobx/stores/Ordering.ts
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
import { action, computed, makeAutoObservable } from "mobx";
|
||||||
|
|
||||||
|
import { reorder } from "@revoltchat/ui";
|
||||||
|
|
||||||
|
import State from "../State";
|
||||||
|
import Persistent from "../interfaces/Persistent";
|
||||||
|
import Store from "../interfaces/Store";
|
||||||
|
import Syncable from "../interfaces/Syncable";
|
||||||
|
|
||||||
|
export interface Data {
|
||||||
|
servers?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of ordering of various elements
|
||||||
|
*/
|
||||||
|
export default class Ordering implements Store, Persistent<Data>, Syncable {
|
||||||
|
private state: State;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ordered list of server IDs
|
||||||
|
*/
|
||||||
|
private servers: string[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new Layout store.
|
||||||
|
*/
|
||||||
|
constructor(state: State) {
|
||||||
|
this.servers = [];
|
||||||
|
makeAutoObservable(this);
|
||||||
|
|
||||||
|
this.state = state;
|
||||||
|
this.reorderServer = this.reorderServer.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
get id() {
|
||||||
|
return "ordering";
|
||||||
|
}
|
||||||
|
|
||||||
|
toJSON() {
|
||||||
|
return {
|
||||||
|
servers: this.servers,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@action hydrate(data: Data) {
|
||||||
|
if (data.servers) {
|
||||||
|
this.servers = data.servers;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply(_key: string, data: unknown, _revision: number): void {
|
||||||
|
this.hydrate(data as Data);
|
||||||
|
}
|
||||||
|
|
||||||
|
toSyncable(): { [key: string]: object } {
|
||||||
|
return {
|
||||||
|
ordering: this.toJSON(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All known servers with ordering applied
|
||||||
|
*/
|
||||||
|
@computed get orderedServers() {
|
||||||
|
const known = new Set(this.state.client?.servers.keys() ?? []);
|
||||||
|
const ordered = [...this.servers];
|
||||||
|
|
||||||
|
const out = [];
|
||||||
|
for (const id of ordered) {
|
||||||
|
if (known.delete(id)) {
|
||||||
|
out.push(this.state.client!.servers.get(id)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const id of known) {
|
||||||
|
out.push(this.state.client!.servers.get(id)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Re-order a server
|
||||||
|
*/
|
||||||
|
@action reorderServer(source: number, dest: number) {
|
||||||
|
this.servers = reorder(
|
||||||
|
this.orderedServers.map((x) => x._id),
|
||||||
|
source,
|
||||||
|
dest,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,13 +14,19 @@ import State from "../State";
|
||||||
import Persistent from "../interfaces/Persistent";
|
import Persistent from "../interfaces/Persistent";
|
||||||
import Store from "../interfaces/Store";
|
import Store from "../interfaces/Store";
|
||||||
|
|
||||||
export type SyncKeys = "theme" | "appearance" | "locale" | "notifications";
|
export type SyncKeys =
|
||||||
|
| "theme"
|
||||||
|
| "appearance"
|
||||||
|
| "locale"
|
||||||
|
| "notifications"
|
||||||
|
| "ordering";
|
||||||
|
|
||||||
export const SYNC_KEYS: SyncKeys[] = [
|
export const SYNC_KEYS: SyncKeys[] = [
|
||||||
"theme",
|
"theme",
|
||||||
"appearance",
|
"appearance",
|
||||||
"locale",
|
"locale",
|
||||||
"notifications",
|
"notifications",
|
||||||
|
"ordering",
|
||||||
];
|
];
|
||||||
|
|
||||||
export interface Data {
|
export interface Data {
|
||||||
|
@ -151,6 +157,13 @@ export default class Sync implements Store, Persistent<Data> {
|
||||||
);
|
);
|
||||||
this.setRevision("notifications", notifications[0]);
|
this.setRevision("notifications", notifications[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ordering = tryRead("ordering");
|
||||||
|
if (ordering) {
|
||||||
|
this.state.setDisabled("ordering");
|
||||||
|
this.state.ordering.apply("ordering", ordering[1], ordering[0]);
|
||||||
|
this.setRevision("ordering", ordering[0]);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
24
yarn.lock
24
yarn.lock
|
@ -2220,9 +2220,9 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@revoltchat/ui@npm:^1.0.32":
|
"@revoltchat/ui@npm:1.0.33":
|
||||||
version: 1.0.32
|
version: 1.0.33
|
||||||
resolution: "@revoltchat/ui@npm:1.0.32"
|
resolution: "@revoltchat/ui@npm:1.0.33"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@styled-icons/boxicons-logos": ^10.38.0
|
"@styled-icons/boxicons-logos": ^10.38.0
|
||||||
"@styled-icons/boxicons-regular": ^10.38.0
|
"@styled-icons/boxicons-regular": ^10.38.0
|
||||||
|
@ -2235,7 +2235,7 @@ __metadata:
|
||||||
react-device-detect: "*"
|
react-device-detect: "*"
|
||||||
react-virtuoso: "*"
|
react-virtuoso: "*"
|
||||||
revolt.js: "*"
|
revolt.js: "*"
|
||||||
checksum: 7004add041a66932a7efc836f33648e905bd9820dd1d65890bccc93bc95cbc643ccede67dc570341fcc9c9993fffb57702dbd6ed41dac014553be18400bc313e
|
checksum: 503fbf8557d205be153343776b8803335b6444b8767e0b1fccf6a34470e4cb333118f7cb614bf16e20d22cb811e7e1160622b9557b73414ad554f8b4bbfb565b
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -2384,15 +2384,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@tippyjs/react@npm:4.2.5":
|
"@tippyjs/react@npm:4.2.6":
|
||||||
version: 4.2.5
|
version: 4.2.6
|
||||||
resolution: "@tippyjs/react@npm:4.2.5"
|
resolution: "@tippyjs/react@npm:4.2.6"
|
||||||
dependencies:
|
dependencies:
|
||||||
tippy.js: ^6.3.1
|
tippy.js: ^6.3.1
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ">=16.8"
|
react: ">=16.8"
|
||||||
react-dom: ">=16.8"
|
react-dom: ">=16.8"
|
||||||
checksum: 68a6bb8922597df105f601953f14c593a8179328026dc425db0cd5d8521cdd8ad8c6ec7b6d0707708c8ed25e5ad01c488e95a6b3de0b2f404bd71137e2b8fce9
|
checksum: 8f0fba591c9dae2e1af1ae632bbc775ba5c9dd4498e50e242be70302b4c27115c6740eec44e885e294b27cb28515777b52af5b34aac9d4bab627d948add938ae
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -3521,13 +3521,13 @@ __metadata:
|
||||||
"@hcaptcha/react-hcaptcha": ^0.3.6
|
"@hcaptcha/react-hcaptcha": ^0.3.6
|
||||||
"@insertish/vite-plugin-babel-macros": ^1.0.5
|
"@insertish/vite-plugin-babel-macros": ^1.0.5
|
||||||
"@preact/preset-vite": ^2.0.0
|
"@preact/preset-vite": ^2.0.0
|
||||||
"@revoltchat/ui": ^1.0.32
|
"@revoltchat/ui": 1.0.33
|
||||||
"@rollup/plugin-replace": ^2.4.2
|
"@rollup/plugin-replace": ^2.4.2
|
||||||
"@styled-icons/boxicons-logos": ^10.38.0
|
"@styled-icons/boxicons-logos": ^10.38.0
|
||||||
"@styled-icons/boxicons-regular": ^10.38.0
|
"@styled-icons/boxicons-regular": ^10.38.0
|
||||||
"@styled-icons/boxicons-solid": ^10.38.0
|
"@styled-icons/boxicons-solid": ^10.38.0
|
||||||
"@styled-icons/simple-icons": ^10.33.0
|
"@styled-icons/simple-icons": ^10.33.0
|
||||||
"@tippyjs/react": "npm:4.2.5"
|
"@tippyjs/react": 4.2.6
|
||||||
"@traptitech/markdown-it-katex": ^3.4.3
|
"@traptitech/markdown-it-katex": ^3.4.3
|
||||||
"@traptitech/markdown-it-spoiler": ^1.1.6
|
"@traptitech/markdown-it-spoiler": ^1.1.6
|
||||||
"@trivago/prettier-plugin-sort-imports": ^2.0.2
|
"@trivago/prettier-plugin-sort-imports": ^2.0.2
|
||||||
|
@ -3571,14 +3571,14 @@ __metadata:
|
||||||
prettier: ^2.3.1
|
prettier: ^2.3.1
|
||||||
prismjs: ^1.23.0
|
prismjs: ^1.23.0
|
||||||
react-beautiful-dnd: ^13.1.0
|
react-beautiful-dnd: ^13.1.0
|
||||||
react-device-detect: "npm:2.2.2"
|
react-device-detect: 2.2.2
|
||||||
react-helmet: ^6.1.0
|
react-helmet: ^6.1.0
|
||||||
react-hook-form: 6.3.0
|
react-hook-form: 6.3.0
|
||||||
react-overlapping-panels: 1.2.2
|
react-overlapping-panels: 1.2.2
|
||||||
react-router-dom: ^5.2.0
|
react-router-dom: ^5.2.0
|
||||||
react-scroll: ^1.8.2
|
react-scroll: ^1.8.2
|
||||||
react-virtuoso: ^2.12.0
|
react-virtuoso: ^2.12.0
|
||||||
revolt.js: "npm:6.0.1"
|
revolt.js: 6.0.1
|
||||||
rimraf: ^3.0.2
|
rimraf: ^3.0.2
|
||||||
sass: ^1.35.1
|
sass: ^1.35.1
|
||||||
shade-blend-color: ^1.0.0
|
shade-blend-color: ^1.0.0
|
||||||
|
|
Loading…
Reference in a new issue