Restructure the storage files.
This commit is contained in:
parent
d7ddbe4620
commit
df09098f89
|
@ -1,6 +1,6 @@
|
||||||
import {offset, type Offset} from "caret-pos";
|
import {offset, type Offset} from "caret-pos";
|
||||||
import {Component} from "preact";
|
import {Component} from "preact";
|
||||||
import {type UserLabelsData} from "../../storage/common.js";
|
import {type UserLabelsData} from "../../storage/exports.js";
|
||||||
import {log, querySelectorAll} from "../../utilities/exports.js";
|
import {log, querySelectorAll} from "../../utilities/exports.js";
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {type HideVotesData} from "../../storage/common.js";
|
import {type HideVotesData} from "../../storage/exports.js";
|
||||||
import {log, querySelectorAll} from "../../utilities/exports.js";
|
import {log, querySelectorAll} from "../../utilities/exports.js";
|
||||||
|
|
||||||
export function runHideVotesFeature(data: HideVotesData) {
|
export function runHideVotesFeature(data: HideVotesData) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
type UserLabelsData,
|
type UserLabelsData,
|
||||||
createValueUserLabel,
|
createValueUserLabel,
|
||||||
saveUserLabels,
|
saveUserLabels,
|
||||||
} from "../../storage/common.js";
|
} from "../../storage/exports.js";
|
||||||
import {
|
import {
|
||||||
createElementFromString,
|
createElementFromString,
|
||||||
isColorBright,
|
isColorBright,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {log, querySelectorAll} from "../../utilities/exports.js";
|
import {log, querySelectorAll} from "../../utilities/exports.js";
|
||||||
import {type UsernameColorsData} from "../../storage/common.js";
|
import {type UsernameColorsData} from "../../storage/exports.js";
|
||||||
|
|
||||||
export function runUsernameColorsFeature(
|
export function runUsernameColorsFeature(
|
||||||
data: UsernameColorsData,
|
data: UsernameColorsData,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import {type JSX, render} from "preact";
|
import {type JSX, render} from "preact";
|
||||||
import {extractGroups, initializeGlobals, log} from "../utilities/exports.js";
|
import {extractGroups, initializeGlobals, log} from "../utilities/exports.js";
|
||||||
import {Feature, fromStorage, Data} from "../storage/common.js";
|
import {Feature, fromStorage, Data} from "../storage/exports.js";
|
||||||
import {
|
import {
|
||||||
AutocompleteFeature,
|
AutocompleteFeature,
|
||||||
BackToTopFeature,
|
BackToTopFeature,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import {
|
||||||
fromStorage,
|
fromStorage,
|
||||||
Feature,
|
Feature,
|
||||||
type HideVotesData,
|
type HideVotesData,
|
||||||
} from "../../storage/common.js";
|
} from "../../storage/exports.js";
|
||||||
import {Setting, type SettingProps} from "./index.js";
|
import {Setting, type SettingProps} from "./index.js";
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import {Component, type ComponentChildren, type JSX} from "preact";
|
||||||
// eslint-disable-next-line n/file-extension-in-import
|
// eslint-disable-next-line n/file-extension-in-import
|
||||||
import {useContext} from "preact/hooks";
|
import {useContext} from "preact/hooks";
|
||||||
import {AppContext} from "../context.js";
|
import {AppContext} from "../context.js";
|
||||||
import {type Feature} from "../../storage/common.js";
|
import {type Feature} from "../../storage/exports.js";
|
||||||
|
|
||||||
export type SettingProps = {
|
export type SettingProps = {
|
||||||
children: ComponentChildren;
|
children: ComponentChildren;
|
||||||
|
|
|
@ -6,7 +6,7 @@ import {
|
||||||
type UsernameColor,
|
type UsernameColor,
|
||||||
Feature,
|
Feature,
|
||||||
fromStorage,
|
fromStorage,
|
||||||
} from "../../storage/common.js";
|
} from "../../storage/exports.js";
|
||||||
import {Setting, type SettingProps} from "./index.js";
|
import {Setting, type SettingProps} from "./index.js";
|
||||||
|
|
||||||
type State = {
|
type State = {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import {createContext} from "preact";
|
import {createContext} from "preact";
|
||||||
import {type Feature} from "../storage/common.js";
|
import {type Feature} from "../storage/exports.js";
|
||||||
|
|
||||||
type AppContextValues = {
|
type AppContextValues = {
|
||||||
setActiveFeature: (feature: Feature) => void;
|
setActiveFeature: (feature: Feature) => void;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {Feature} from "../storage/common.js";
|
import {Feature} from "../storage/exports.js";
|
||||||
import {
|
import {
|
||||||
AboutSetting,
|
AboutSetting,
|
||||||
AnonymizeUsernamesSetting,
|
AnonymizeUsernamesSetting,
|
||||||
|
|
|
@ -7,7 +7,7 @@ import {
|
||||||
createReportTemplate,
|
createReportTemplate,
|
||||||
initializeGlobals,
|
initializeGlobals,
|
||||||
} from "../utilities/exports.js";
|
} from "../utilities/exports.js";
|
||||||
import {type Feature, Data, fromStorage} from "../storage/common.js";
|
import {type Feature, Data, fromStorage} from "../storage/exports.js";
|
||||||
import {AppContext} from "./context.js";
|
import {AppContext} from "./context.js";
|
||||||
import {features} from "./features.js";
|
import {features} from "./features.js";
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ import {
|
||||||
Feature,
|
Feature,
|
||||||
createValueUserLabel,
|
createValueUserLabel,
|
||||||
saveUserLabels,
|
saveUserLabels,
|
||||||
} from "../storage/common.js";
|
} from "../storage/exports.js";
|
||||||
import "../scss/index.scss";
|
import "../scss/index.scss";
|
||||||
import "../scss/user-label-editor.scss";
|
import "../scss/user-label-editor.scss";
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
export enum Feature {
|
||||||
|
AnonymizeUsernames = "anonymize-usernames",
|
||||||
|
Autocomplete = "autocomplete",
|
||||||
|
BackToTop = "back-to-top",
|
||||||
|
Debug = "debug",
|
||||||
|
HideVotes = "hide-votes",
|
||||||
|
JumpToNewComment = "jump-to-new-comment",
|
||||||
|
MarkdownToolbar = "markdown-toolbar",
|
||||||
|
ThemedLogo = "themed-logo",
|
||||||
|
UserLabels = "user-labels",
|
||||||
|
UsernameColors = "username-colors",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Data {
|
||||||
|
EnabledFeatures = "enabled-features",
|
||||||
|
KnownGroups = "known-groups",
|
||||||
|
LatestActiveFeatureTab = "latest-active-feature-tab",
|
||||||
|
Version = "data-version",
|
||||||
|
}
|
|
@ -1,25 +1,10 @@
|
||||||
import {createValue, type Value} from "@holllo/webextension-storage";
|
import {createValue, type Value} from "@holllo/webextension-storage";
|
||||||
import browser from "webextension-polyfill";
|
import browser from "webextension-polyfill";
|
||||||
|
import {collectUserLabels} from "./user-label.js";
|
||||||
|
import {Data, Feature} from "./enums.js";
|
||||||
|
|
||||||
export enum Feature {
|
export * from "./user-label.js";
|
||||||
AnonymizeUsernames = "anonymize-usernames",
|
export * from "./enums.js";
|
||||||
Autocomplete = "autocomplete",
|
|
||||||
BackToTop = "back-to-top",
|
|
||||||
Debug = "debug",
|
|
||||||
HideVotes = "hide-votes",
|
|
||||||
JumpToNewComment = "jump-to-new-comment",
|
|
||||||
MarkdownToolbar = "markdown-toolbar",
|
|
||||||
ThemedLogo = "themed-logo",
|
|
||||||
UserLabels = "user-labels",
|
|
||||||
UsernameColors = "username-colors",
|
|
||||||
}
|
|
||||||
|
|
||||||
export enum Data {
|
|
||||||
EnabledFeatures = "enabled-features",
|
|
||||||
KnownGroups = "known-groups",
|
|
||||||
LatestActiveFeatureTab = "latest-active-feature-tab",
|
|
||||||
Version = "data-version",
|
|
||||||
}
|
|
||||||
|
|
||||||
export type HideVotesData = {
|
export type HideVotesData = {
|
||||||
otherComments: boolean;
|
otherComments: boolean;
|
||||||
|
@ -28,16 +13,6 @@ export type HideVotesData = {
|
||||||
ownTopics: boolean;
|
ownTopics: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UserLabel = {
|
|
||||||
color: string;
|
|
||||||
id: number;
|
|
||||||
priority: number;
|
|
||||||
text: string;
|
|
||||||
username: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type UserLabelsData = Array<Value<UserLabel>>;
|
|
||||||
|
|
||||||
export type UsernameColor = {
|
export type UsernameColor = {
|
||||||
color: string;
|
color: string;
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -46,56 +21,6 @@ export type UsernameColor = {
|
||||||
|
|
||||||
export type UsernameColorsData = UsernameColor[];
|
export type UsernameColorsData = UsernameColor[];
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a {@link Value}-wrapped {@link UserLabel}.
|
|
||||||
*/
|
|
||||||
export async function createValueUserLabel(
|
|
||||||
userLabel: UserLabel,
|
|
||||||
): Promise<UserLabelsData[number]> {
|
|
||||||
return createValue<UserLabel>({
|
|
||||||
deserialize: (input) => JSON.parse(input) as UserLabel,
|
|
||||||
serialize: (input) => JSON.stringify(input),
|
|
||||||
key: `${Feature.UserLabels}-${userLabel.id}`,
|
|
||||||
value: userLabel,
|
|
||||||
storage: browser.storage.sync,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all user labels from storage and combine them into a single array.
|
|
||||||
*/
|
|
||||||
export async function collectUserLabels(): Promise<UserLabelsData> {
|
|
||||||
const storage = await browser.storage.sync.get();
|
|
||||||
const userLabels = [];
|
|
||||||
for (const [key, value] of Object.entries(storage)) {
|
|
||||||
if (!key.startsWith(Feature.UserLabels)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
userLabels.push(
|
|
||||||
await createValueUserLabel(JSON.parse(value as string) as UserLabel),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return userLabels;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Save all user labels to storage under individual keys.
|
|
||||||
*
|
|
||||||
* They are stored under individual keys so that we don't run into storage quota
|
|
||||||
* limits. If it was stored under a single key we would only be able to fit
|
|
||||||
* around 80-100 labels before hitting the limit.
|
|
||||||
* @param userLabels The user labels array to save.
|
|
||||||
*/
|
|
||||||
export async function saveUserLabels(
|
|
||||||
userLabels: UserLabelsData,
|
|
||||||
): Promise<void> {
|
|
||||||
for (const label of userLabels) {
|
|
||||||
await label.save();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const storageValues = {
|
export const storageValues = {
|
||||||
[Data.EnabledFeatures]: createValue({
|
[Data.EnabledFeatures]: createValue({
|
||||||
deserialize: (input) => new Set(JSON.parse(input) as Feature[]),
|
deserialize: (input) => new Set(JSON.parse(input) as Feature[]),
|
||||||
|
@ -137,7 +62,6 @@ export const storageValues = {
|
||||||
},
|
},
|
||||||
storage: browser.storage.sync,
|
storage: browser.storage.sync,
|
||||||
}),
|
}),
|
||||||
// eslint-disable-next-line unicorn/prefer-top-level-await
|
|
||||||
[Feature.UserLabels]: collectUserLabels(),
|
[Feature.UserLabels]: collectUserLabels(),
|
||||||
[Feature.UsernameColors]: createValue({
|
[Feature.UsernameColors]: createValue({
|
||||||
deserialize: (input) => JSON.parse(input) as UsernameColorsData,
|
deserialize: (input) => JSON.parse(input) as UsernameColorsData,
|
|
@ -1,6 +1,6 @@
|
||||||
import browser from "webextension-polyfill";
|
import browser from "webextension-polyfill";
|
||||||
import {setup} from "@holllo/test";
|
import {setup} from "@holllo/test";
|
||||||
import {Data, Feature} from "../common.js";
|
import {Data, Feature} from "../exports.js";
|
||||||
import {migrations} from "./migrations.js";
|
import {migrations} from "./migrations.js";
|
||||||
import {v112Sample} from "./v1-1-2.js";
|
import {v112Sample} from "./v1-1-2.js";
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import {setup} from "@holllo/test";
|
|
||||||
import {type Migration} from "@holllo/migration-helper";
|
import {type Migration} from "@holllo/migration-helper";
|
||||||
import browser from "webextension-polyfill";
|
|
||||||
import {
|
import {
|
||||||
Data,
|
Data,
|
||||||
Feature,
|
Feature,
|
||||||
createValueUserLabel,
|
createValueUserLabel,
|
||||||
fromStorage,
|
fromStorage,
|
||||||
saveUserLabels,
|
saveUserLabels,
|
||||||
} from "../common.js";
|
} from "../exports.js";
|
||||||
import {v112DeserializeData, v112Sample, type V112Settings} from "./v1-1-2.js";
|
import {v112DeserializeData, v112Sample, type V112Settings} from "./v1-1-2.js";
|
||||||
|
|
||||||
export const migrations: Array<Migration<string>> = [
|
export const migrations: Array<Migration<string>> = [
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
import {createValue, type Value} from "@holllo/webextension-storage";
|
||||||
|
import browser from "webextension-polyfill";
|
||||||
|
import {Feature} from "./enums.js";
|
||||||
|
|
||||||
|
export type UserLabel = {
|
||||||
|
color: string;
|
||||||
|
id: number;
|
||||||
|
priority: number;
|
||||||
|
text: string;
|
||||||
|
username: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type UserLabelsData = Array<Value<UserLabel>>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a {@link Value}-wrapped {@link UserLabel}.
|
||||||
|
*/
|
||||||
|
export async function createValueUserLabel(
|
||||||
|
userLabel: UserLabel,
|
||||||
|
): Promise<UserLabelsData[number]> {
|
||||||
|
return createValue<UserLabel>({
|
||||||
|
deserialize: (input) => JSON.parse(input) as UserLabel,
|
||||||
|
serialize: (input) => JSON.stringify(input),
|
||||||
|
key: `${Feature.UserLabels}-${userLabel.id}`,
|
||||||
|
value: userLabel,
|
||||||
|
storage: browser.storage.sync,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all user labels from storage and combine them into a single array.
|
||||||
|
*/
|
||||||
|
export async function collectUserLabels(): Promise<UserLabelsData> {
|
||||||
|
const storage = await browser.storage.sync.get();
|
||||||
|
const userLabels = [];
|
||||||
|
for (const [key, value] of Object.entries(storage)) {
|
||||||
|
if (!key.startsWith(Feature.UserLabels)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
userLabels.push(
|
||||||
|
await createValueUserLabel(JSON.parse(value as string) as UserLabel),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return userLabels;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save all user labels to storage under individual keys.
|
||||||
|
*
|
||||||
|
* They are stored under individual keys so that we don't run into storage quota
|
||||||
|
* limits. If it was stored under a single key we would only be able to fit
|
||||||
|
* around 80-100 labels before hitting the limit.
|
||||||
|
* @param userLabels The user labels array to save.
|
||||||
|
*/
|
||||||
|
export async function saveUserLabels(
|
||||||
|
userLabels: UserLabelsData,
|
||||||
|
): Promise<void> {
|
||||||
|
for (const label of userLabels) {
|
||||||
|
await label.save();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue