feat(mobx): migrate legacy data

This commit is contained in:
Paul 2021-12-24 11:19:02 +00:00
parent e89bbb7455
commit 74430b1a8f
2 changed files with 105 additions and 13 deletions

View file

@ -4,6 +4,8 @@ import localforage from "localforage";
import { makeAutoObservable, reaction } from "mobx";
import { Client } from "revolt.js";
import { legacyMigrateForwards, LegacyState } from "./legacy/redux";
import Persistent from "./interfaces/Persistent";
import Syncable from "./interfaces/Syncable";
import Auth from "./stores/Auth";
@ -89,10 +91,23 @@ export default class State {
}
}
/**
* Temporarily ignore updates to a key.
* @param key Key to ignore
*/
setDisabled(key: string) {
this.disabled.add(key);
}
/**
* Save to disk.
*/
async save() {
for (const [id, store] of this.persistent) {
await localforage.setItem(id, store.toJSON());
}
}
/**
* Register reaction listeners for persistent data stores.
* @returns Function to dispose of listeners
@ -177,6 +192,20 @@ export default class State {
* Load data stores from local storage.
*/
async hydrate() {
// Migrate legacy Redux store.
let legacy = await localforage.getItem("state");
if (legacy) {
if (typeof legacy === "string") {
legacy = JSON.parse(legacy);
}
legacyMigrateForwards(legacy as Partial<LegacyState>, this);
await localforage.removeItem("state");
await this.save();
return;
}
// Load MobX store.
const sync = (await localforage.getItem("sync")) as DataSync;
if (sync) {
const { revision } = sync;
@ -205,15 +234,3 @@ export async function hydrateState() {
export function useApplicationState() {
return state;
}
/**
*
* Redux hydration:
* localForage.getItem("state").then((s) => {
if (s !== null) {
dispatch({ type: "__INIT", state: s as State });
}
state.hydrate().then(() => setLoaded(true));
});
*/

View file

@ -1,8 +1,15 @@
import { runInAction } from "mobx";
import { Session } from "revolt-api/types/Auth";
import { Language } from "../../context/Locale";
import { Fonts, MonospaceFonts, Overrides } from "../../context/Theme";
import {
Fonts,
MonospaceFonts,
Overrides,
ThemeOptions,
} from "../../context/Theme";
import State from "../State";
import { Data as DataAuth } from "../stores/Auth";
import { Data as DataLocaleOptions } from "../stores/LocaleOptions";
import { Data as DataNotificationOptions } from "../stores/NotificationOptions";
@ -62,6 +69,11 @@ export interface LegacyAuthState {
active?: string;
}
export interface LegacySettings {
theme?: LegacyThemeOptions;
appearance?: LegacyAppearanceOptions;
}
export function legacyMigrateAuth(auth: LegacyAuthState): DataAuth {
return {
current: auth.active,
@ -100,6 +112,20 @@ export function legacyMigrateAppearance(
};
}
/**
* Remove trolling from an object
* @param inp Object to remove trolling from
* @returns Object without trolling
*/
function detroll(inp: object): ISettings {
const obj: object = {};
Object.keys(inp)
.filter((x) => typeof (inp as any)[x] !== "undefined")
.map((x) => ((obj as any)[x] = (inp as any)[x]));
return obj as unknown as ISettings;
}
export function legacyMigrateNotification(
channel: LegacyNotifications,
): DataNotificationOptions {
@ -116,3 +142,52 @@ export function legacyMigrateSync(sync: LegacySyncOptions): DataSync {
},
};
}
export type LegacyState = {
locale: Language;
auth: LegacyAuthState;
settings: LegacySettings;
sync: LegacySyncOptions;
notifications: LegacyNotifications;
};
export function legacyMigrateForwards(
data: Partial<LegacyState>,
target: State,
) {
runInAction(() => {
if ("sync" in data) {
target.sync.hydrate(legacyMigrateSync(data.sync!));
}
if ("locale" in data) {
target.locale.hydrate(legacyMigrateLocale(data.locale!));
}
if ("auth" in data) {
target.auth.hydrate(legacyMigrateAuth(data.auth!));
}
if ("settings" in data) {
if (data!.settings!.theme) {
target.settings.hydrate(
detroll(legacyMigrateTheme(data.settings!.theme!)),
);
}
if (data!.settings!.appearance) {
target.settings.hydrate(
detroll(
legacyMigrateAppearance(data.settings!.appearance!),
),
);
}
}
if ("notifications" in data) {
target.notifications.hydrate(
legacyMigrateNotification(data.notifications!),
);
}
});
}