web/settings: move migration to separate file, rename v7 migration

This commit is contained in:
jj 2024-10-30 12:42:48 +00:00
parent 44f842997e
commit b125894b7e
No known key found for this signature in database
3 changed files with 144 additions and 136 deletions

View file

@ -0,0 +1,109 @@
import type { AllPartialSettingsWithSchema } from "$lib/types/settings";
const oldSwitcherValues = {
theme: ['auto', 'light', 'dark'],
vCodec: ['h264', 'av1', 'vp9'],
vQuality: ['720', 'max', '2160', '1440', '1080', '480', '360', '240', '144'],
aFormat: ['mp3', 'best', 'ogg', 'wav', 'opus'],
filenamePattern: ['classic', 'pretty', 'basic', 'nerdy']
} as const;
const oldCheckboxes = [
'audioMode',
'fullTikTokAudio',
'muteAudio',
'reduceTransparency',
'disableAnimations',
'disableMetadata',
'plausible_ignore',
'ytDub',
'tiktokH265'
] as const;
type LegacySwitchers = keyof typeof oldSwitcherValues;
type LegacyCheckboxes = typeof oldCheckboxes[number];
const _get = (name: LegacyCheckboxes | LegacySwitchers) => {
const value = localStorage.getItem(name);
if (value !== null) {
return value;
}
}
const getBool = (name: LegacyCheckboxes) => {
const value = _get(name);
if (value !== undefined) {
return value === 'true';
}
}
const getLiteral = <T extends LegacySwitchers>(name: T) => {
const value = _get(name);
if (value === undefined) {
return;
}
const values = oldSwitcherValues[name] as readonly string[];
if (values.includes(value)) {
type SwitcherOptions = typeof oldSwitcherValues[T][number];
return value as SwitcherOptions;
}
}
const getDownloadMode = () => {
if (getBool('muteAudio')) {
return 'mute';
}
if (getBool('audioMode')) {
return 'audio';
}
return 'auto';
}
const cleanup = () => {
for (const key of Object.keys(localStorage)) {
// plausible script needs this value, so we keep it if migrating
if (key !== 'plausible_ignore') {
localStorage.removeItem(key);
}
}
}
export const migrateOldSettings = () => {
if (getLiteral('vCodec') === undefined) {
/* on the old frontend, preferences such as "vCodec" are set right
* when you open it. so, if this preference does not exist, we can
* assume that the user never used the old frontend, and abort the
* migration early. */
return;
}
const migrated: AllPartialSettingsWithSchema = {
schemaVersion: 2,
appearance: {
theme: getLiteral('theme'),
reduceTransparency: getBool('reduceTransparency'),
reduceMotion: getBool('disableAnimations'),
},
privacy: {
disableAnalytics: getBool('plausible_ignore')
},
save: {
youtubeVideoCodec: getLiteral('vCodec'),
videoQuality: getLiteral('vQuality'),
audioFormat: getLiteral('aFormat'),
downloadMode: getDownloadMode(),
filenameStyle: getLiteral('filenamePattern'),
tiktokFullAudio: getBool('fullTikTokAudio'),
tiktokH265: getBool('tiktokH265'),
disableMetadata: getBool('disableMetadata'),
youtubeDubBrowserLang: getBool('ytDub'),
}
};
cleanup();
return migrated;
}

View file

