From 6cf2dd98486a3089e48b160414c3344bb215d7aa Mon Sep 17 00:00:00 2001 From: L&H Date: Thu, 30 Nov 2023 16:27:15 +0800 Subject: [PATCH] feat: migrate web storage to chrome storage --- src/scripts/background/start-changelog.ts | 23 +++----- src/scripts/options.ts | 21 +++---- src/scripts/popup.ts | 37 +++++++----- src/scripts/sharre/chrome-storage.ts | 72 +++++++++++++++++++++++ src/scripts/sharre/constant.ts | 21 +------ 5 files changed, 113 insertions(+), 61 deletions(-) create mode 100644 src/scripts/sharre/chrome-storage.ts diff --git a/src/scripts/background/start-changelog.ts b/src/scripts/background/start-changelog.ts index c7b1362..0f84a21 100644 --- a/src/scripts/background/start-changelog.ts +++ b/src/scripts/background/start-changelog.ts @@ -1,4 +1,5 @@ -import { K_AUTO_DISPLAY_CHANGELOG, PConfig } from "../sharre/constant.js"; +import { K_AUTO_DISPLAY_CHANGELOG } from "../sharre/constant.js"; +import { chromeStorageSync } from "../sharre/chrome-storage.js"; /** * Changelog @@ -20,18 +21,12 @@ chrome.runtime.onInstalled.addListener((details) => { return; } } - chrome.storage.sync.get( - { - [K_AUTO_DISPLAY_CHANGELOG]: PConfig.defaultOptions.autoDisplayChangelog, - }, - (items) => { - if (chrome.runtime.lastError) return; - if (items[K_AUTO_DISPLAY_CHANGELOG]) { - chrome.tabs.create({ - url: chrome.i18n.getMessage("project_changelog"), - }); - } - }, - ); + chromeStorageSync.promise.then((items) => { + if (items[K_AUTO_DISPLAY_CHANGELOG]) { + chrome.tabs.create({ + url: chrome.i18n.getMessage("project_changelog"), + }); + } + }); } }); diff --git a/src/scripts/options.ts b/src/scripts/options.ts index ea294c6..b83848f 100644 --- a/src/scripts/options.ts +++ b/src/scripts/options.ts @@ -6,6 +6,7 @@ import { K_KEEP_LAST_SEARCH_STATUS, ChromeExtensionType, } from "./sharre/constant.js"; +import { chromeStorageSync } from "./sharre/chrome-storage.js"; /** * @desc i18n @@ -26,23 +27,15 @@ function setOptionsItem(node: HTMLInputElement, items: Record, key: }); } -chrome.storage.sync.get( - { - [K_AUTO_DISPLAY_CHANGELOG]: PConfig.defaultOptions.autoDisplayChangelog, - [K_KEEP_LAST_SEARCH_STATUS]: PConfig.defaultOptions.keepLastSearchStatus, - }, - (items) => { - if (chrome.runtime.lastError) return; - setOptionsItem(document.querySelector(`input[value="update_details"]`), items, K_AUTO_DISPLAY_CHANGELOG); - setOptionsItem(document.querySelector(`input[value="search_status"]`), items, K_KEEP_LAST_SEARCH_STATUS); - }, -); +chromeStorageSync.promise.then((items) => { + setOptionsItem(document.querySelector(`input[value="update_details"]`), items, K_AUTO_DISPLAY_CHANGELOG); + setOptionsItem(document.querySelector(`input[value="search_status"]`), items, K_KEEP_LAST_SEARCH_STATUS); +}); /** * @desc 配置数据同步 */ -chrome.storage.sync.get(K_EXTENSION_TYPE_CHECKED, (items) => { - if (chrome.runtime.lastError) return; +chromeStorageSync.promise.then((items) => { const eTypeChecked = Object.assign(PConfig.eTypeChecked, items[K_EXTENSION_TYPE_CHECKED]); for (const [type, checked] of Object.entries(eTypeChecked)) { const node = document.querySelector(`input[value="${type}"]`); @@ -52,7 +45,7 @@ chrome.storage.sync.get(K_EXTENSION_TYPE_CHECKED, (items) => { node.disabled = disabled; node.addEventListener("click", (e) => { if (!disabled) { - eTypeChecked[type] = node.checked; + eTypeChecked[type as ChromeExtensionType] = node.checked; chrome.storage.sync.set({ [K_EXTENSION_TYPE_CHECKED]: eTypeChecked, }); diff --git a/src/scripts/popup.ts b/src/scripts/popup.ts index 0e457a1..49efdbe 100644 --- a/src/scripts/popup.ts +++ b/src/scripts/popup.ts @@ -5,6 +5,7 @@ import { K_LAST_SEARCH_USER_INPUT, PConfig, } from "./sharre/constant.js"; +import { chromeStorageLocal, chromeStorageSync } from "./sharre/chrome-storage.js"; class ExtensionManager { excludeTypeSet: Set; @@ -37,35 +38,43 @@ class ExtensionManager { } async init() { - this.getLastSearchUserInput(); - this.getDisabledExtensionIds(); + await this.getLastSearchUserInput(); + await this.getDisabledExtensionIds(); await this.renderFrameContent(); this.registerAutoFocusEvent(); this.registerUserInputEvent(); this.registerOtherEvents(); } - getLastSearchUserInput() { + async getLastSearchUserInput() { if (this.enableLastSearchStatus) { - const data = localStorage.getItem(K_LAST_SEARCH_USER_INPUT); - if (typeof data === "string") { - this.lastSearchUserInput = data; - } + chromeStorageLocal.promise.then((items) => { + const data = items[K_LAST_SEARCH_USER_INPUT]; + if (typeof data === "string") { + this.lastSearchUserInput = data; + } + }); } } setLastSearchUserInput() { - localStorage.setItem(K_LAST_SEARCH_USER_INPUT, this.lastSearchUserInput); + chromeStorageLocal.set({ + [K_LAST_SEARCH_USER_INPUT]: this.lastSearchUserInput, + }); } - getDisabledExtensionIds() { - const data = localStorage.getItem(K_DISABLED_EXTENSION_ID); - const list = data ? data.split(",") : []; - list.forEach((id) => this.disabledExtensionIdSet.add(id)); + async getDisabledExtensionIds() { + return chromeStorageLocal.promise.then((items) => { + const data = items[K_DISABLED_EXTENSION_ID]; + const list = data ? data.split(",") : []; + list.forEach((id) => this.disabledExtensionIdSet.add(id)); + }); } setDisabledExtensionIds() { - localStorage.setItem(K_DISABLED_EXTENSION_ID, Array.from(this.disabledExtensionIdSet).join(",")); + chromeStorageLocal.set({ + [K_DISABLED_EXTENSION_ID]: Array.from(this.disabledExtensionIdSet).join(","), + }); } resetContainerContents() { @@ -328,7 +337,7 @@ class ExtensionManager { } } -chrome.storage.sync.get([K_EXTENSION_TYPE_CHECKED, K_KEEP_LAST_SEARCH_STATUS], (items) => { +chromeStorageSync.promise.then((items) => { const excludeTypeSet: Set = new Set(); const eTypeChecked = Object.assign(PConfig.eTypeChecked, items[K_EXTENSION_TYPE_CHECKED]); const enableLastSearchStatus = Boolean( diff --git a/src/scripts/sharre/chrome-storage.ts b/src/scripts/sharre/chrome-storage.ts new file mode 100644 index 0000000..d76b41c --- /dev/null +++ b/src/scripts/sharre/chrome-storage.ts @@ -0,0 +1,72 @@ +import { + ChromeExtensionType, + K_AUTO_DISPLAY_CHANGELOG, + K_DISABLED_EXTENSION_ID, + K_EXTENSION_TYPE_CHECKED, + K_KEEP_LAST_SEARCH_STATUS, + K_LAST_SEARCH_USER_INPUT, + PConfig, +} from "./constant.js"; + +interface IChromeStorageLocalInfo { + [K_DISABLED_EXTENSION_ID]: string; + [K_LAST_SEARCH_USER_INPUT]: string; +} + +interface IChromeStorageSyncInfo { + [K_EXTENSION_TYPE_CHECKED]: Record; + [K_AUTO_DISPLAY_CHANGELOG]: boolean; + [K_KEEP_LAST_SEARCH_STATUS]: boolean; +} + +const SADCache = new Map(); + +async function initializeStorageArea(areaName: chrome.storage.AreaName, keys?: unknown): Promise { + const promise = chrome.storage[areaName].get(keys) as Promise; + promise.then((data) => SADCache.set(areaName, data)); + return promise; +} + +chrome.storage.onChanged.addListener((changes, areaName) => { + const data: Record = SADCache.get(areaName) || Object.create(null); + + for (let [key, { oldValue, newValue }] of Object.entries(changes)) { + data[key] = newValue; + } + + SADCache.set(areaName, data); +}); + +class ChromeStorageArea { + readonly __initPromise: Promise; + + get promise(): Promise { + if (SADCache.has(this.areaName)) { + return Promise.resolve(SADCache.get(this.areaName)) as Promise; + } else { + return this.__initPromise; + } + } + + constructor( + readonly areaName: chrome.storage.AreaName, + keys?: Partial, + ) { + this.__initPromise = initializeStorageArea(this.areaName, keys); + } + + get(): T { + return (SADCache.get(this.areaName) || Object.create(null)) as T; + } + + set(items: Partial): Promise { + return chrome.storage[this.areaName].set(items); + } +} + +export const chromeStorageLocal = new ChromeStorageArea("local"); + +export const chromeStorageSync = new ChromeStorageArea("sync", { + [K_AUTO_DISPLAY_CHANGELOG]: PConfig.defaultOptions.autoDisplayChangelog, + [K_KEEP_LAST_SEARCH_STATUS]: PConfig.defaultOptions.keepLastSearchStatus, +}); diff --git a/src/scripts/sharre/constant.ts b/src/scripts/sharre/constant.ts index 7c4a68d..1ee6c76 100644 --- a/src/scripts/sharre/constant.ts +++ b/src/scripts/sharre/constant.ts @@ -1,34 +1,17 @@ /** - * @desc chrome.StorageArea + * @desc chrome.StorageArea.sync */ export const K_EXTENSION_TYPE_CHECKED = "extension_type_checked"; // 用于存储扩展类型的状态 export const K_AUTO_DISPLAY_CHANGELOG = "auto_display_changelog"; export const K_KEEP_LAST_SEARCH_STATUS = "keep_last_search_status"; -/** - * chrome.StorageArea schema - */ -interface ChromeStorageArea { - [K_EXTENSION_TYPE_CHECKED]: Record; - [K_AUTO_DISPLAY_CHANGELOG]: boolean; - [K_KEEP_LAST_SEARCH_STATUS]: boolean; -} - /** * @desc for `popup` page - * @desc localStorage/sessionStorage + * @desc chrome.StorageArea.local */ export const K_DISABLED_EXTENSION_ID = "disabled_extension_id"; // 用于存储被批量方式禁用的扩展ID export const K_LAST_SEARCH_USER_INPUT = "last_search_user_input"; -/** - * localStorage schema - */ -interface WebLocalStorage { - [K_DISABLED_EXTENSION_ID]: string; - [K_LAST_SEARCH_USER_INPUT]: string; -} - /** * @enum * @see https://developer.chrome.com/extensions/management#type-ExtensionType