1
Fork 0

Rework storage values to use a single function.

This commit is contained in:
Bauke 2023-07-02 12:25:48 +02:00
parent 2e0ea98225
commit 866d823820
Signed by: Bauke
GPG Key ID: C1C0F29952BCF558
4 changed files with 43 additions and 27 deletions

View File

@ -1,8 +1,5 @@
import Shepherd from "shepherd.js"; import Shepherd from "shepherd.js";
import { import {fromStorage, StorageKey} from "../storage/common.js";
addCompletedTour,
createIntroductionUnderstood,
} from "../storage/common.js";
import { import {
allTours, allTours,
introductionTour, introductionTour,
@ -12,7 +9,9 @@ import {
/** The main entry point for the content script. */ /** The main entry point for the content script. */
async function main(): Promise<void> { async function main(): Promise<void> {
const introductionUnderstood = await createIntroductionUnderstood(); const introductionUnderstood = await fromStorage(
StorageKey.IntroductionUnderstood,
);
// Get the anchor without the leading #. // Get the anchor without the leading #.
const anchor = window.location.hash.slice(1); const anchor = window.location.hash.slice(1);
@ -121,7 +120,9 @@ function startTour(data: TourData, runMainAgainAfterComplete: boolean): void {
} }
// Mark the tour as completed. // Mark the tour as completed.
await addCompletedTour(data.id); const completedTours = await fromStorage(StorageKey.ToursCompleted);
completedTours.value.add(data.id);
await completedTours.save();
if (runMainAgainAfterComplete) { if (runMainAgainAfterComplete) {
await main(); await main();

View File

@ -1,12 +1,16 @@
import {Component, type JSX} from "preact"; import {Component, type JSX} from "preact";
import {createToursCompleted} from "../../storage/common.js"; import {
fromStorage,
StorageKey,
type StorageValues,
} from "../../storage/common.js";
import {allTours} from "../../tours/exports.js"; import {allTours} from "../../tours/exports.js";
import {Tour} from "./tour.js"; import {Tour} from "./tour.js";
type Props = Record<string, unknown>; type Props = Record<string, unknown>;
type State = { type State = {
toursCompleted: Awaited<ReturnType<typeof createToursCompleted>>["value"]; toursCompleted: Awaited<StorageValues[StorageKey.ToursCompleted]>;
}; };
export class Tours extends Component<Props, State> { export class Tours extends Component<Props, State> {
@ -14,20 +18,23 @@ export class Tours extends Component<Props, State> {
super(props); super(props);
this.state = { this.state = {
toursCompleted: new Set(), toursCompleted: undefined!,
}; };
} }
async componentDidMount(): Promise<void> { async componentDidMount(): Promise<void> {
const toursCompleted = await createToursCompleted(); const toursCompleted = await fromStorage(StorageKey.ToursCompleted);
this.setState({toursCompleted: toursCompleted.value}); this.setState({toursCompleted});
} }
render(): JSX.Element { render(): JSX.Element {
const {toursCompleted} = this.state; const {toursCompleted} = this.state;
if (toursCompleted === undefined) {
return <></>;
}
const tours = allTours.map((tour) => ( const tours = allTours.map((tour) => (
<Tour hasBeenCompleted={toursCompleted.has(tour.id)} tour={tour} /> <Tour hasBeenCompleted={toursCompleted.value.has(tour.id)} tour={tour} />
)); ));
return ( return (

View File

@ -2,33 +2,39 @@ import browser from "webextension-polyfill";
import {createValue} from "@holllo/webextension-storage"; import {createValue} from "@holllo/webextension-storage";
import {type TourId} from "../tours/exports.js"; import {type TourId} from "../tours/exports.js";
/** All available storage keys. */
export enum StorageKey { export enum StorageKey {
IntroductionUnderstood = "introduction-understood", IntroductionUnderstood = "introduction-understood",
ToursCompleted = "tours-completed", ToursCompleted = "tours-completed",
} }
export async function createIntroductionUnderstood() { /** All values we want to save in storage. */
return createValue<boolean>({ const storageValues = {
[StorageKey.IntroductionUnderstood]: createValue<boolean>({
deserialize: (input) => input === "true", deserialize: (input) => input === "true",
serialize: (input) => JSON.stringify(input), serialize: (input) => JSON.stringify(input),
key: StorageKey.IntroductionUnderstood, key: StorageKey.IntroductionUnderstood,
storage: browser.storage.local, storage: browser.storage.local,
value: false, value: false,
}); }),
} [StorageKey.ToursCompleted]: createValue<Set<TourId>>({
export async function createToursCompleted() {
return createValue<Set<TourId>>({
deserialize: (input) => new Set(JSON.parse(input) as TourId[]), deserialize: (input) => new Set(JSON.parse(input) as TourId[]),
serialize: (input) => JSON.stringify(Array.from(input)), serialize: (input) => JSON.stringify(Array.from(input)),
key: StorageKey.ToursCompleted, key: StorageKey.ToursCompleted,
storage: browser.storage.local, storage: browser.storage.local,
value: new Set([]), value: new Set([]),
}); }),
} };
export async function addCompletedTour(tourId: TourId): Promise<void> { /** Alias to get the inferred type shape of {@link storageValues}. */
const toursCompleted = await createToursCompleted(); export type StorageValues = typeof storageValues;
toursCompleted.value.add(tourId);
await toursCompleted.save(); /**
* Get the stored value for a given key.
* @param key The key to get from storage.
*/
export async function fromStorage<K extends StorageKey>(
key: K,
): Promise<StorageValues[K]> {
return storageValues[key];
} }

View File

@ -1,4 +1,4 @@
import {createIntroductionUnderstood} from "../storage/common.js"; import {fromStorage, StorageKey} from "../storage/common.js";
import {TourId, type TourData} from "./types.js"; import {TourId, type TourData} from "./types.js";
import {openOptionsPageFromBackground, renderInContainer} from "./utilities.js"; import {openOptionsPageFromBackground, renderInContainer} from "./utilities.js";
@ -103,7 +103,9 @@ const steps: TourData["steps"] = [
classes: "btn", classes: "btn",
text: "I understand", text: "I understand",
async action() { async action() {
const introductionUnderstood = await createIntroductionUnderstood(); const introductionUnderstood = await fromStorage(
StorageKey.IntroductionUnderstood,
);
introductionUnderstood.value = true; introductionUnderstood.value = true;
await introductionUnderstood.save(); await introductionUnderstood.save();
this.complete(); this.complete();