Переглянути джерело

feat: helper function for config migration & bump format ver

Sv443 11 місяців тому
батько
коміт
ba0996997b
1 змінених файлів з 62 додано та 17 видалено
  1. 62 17
      src/config.ts

+ 62 - 17
src/config.ts

@@ -1,13 +1,22 @@
 import { DataStore, compress, type DataMigrationsDict, decompress } from "@sv443-network/userutils";
-import { featInfo } from "./features/index";
-import { compressionSupported, error, info, log } from "./utils";
+import { disableBeforeUnload, featInfo } from "./features/index";
+import { compressionSupported, error, getVideoTime, info, log, t } from "./utils";
 import { emitSiteEvent } from "./siteEvents";
 import { compressionFormat, mode } from "./constants";
 import { emitInterface } from "./interface";
+import { closeCfgMenu } from "./menu/menu_old";
 import type { FeatureConfig, FeatureKey } from "./types";
 
 /** If this number is incremented, the features object data will be migrated to the new format */
-export const formatVersion = 5;
+export const formatVersion = 6;
+
+export const defaultData = (Object.keys(featInfo) as (keyof typeof featInfo)[])
+  .reduce<Partial<FeatureConfig>>((acc, key) => {
+    // @ts-ignore
+    acc[key] = featInfo?.[key]?.default as unknown as undefined;
+    return acc;
+  }, {}) as FeatureConfig;
+
 /** Config data format migration dictionary */
 export const migrations: DataMigrationsDict = {
   // 1 -> 2 (<=v1.0)
@@ -59,25 +68,24 @@ export const migrations: DataMigrationsDict = {
     "closeToastsTimeout", "disableDarkReaderSites",
   ]),
   // 5 -> 6 (v2.1)
-  6: (oldData: FeatureConfig) => useDefaultConfig(oldData, [
-    "autoLikeChannels", "autoLikeChannelToggleBtn",
-    "autoLikePlayerBarToggleBtn", "autoLikeTimeout",
-    "autoLikeShowToast", "autoLikeOpenMgmtDialog",
-    // reset existing:
-    "rememberSongTimeSites",
-  ]),
+  6: (oldData: FeatureConfig) => useNewDefaultIfUnchanged(
+    useDefaultConfig(
+      JSON.parse(JSON.stringify(oldData)),
+      [
+        "autoLikeChannels", "autoLikeChannelToggleBtn",
+        "autoLikePlayerBarToggleBtn", "autoLikeTimeout",
+        "autoLikeShowToast", "autoLikeOpenMgmtDialog",
+      ],
+    ), [
+      { key: "rememberSongTimeSites", oldDefault: "ytm" },
+      { key: "volumeSliderScrollStep", oldDefault: 10 },
+    ],
+  ),
   // TODO: once advanced filtering is fully implemented, clear cache on migration to fv6
   // 6 -> 7 (v2.x)
   // 7: (oldData: FeatureConfig) => 
 } as const satisfies DataMigrationsDict;
 
-export const defaultData = (Object.keys(featInfo) as (keyof typeof featInfo)[])
-  .reduce<Partial<FeatureConfig>>((acc, key) => {
-    // @ts-ignore
-    acc[key] = featInfo?.[key]?.default as unknown as undefined;
-    return acc;
-  }, {}) as FeatureConfig;
-
 /** Uses the default config as the base, then overwrites all values with the passed {@linkcode baseData}, then sets all passed {@linkcode resetKeys} to their default values */
 function useDefaultConfig(baseData: Partial<FeatureConfig> | undefined, resetKeys: (keyof typeof featInfo)[]): FeatureConfig {
   const newData = { ...defaultData, ...(baseData ?? {}) };
@@ -86,6 +94,25 @@ function useDefaultConfig(baseData: Partial<FeatureConfig> | undefined, resetKey
   return newData;
 }
 
+/**
+ * Uses {@linkcode oldData} as the base, then sets all keys provided in {@linkcode defaults} to their old default values, as long as their current value is equal to the provided old default.  
+ * This essentially means if someone has changed a feature's value from its old default value, that decision will be respected. Only if it has been left on its default value, it will be reset to the new default value.  
+ * Returns a copy of the object.
+ */
+function useNewDefaultIfUnchanged<TConfig extends Partial<FeatureConfig>>(
+  oldData: TConfig,
+  defaults: Array<{ key: FeatureKey, oldDefault: unknown }>,
+) {
+  const newData = { ...oldData };
+  for(const { key, oldDefault } of defaults) {
+    // @ts-ignore
+    const defaultVal = featInfo?.[key]?.default as TConfig[typeof key];
+    if(newData[key] === oldDefault)
+      newData[key] = defaultVal as never; // we love TS
+  }
+  return newData as TConfig;
+}
+
 let canCompress = true;
 
 const cfgDataStore = new DataStore({
@@ -169,6 +196,24 @@ export function setDefaultFeatures() {
   return res;
 }
 
+export async function promptResetConfig() {
+  if(confirm(t("reset_config_confirm"))) {
+    closeCfgMenu();
+    disableBeforeUnload();
+    await setDefaultFeatures();
+    if(location.pathname.startsWith("/watch")) {
+      const videoTime = await getVideoTime(0);
+      const url = new URL(location.href);
+      url.searchParams.delete("t");
+      if(videoTime)
+        url.searchParams.set("t", String(videoTime));
+      location.replace(url.href);
+    }
+    else
+      location.reload();
+  }
+}
+
 /** Clears the feature config from the persistent storage - since the cache will be out of whack, this should only be run before a site re-/unload */
 export async function clearConfig() {
   await cfgDataStore.deleteData();