mirror of
https://github.com/revoltchat/revite.git
synced 2024-12-24 06:32:08 -05:00
feat(mobx): write experiments, lastOpened and localeOptions stores
This commit is contained in:
parent
5a41c25e3c
commit
185f76d850
4 changed files with 236 additions and 10 deletions
|
@ -1,4 +1,4 @@
|
||||||
import { makeAutoObservable } from "mobx";
|
import { makeAutoObservable, ObservableMap } from "mobx";
|
||||||
import { Session } from "revolt-api/types/Auth";
|
import { Session } from "revolt-api/types/Auth";
|
||||||
import { Nullable } from "revolt.js/dist/util/null";
|
import { Nullable } from "revolt.js/dist/util/null";
|
||||||
|
|
||||||
|
@ -15,14 +15,14 @@ interface Data {
|
||||||
* accounts and their sessions.
|
* accounts and their sessions.
|
||||||
*/
|
*/
|
||||||
export default class Auth implements Persistent<Data> {
|
export default class Auth implements Persistent<Data> {
|
||||||
private sessions: Record<string, Session>;
|
private sessions: ObservableMap<string, Session>;
|
||||||
private current: Nullable<string>;
|
private current: Nullable<string>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct new Auth store.
|
* Construct new Auth store.
|
||||||
*/
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
this.sessions = {};
|
this.sessions = new ObservableMap();
|
||||||
this.current = null;
|
this.current = null;
|
||||||
makeAutoObservable(this);
|
makeAutoObservable(this);
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,11 @@ export default class Auth implements Persistent<Data> {
|
||||||
|
|
||||||
// eslint-disable-next-line require-jsdoc
|
// eslint-disable-next-line require-jsdoc
|
||||||
hydrate(data: Data) {
|
hydrate(data: Data) {
|
||||||
this.sessions = data.sessions;
|
Object.keys(data.sessions).forEach((id) =>
|
||||||
if (data.current && this.sessions[data.current]) {
|
this.sessions.set(id, data.sessions[id]),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (data.current && this.sessions.has(data.current)) {
|
||||||
this.current = data.current;
|
this.current = data.current;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,11 +51,7 @@ export default class Auth implements Persistent<Data> {
|
||||||
* @param session Session
|
* @param session Session
|
||||||
*/
|
*/
|
||||||
setSession(session: Session) {
|
setSession(session: Session) {
|
||||||
this.sessions = {
|
this.sessions.set(session.user_id, session);
|
||||||
...this.sessions,
|
|
||||||
[session.user_id]: session,
|
|
||||||
};
|
|
||||||
|
|
||||||
this.current = session.user_id;
|
this.current = session.user_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
86
src/mobx/stores/Experiments.ts
Normal file
86
src/mobx/stores/Experiments.ts
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
import { action, computed, makeAutoObservable, ObservableSet } from "mobx";
|
||||||
|
|
||||||
|
import Persistent from "../Persistent";
|
||||||
|
|
||||||
|
export type Experiment = "search" | "theme_shop";
|
||||||
|
|
||||||
|
export const AVAILABLE_EXPERIMENTS: Experiment[] = ["theme_shop"];
|
||||||
|
|
||||||
|
export const EXPERIMENTS: {
|
||||||
|
[key in Experiment]: { title: string; description: string };
|
||||||
|
} = {
|
||||||
|
search: {
|
||||||
|
title: "Search",
|
||||||
|
description: "Allows you to search for messages in channels.",
|
||||||
|
},
|
||||||
|
theme_shop: {
|
||||||
|
title: "Theme Shop",
|
||||||
|
description: "Allows you to access and set user submitted themes.",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
enabled?: Experiment[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles enabling and disabling client experiments.
|
||||||
|
*/
|
||||||
|
export default class Experiments implements Persistent<Data> {
|
||||||
|
private enabled: ObservableSet<Experiment>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new Experiments store.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this.enabled = new ObservableSet();
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
toJSON() {
|
||||||
|
return {
|
||||||
|
enabled: this.enabled,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
@action hydrate(data: Data) {
|
||||||
|
if (data.enabled) {
|
||||||
|
for (const experiment of data.enabled) {
|
||||||
|
this.enabled.add(experiment as Experiment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if an experiment is enabled.
|
||||||
|
* @param experiment Experiment
|
||||||
|
*/
|
||||||
|
@computed isEnabled(experiment: Experiment) {
|
||||||
|
return this.enabled.has(experiment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable an experiment.
|
||||||
|
* @param experiment Experiment
|
||||||
|
*/
|
||||||
|
@action enable(experiment: Experiment) {
|
||||||
|
this.enabled.add(experiment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable an experiment.
|
||||||
|
* @param experiment Experiment
|
||||||
|
*/
|
||||||
|
@action disable(experiment: Experiment) {
|
||||||
|
this.enabled.delete(experiment);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset and disable all experiments.
|
||||||
|
*/
|
||||||
|
@action reset() {
|
||||||
|
this.enabled.clear();
|
||||||
|
}
|
||||||
|
}
|
57
src/mobx/stores/LastOpened.ts
Normal file
57
src/mobx/stores/LastOpened.ts
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
import { action, computed, makeAutoObservable, ObservableMap } from "mobx";
|
||||||
|
|
||||||
|
import Persistent from "../Persistent";
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
server?: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of the last open channels, tabs, etc.
|
||||||
|
* Handles providing good UX experience on navigating
|
||||||
|
* back and forth between different parts of the app.
|
||||||
|
*/
|
||||||
|
export default class Experiments implements Persistent<Data> {
|
||||||
|
private server: ObservableMap<string, string>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new Experiments store.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this.server = new ObservableMap();
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
toJSON() {
|
||||||
|
return {
|
||||||
|
server: this.server,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
@action hydrate(data: Data) {
|
||||||
|
if (data.server) {
|
||||||
|
Object.keys(data.server).forEach((key) =>
|
||||||
|
this.server.set(key, data.server![key]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get last opened channel in a server.
|
||||||
|
* @param server Server ID
|
||||||
|
*/
|
||||||
|
@computed get(server: string) {
|
||||||
|
return this.server.get(server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set last opened channel in a server.
|
||||||
|
* @param server Server ID
|
||||||
|
* @param channel Channel ID
|
||||||
|
*/
|
||||||
|
@action enable(server: string, channel: string) {
|
||||||
|
this.server.set(server, channel);
|
||||||
|
}
|
||||||
|
}
|
84
src/mobx/stores/LocaleOptions.ts
Normal file
84
src/mobx/stores/LocaleOptions.ts
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import { action, computed, makeAutoObservable } from "mobx";
|
||||||
|
|
||||||
|
import { Language, Languages } from "../../context/Locale";
|
||||||
|
|
||||||
|
import Persistent from "../Persistent";
|
||||||
|
|
||||||
|
interface Data {
|
||||||
|
lang: Language;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect the browser language or match given language.
|
||||||
|
* @param lang Language to find
|
||||||
|
* @returns Matched Language
|
||||||
|
*/
|
||||||
|
export function findLanguage(lang?: string): Language {
|
||||||
|
if (!lang) {
|
||||||
|
if (typeof navigator === "undefined") {
|
||||||
|
lang = Language.ENGLISH;
|
||||||
|
} else {
|
||||||
|
lang = navigator.language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = lang.replace("-", "_");
|
||||||
|
const short = code.split("_")[0];
|
||||||
|
|
||||||
|
const values = [];
|
||||||
|
for (const key in Language) {
|
||||||
|
const value = Language[key as keyof typeof Language];
|
||||||
|
|
||||||
|
// Skip alternative/joke languages
|
||||||
|
if (Languages[value].cat === "alt") continue;
|
||||||
|
|
||||||
|
values.push(value);
|
||||||
|
if (value.startsWith(code)) {
|
||||||
|
return value as Language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const value of values.reverse()) {
|
||||||
|
if (value.startsWith(short)) {
|
||||||
|
return value as Language;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Language.ENGLISH;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Keeps track of the last open channels, tabs, etc.
|
||||||
|
* Handles providing good UX experience on navigating
|
||||||
|
* back and forth between different parts of the app.
|
||||||
|
*/
|
||||||
|
export default class LocaleOptions implements Persistent<Data> {
|
||||||
|
private lang: Language;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct new LocaleOptions store.
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
this.lang = findLanguage();
|
||||||
|
makeAutoObservable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
toJSON() {
|
||||||
|
return {
|
||||||
|
lang: this.lang,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line require-jsdoc
|
||||||
|
@action hydrate(data: Data) {
|
||||||
|
this.lang = data.lang;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get current language.
|
||||||
|
*/
|
||||||
|
@computed getLang() {
|
||||||
|
return this.lang;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue