Skip to content

Commit

Permalink
feat(custom text): remember custom text settings between sessions
Browse files Browse the repository at this point in the history
closes #4182
  • Loading branch information
Miodec committed Sep 19, 2024
1 parent 09ce4bd commit 2dcb107
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 60 deletions.
6 changes: 4 additions & 2 deletions frontend/__tests__/utils/local-storage-with-schema.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ describe("local-storage-with-schema.ts", () => {
expect(localStorage.getItem).toHaveBeenCalledWith("config");
expect(migrateFnMock).toHaveBeenCalledWith(
existingValue,
expect.any(Array)
expect.any(Array),
defaultObject
);
expect(localStorage.setItem).toHaveBeenCalledWith(
"config",
Expand Down Expand Up @@ -166,7 +167,8 @@ describe("local-storage-with-schema.ts", () => {
expect(localStorage.getItem).toHaveBeenCalledWith("config");
expect(migrateFnMock).toHaveBeenCalledWith(
existingValue,
expect.any(Array)
expect.any(Array),
defaultObject
);
expect(localStorage.setItem).toHaveBeenCalledWith(
"config",
Expand Down
34 changes: 17 additions & 17 deletions frontend/src/html/popups.html
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,23 @@
</div>
</div>

<div class="group" data-id="delimiter">
<div class="title">
<i class="fas fa-fw fa-grip-lines-vertical"></i>
Word delimiter
</div>
<div class="sub">
Change how words are separated. Using the pipe delimiter allows you to
randomize groups of words.
</div>
<div class="groupInputs">
<div class="buttonGroup">
<button value="true">pipe</button>
<button value="false">space</button>
</div>
</div>
</div>

<div class="group" data-id="fancy">
<div class="title">
<i class="fas fa-fw fa-pen-fancy"></i>
Expand Down Expand Up @@ -584,23 +601,6 @@
</div>
</div>

<div class="group" data-id="delimiter">
<div class="title">
<i class="fas fa-fw fa-grip-lines-vertical"></i>
Word delimiter
</div>
<div class="sub">
Change how words are separated. Using the pipe delimiter allows you to
randomize groups of words.
</div>
<div class="groupInputs">
<div class="buttonGroup">
<button value="true">pipe</button>
<button value="false">space</button>
</div>
</div>
</div>

<div class="group" data-id="newlines">
<div class="title">
<i class="fas fa-fw fa-level-down-alt fa-rotate-90"></i>
Expand Down
117 changes: 76 additions & 41 deletions frontend/src/ts/test/custom-text.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import {
CustomTextLimitMode,
CustomTextLimitModeSchema,
CustomTextMode,
CustomTextModeSchema,
} from "@monkeytype/contracts/schemas/util";
import { LocalStorageWithSchema } from "../utils/local-storage-with-schema";
import { z } from "zod";

//zod schema for an object with string keys and string values
const CustomTextObjectSchema = z.record(z.string(), z.string());
type CustomTextObject = z.infer<typeof CustomTextObjectSchema>;

Expand All @@ -27,83 +28,117 @@ const customTextLongLS = new LocalStorageWithSchema({
fallback: {},
});

// function setLocalStorage(data: CustomTextObject): void {
// window.localStorage.setItem("customText", JSON.stringify(data));
// }

// function setLocalStorageLong(data: CustomTextLongObject): void {

let text: string[] = [
"The",
"quick",
"brown",
"fox",
"jumps",
"over",
"the",
"lazy",
"dog",
];

let mode: CustomTextMode = "repeat";
const limit: MonkeyTypes.CustomTextLimit = {
value: 9,
mode: "word",
const CustomTextSettingsSchema = z.object({
text: z.array(z.string()),
mode: CustomTextModeSchema,
limit: z.object({ value: z.number(), mode: CustomTextLimitModeSchema }),
pipeDelimiter: z.boolean(),
});

type CustomTextSettings = z.infer<typeof CustomTextSettingsSchema>;

const defaultCustomTextSettings: CustomTextSettings = {
text: ["The", "quick", "brown", "fox", "jumps", "over", "the", "lazy", "dog"],
mode: "repeat",
limit: { value: 9, mode: "word" },
pipeDelimiter: false,
};
let pipeDelimiter = false;

const customTextSettings = new LocalStorageWithSchema({
key: "customTextSettings",
schema: CustomTextSettingsSchema,
fallback: defaultCustomTextSettings,
migrate: (oldData, _zodIssues, fallback) => {
if (typeof oldData !== "object" || oldData === null) {
return fallback;
}
const migratedData = fallback;
if (
"text" in oldData &&
z.array(z.string()).safeParse(migratedData.text).success
) {
migratedData.text = oldData.text as string[];
}
return migratedData;
},
});

export function getText(): string[] {
return text;
return customTextSettings.get().text;
}

export function setText(txt: string[]): void {
text = txt;
limit.value = text.length;
const currentSettings = customTextSettings.get();
customTextSettings.set({
...currentSettings,
text: txt,
limit: { value: txt.length, mode: currentSettings.limit.mode },
});
}

export function getMode(): CustomTextMode {
return mode;
const currentSettings = customTextSettings.get();
return currentSettings.mode;
}

export function setMode(val: CustomTextMode): void {
mode = val;
limit.value = text.length;
const currentSettings = customTextSettings.get();
customTextSettings.set({
...currentSettings,
mode: val,
limit: {
value: currentSettings.text.length,
mode: currentSettings.limit.mode,
},
});
}

export function getLimit(): MonkeyTypes.CustomTextLimit {
return limit;
return customTextSettings.get().limit as MonkeyTypes.CustomTextLimit;
}

export function getLimitValue(): number {
return limit.value;
return customTextSettings.get().limit.value;
}

export function getLimitMode(): CustomTextLimitMode {
return limit.mode;
return customTextSettings.get().limit.mode;
}

export function setLimitValue(val: number): void {
limit.value = val;
const currentSettings = customTextSettings.get();
customTextSettings.set({
...currentSettings,
limit: { value: val, mode: currentSettings.limit.mode },
});
}

export function setLimitMode(val: CustomTextLimitMode): void {
limit.mode = val;
const currentSettings = customTextSettings.get();
customTextSettings.set({
...currentSettings,
limit: { value: currentSettings.limit.value, mode: val },
});
}

export function getPipeDelimiter(): boolean {
return pipeDelimiter;
return customTextSettings.get().pipeDelimiter;
}

export function setPipeDelimiter(val: boolean): void {
pipeDelimiter = val;
const currentSettings = customTextSettings.get();
customTextSettings.set({
...currentSettings,
pipeDelimiter: val,
});
}

export function getData(): MonkeyTypes.CustomTextData {
return {
text,
mode,
limit,
pipeDelimiter,
text: getText(),
mode: getMode(),
limit: getLimit(),
pipeDelimiter: getPipeDelimiter(),
};
}

Expand Down

0 comments on commit 2dcb107

Please sign in to comment.