1
0
mirror of https://github.com/XFox111/TabsAsideExtension.git synced 2026-04-22 07:58:01 +03:00

!feat: major 3.0 release candidate

This commit is contained in:
2025-05-03 23:59:43 +03:00
parent dbc8c7fd4d
commit 39793a38c3
143 changed files with 14277 additions and 0 deletions
@@ -0,0 +1,10 @@
import migrateLocalStorage from "../utils/migrateLocalStorage";
export default function useLocalMigration(): void
{
useEffect(() =>
{
if (globalThis.localStorage?.getItem("sets"))
migrateLocalStorage().then(() => document.location.reload());
}, []);
}
+2
View File
@@ -0,0 +1,2 @@
export { default as useLocalMigration } from "./hooks/useLocalMigration";
export { default as migrateStorage } from "./utils/migrateStorage";
+15
View File
@@ -0,0 +1,15 @@
export type LegacyCollection =
{
timestamp: number;
tabsCount: number;
titles: string[];
links: string[];
icons?: string[];
thumbnails?: string[];
};
export type LegacyGraphics =
{
pageCapture?: string;
iconUrl?: string;
};
@@ -0,0 +1,38 @@
import { CollectionItem, GraphicsStorage, TabItem } from "@/models/CollectionModels";
import { LegacyCollection } from "../models/LegacyModels";
export default function migrateCollections(legacyCollections: LegacyCollection[]): [CollectionItem[], GraphicsStorage]
{
const collections: CollectionItem[] = [];
const graphics: GraphicsStorage = {};
for (let i = 0; i < legacyCollections.length; i++)
{
const legacyCollection: LegacyCollection = legacyCollections[i];
const items: TabItem[] = legacyCollection.links.map((url, index) =>
{
const title: string | undefined = legacyCollection.titles[index];
const icon: string | undefined = legacyCollection.icons?.[index];
const preview: string | undefined = legacyCollection.thumbnails?.[index];
if (!graphics[url])
graphics[url] = { icon, preview };
else
graphics[url] = { icon: graphics[url].icon ?? icon, preview: graphics[url].preview ?? preview };
return {
type: "tab",
url,
title
};
});
collections.push({
type: "collection",
timestamp: legacyCollection.timestamp,
items
});
}
return [collections, graphics];
}
@@ -0,0 +1,18 @@
import { getCollections } from "@/features/collectionStorage";
import saveCollections from "@/features/collectionStorage/utils/saveCollections";
import { LegacyCollection } from "../models/LegacyModels";
import migrateCollections from "./migrateCollections";
export default async function migrateLocalStorage(): Promise<void>
{
// Retrieve v1 collections
const legacyCollections: LegacyCollection[] = JSON.parse(globalThis.localStorage?.getItem("sets") || "[]");
// Nuke localStorage
globalThis.localStorage?.clear();
// Migrate collections
const [resultCollections, resultGraphics] = migrateCollections(legacyCollections);
const [collections] = await getCollections();
await saveCollections([...collections, ...resultCollections], true, resultGraphics);
}
@@ -0,0 +1,60 @@
import { saveCollections } from "@/features/collectionStorage";
import { GraphicsStorage } from "@/models/CollectionModels";
import { settings } from "@/utils/settings";
import { decompress } from "lzutf8";
import { LegacyCollection, LegacyGraphics } from "../models/LegacyModels";
import migrateCollections from "./migrateCollections";
export default async function migrateStorage(): Promise<void>
{
// Retrieve settings
const loadOnRestore: boolean | null = await storage.getItem<boolean>("sync:loadOnRestore");
const setAsideOnClick: boolean | null = await storage.getItem<boolean>("sync:setAsideOnClick");
const showDeleteDialog: boolean | null = await storage.getItem<boolean>("sync:showDeleteDialog");
const listView: boolean | null = await storage.getItem<boolean>("sync:listview");
// Retrieve v2 collections
const legacyCollections: LegacyCollection[] = [];
Object.entries(await browser.storage.sync.get(null)).forEach(([key, value]) =>
{
if (key.startsWith("set_"))
legacyCollections.push({
...JSON.parse(decompress(value, { inputEncoding: "StorageBinaryString" })),
timestamp: parseInt(key.substring(4))
});
});
// Retrieve v2 graphics
const v2Graphics: Record<string, LegacyGraphics> = await storage.getItem("local:thumbnails") ?? {};
// Nuke everything
await browser.storage.local.clear();
await browser.storage.sync.clear();
// Migrate collections & graphics
const [collections] = migrateCollections(legacyCollections);
const graphics: GraphicsStorage = {};
for (const [key, record] of Object.entries(v2Graphics))
{
if (!graphics[key])
graphics[key] = { icon: record.iconUrl, preview: record.pageCapture };
else
{
graphics[key].icon ??= record.iconUrl;
graphics[key].preview ??= record.pageCapture;
}
}
await saveCollections(collections, true, graphics);
// Migrate settings
if (loadOnRestore !== null)
settings.dismissOnLoad.setValue(!loadOnRestore);
if (setAsideOnClick !== null)
settings.contextAction.setValue(setAsideOnClick ? "action" : "open");
if (showDeleteDialog !== null)
settings.deletePrompt.setValue(showDeleteDialog);
if (listView !== null)
settings.tilesView.setValue(!listView);
}