mirror of
https://github.com/SoPat712/videospeed.git
synced 2026-04-27 14:42:51 -04:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
1a7dc3097e
|
|||
|
c626aca89c
|
|||
|
05b8456e94
|
|||
|
0cbfac4b82
|
|||
|
b3707c0803
|
|||
|
fb25c56230
|
|||
|
4efc3e0acc
|
|||
|
7c0a188cd3
|
|||
|
d7ce1fd000
|
|||
|
313832015b
|
+1
-1
@@ -12,7 +12,7 @@ function exportSettings() {
|
|||||||
chrome.storage.local.get(null, function (localStorage) {
|
chrome.storage.local.get(null, function (localStorage) {
|
||||||
const backup = importExportUtils.buildBackupPayload(
|
const backup = importExportUtils.buildBackupPayload(
|
||||||
storage,
|
storage,
|
||||||
localStorage,
|
importExportUtils.filterLocalSettingsForExport(localStorage),
|
||||||
new Date()
|
new Date()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "Speeder",
|
"name": "Speeder",
|
||||||
"short_name": "Speeder",
|
"short_name": "Speeder",
|
||||||
"version": "5.2.2.0",
|
"version": "5.2.4",
|
||||||
"manifest_version": 2,
|
"manifest_version": 2,
|
||||||
"description": "Speed up, slow down, advance and rewind HTML5 audio/video with shortcuts (New and improved version of \"Video Speed Controller\")",
|
"description": "Speed up, slow down, advance and rewind HTML5 audio/video with shortcuts (New and improved version of \"Video Speed Controller\")",
|
||||||
"homepage_url": "https://github.com/SoPat712/speeder",
|
"homepage_url": "https://github.com/SoPat712/speeder",
|
||||||
|
|||||||
@@ -46,6 +46,29 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Local-only keys excluded from backup JSON. These are disposable caches
|
||||||
|
* (e.g. Lucide tags.json) that bloat exports and are refetched when needed.
|
||||||
|
* Keep in sync with lucide-client.js (LUCIDE_TAGS_CACHE_KEY + "At").
|
||||||
|
*/
|
||||||
|
var localSettingsKeysOmittedFromExport = [
|
||||||
|
"lucideTagsCacheV1",
|
||||||
|
"lucideTagsCacheV1At"
|
||||||
|
];
|
||||||
|
|
||||||
|
function filterLocalSettingsForExport(local) {
|
||||||
|
if (!local || typeof local !== "object" || Array.isArray(local)) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
var out = {};
|
||||||
|
for (var key in local) {
|
||||||
|
if (!Object.prototype.hasOwnProperty.call(local, key)) continue;
|
||||||
|
if (localSettingsKeysOmittedFromExport.indexOf(key) !== -1) continue;
|
||||||
|
out[key] = local[key];
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
function generateBackupFilename(now) {
|
function generateBackupFilename(now) {
|
||||||
var date = now instanceof Date ? now : new Date(now || Date.now());
|
var date = now instanceof Date ? now : new Date(now || Date.now());
|
||||||
var year = date.getFullYear();
|
var year = date.getFullYear();
|
||||||
@@ -117,6 +140,7 @@
|
|||||||
return {
|
return {
|
||||||
buildBackupPayload: buildBackupPayload,
|
buildBackupPayload: buildBackupPayload,
|
||||||
extractImportSettings: extractImportSettings,
|
extractImportSettings: extractImportSettings,
|
||||||
|
filterLocalSettingsForExport: filterLocalSettingsForExport,
|
||||||
generateBackupFilename: generateBackupFilename,
|
generateBackupFilename: generateBackupFilename,
|
||||||
isRecognizedRawSettingsObject: isRecognizedRawSettingsObject,
|
isRecognizedRawSettingsObject: isRecognizedRawSettingsObject,
|
||||||
parseImportText: parseImportText
|
parseImportText: parseImportText
|
||||||
|
|||||||
@@ -79,6 +79,54 @@ describe("import/export flows", () => {
|
|||||||
window.Blob = OriginalBlob;
|
window.Blob = OriginalBlob;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("export strips lucideTagsCacheV1 from localSettings", async () => {
|
||||||
|
vi.useFakeTimers();
|
||||||
|
vi.setSystemTime(new Date(2026, 3, 4, 8, 9, 10));
|
||||||
|
await setupImportExport({
|
||||||
|
sync: { rememberSpeed: true },
|
||||||
|
local: {
|
||||||
|
customButtonIcons: { faster: { slug: "rocket", svg: "<svg/>" } },
|
||||||
|
lucideTagsCacheV1: { "a-arrow-down": ["letter"] },
|
||||||
|
lucideTagsCacheV1At: 42
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const OriginalBlob = window.Blob;
|
||||||
|
class TestBlob {
|
||||||
|
constructor(parts) {
|
||||||
|
this.parts = parts;
|
||||||
|
}
|
||||||
|
async text() {
|
||||||
|
return this.parts.join("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
globalThis.Blob = TestBlob;
|
||||||
|
window.Blob = TestBlob;
|
||||||
|
let capturedBlob = null;
|
||||||
|
Object.defineProperty(window.URL, "createObjectURL", {
|
||||||
|
configurable: true,
|
||||||
|
value: vi.fn((blob) => {
|
||||||
|
capturedBlob = blob;
|
||||||
|
return "blob:test";
|
||||||
|
})
|
||||||
|
});
|
||||||
|
Object.defineProperty(window.URL, "revokeObjectURL", {
|
||||||
|
configurable: true,
|
||||||
|
value: vi.fn(() => {})
|
||||||
|
});
|
||||||
|
vi.spyOn(window.HTMLAnchorElement.prototype, "click").mockImplementation(
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
|
||||||
|
document.getElementById("exportSettings").click();
|
||||||
|
await flushAsyncWork();
|
||||||
|
|
||||||
|
expect(JSON.parse(await capturedBlob.text()).localSettings).toEqual({
|
||||||
|
customButtonIcons: { faster: { slug: "rocket", svg: "<svg/>" } }
|
||||||
|
});
|
||||||
|
globalThis.Blob = OriginalBlob;
|
||||||
|
window.Blob = OriginalBlob;
|
||||||
|
});
|
||||||
|
|
||||||
it("imports wrapped backup payloads and refreshes options", async () => {
|
it("imports wrapped backup payloads and refreshes options", async () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
const chrome = await setupImportExport();
|
const chrome = await setupImportExport();
|
||||||
|
|||||||
@@ -87,6 +87,36 @@ describe("importExport.js", () => {
|
|||||||
expect(document.querySelector("#status").textContent).toContain("exported");
|
expect(document.querySelector("#status").textContent).toContain("exported");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("omits Lucide tags cache from exported localSettings", async () => {
|
||||||
|
vi.spyOn(window.HTMLAnchorElement.prototype, "click").mockImplementation(
|
||||||
|
() => {}
|
||||||
|
);
|
||||||
|
const { createObjectURL } = bootImportExport({
|
||||||
|
syncData: { rememberSpeed: true },
|
||||||
|
localData: {
|
||||||
|
customButtonIcons: {
|
||||||
|
faster: { slug: "rocket", svg: "<svg></svg>" }
|
||||||
|
},
|
||||||
|
lucideTagsCacheV1: { "a-arrow-down": ["letter", "text"] },
|
||||||
|
lucideTagsCacheV1At: 999
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector("#exportSettings").click();
|
||||||
|
await flushAsyncWork();
|
||||||
|
|
||||||
|
const blob = createObjectURL.mock.calls[0][0];
|
||||||
|
const backup = JSON.parse(await blob.text());
|
||||||
|
|
||||||
|
expect(backup.localSettings).toEqual({
|
||||||
|
customButtonIcons: {
|
||||||
|
faster: { slug: "rocket", svg: "<svg></svg>" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
expect(backup.localSettings.lucideTagsCacheV1).toBeUndefined();
|
||||||
|
expect(backup.localSettings.lucideTagsCacheV1At).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
it("imports wrapped backups, restores local data, and refreshes the options page", async () => {
|
it("imports wrapped backups, restores local data, and refreshes the options page", async () => {
|
||||||
const { chrome } = bootImportExport();
|
const { chrome } = bootImportExport();
|
||||||
window.restore_options = vi.fn();
|
window.restore_options = vi.fn();
|
||||||
|
|||||||
@@ -149,5 +149,15 @@ describe("shared helpers", () => {
|
|||||||
expect(importExportUtils.isRecognizedRawSettingsObject({ wat: true })).toBe(
|
expect(importExportUtils.isRecognizedRawSettingsObject({ wat: true })).toBe(
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
expect(
|
||||||
|
importExportUtils.filterLocalSettingsForExport({
|
||||||
|
customButtonIcons: { faster: { slug: "zap" } },
|
||||||
|
lucideTagsCacheV1: { "a-arrow-down": ["letter"] },
|
||||||
|
lucideTagsCacheV1At: 123
|
||||||
|
})
|
||||||
|
).toEqual({
|
||||||
|
customButtonIcons: { faster: { slug: "zap" } }
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user