@ -1,109 +1,38 @@
import type { AllPartialSettingsWithSchema } from "$lib/types/settings";
import type { RecursivePartial } from "$lib/types/generic";
import type {
AllPartialSettingsWithSchema,
CobaltSettingsV3,
PartialSettings,
} from "$lib/types/settings";
import { getBrowserLanguage } from "$lib/settings/youtube-lang";
const oldSwitcherValues = {
theme: ['auto', 'light', 'dark'],
vCodec: ['h264', 'av1', 'vp9'],
vQuality: ['720', 'max', '2160', '1440', '1080', '480', '360', '240', '144'],
aFormat: ['mp3', 'best', 'ogg', 'wav', 'opus'],
filenamePattern: ['classic', 'pretty', 'basic', 'nerdy']
} as const;
type Migrator = (
s: AllPartialSettingsWithSchema
) => AllPartialSettingsWithSchema;
const migrations: Record<number, Migrator> = {
[3]: (settings: AllPartialSettingsWithSchema) => {
const out = settings as RecursivePartial<CobaltSettingsV3>;
out.schemaVersion = 3;
const oldCheckboxes = [
'audioMode',
'fullTikTokAudio',
'muteAudio',
'reduceTransparency',
'disableAnimations',
'disableMetadata',
'plausible_ignore',
'ytDub',
'tiktokH265'
] as const;
if (settings?.save && "youtubeDubBrowserLang" in settings.save) {
if (settings.save.youtubeDubBrowserLang) {
out.save!.youtubeDubLang = getBrowserLanguage();
}
type LegacySwitchers = keyof typeof oldSwitcherValues;
type LegacyCheckboxes = typeof oldCheckboxes[number];
const _get = (name: LegacyCheckboxes | LegacySwitchers) => {
const value = localStorage.getItem(name);
if (value !== null) {
return value;
}
}
const getBool = (name: LegacyCheckboxes) => {
const value = _get(name);
if (value !== undefined) {
return value === 'true';
}
}
const getLiteral = <T extends LegacySwitchers>(name: T) => {
const value = _get(name);
if (value === undefined) {
return;
delete settings.save.youtubeDubBrowserLang;
}
const values = oldSwitcherValues[name] as readonly string[];
if (values.includes(value)) {
type SwitcherOptions = typeof oldSwitcherValues[T][number];
return value as SwitcherOptions;
}
}
return out as AllPartialSettingsWithSchema;
},
};
const getDownloadMode = () => {
if (getBool('muteAudio')) {
return 'mute';
}
if (getBool('audioMode')) {
return 'audio';
}
return 'auto';
}
const cleanup = () => {
for (const key of Object.keys(localStorage)) {
// plausible script needs this value, so we keep it if migrating
if (key !== 'plausible_ignore') {
localStorage.removeItem(key);
}
}
}
export const migrateOldSettings = () => {
if (getLiteral('vCodec') === undefined) {
/* on the old frontend, preferences such as "vCodec" are set right
* when you open it. so, if this preference does not exist, we can
* assume that the user never used the old frontend, and abort the
* migration early. */
return;
}
const migrated: AllPartialSettingsWithSchema = {
schemaVersion: 2,
appearance: {
theme: getLiteral('theme'),
reduceTransparency: getBool('reduceTransparency'),
reduceMotion: getBool('disableAnimations'),
},
privacy: {
disableAnalytics: getBool('plausible_ignore')
},
save: {
youtubeVideoCodec: getLiteral('vCodec'),
videoQuality: getLiteral('vQuality'),
audioFormat: getLiteral('aFormat'),
downloadMode: getDownloadMode(),
filenameStyle: getLiteral('filenamePattern'),
tiktokFullAudio: getBool('fullTikTokAudio'),
tiktokH265: getBool('tiktokH265'),
disableMetadata: getBool('disableMetadata'),
youtubeDubBrowserLang: getBool('ytDub'),
}
};
cleanup();
return migrated;
}
export const migrate = (
settings: AllPartialSettingsWithSchema
): PartialSettings => {
return Object.keys(migrations)
.map(Number)
.filter((version) => version > settings.schemaVersion)
.reduce((settings, migrationVersion) => {
return migrations[migrationVersion](settings);
}, settings as AllPartialSettingsWithSchema) as PartialSettings;
};

View file

@ -4,13 +4,11 @@ import { merge } from 'ts-deepmerge';
import type {
PartialSettings,
AllPartialSettingsWithSchema,
CobaltSettings,
CobaltSettingsV3
CobaltSettings
} from '../types/settings';
import { getBrowserLanguage } from '$lib/settings/youtube-lang';
import { migrateOldSettings } from '../settings/migrate';
import { migrateOldSettings } from '../settings/migrate-v7';
import defaultSettings from '../settings/defaults';
import type { RecursivePartial } from '$lib/types/generic';
import { migrate } from '$lib/settings/migrate';
const updatePlausiblePreference = (settings: PartialSettings) => {
if (settings.privacy?.disableAnalytics) {
@ -29,34 +27,6 @@ const writeToStorage = (settings: PartialSettings) => {
return settings;
}
type Migrator = (s: AllPartialSettingsWithSchema) => AllPartialSettingsWithSchema;
const migrations: Record<number, Migrator> = {
[3]: (settings: AllPartialSettingsWithSchema) => {
const out = settings as RecursivePartial<CobaltSettingsV3>;
out.schemaVersion = 3;
if (settings?.save && 'youtubeDubBrowserLang' in settings.save) {
if (settings.save.youtubeDubBrowserLang) {
out.save!.youtubeDubLang = getBrowserLanguage();
}
delete settings.save.youtubeDubBrowserLang;
}
return out as AllPartialSettingsWithSchema;
}
}
const migrate = (settings: AllPartialSettingsWithSchema): PartialSettings => {
return Object.keys(migrations)
.map(Number)
.filter(version => version > settings.schemaVersion)
.reduce((settings, migrationVersion) => {
return migrations[migrationVersion](settings);
}, settings as AllPartialSettingsWithSchema) as PartialSettings;
}
const loadFromStorage = () => {
if (!browser)
return {};