Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions frontend/__tests__/input/helpers/validation.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@ vi.mock("../../../src/ts/test/funbox/list", () => ({
findSingleActiveFunboxWithFunction: vi.fn(),
}));

vi.mock("../../../src/ts/utils/strings", () => ({
areCharactersVisuallyEqual: vi.fn(),
isSpace: vi.fn(),
}));
vi.mock("../../../src/ts/utils/strings", async () => {
const actual = await vi.importActual<typeof Strings>(
"../../../src/ts/utils/strings"
);
return {
...actual,
areCharactersVisuallyEqual: vi.fn(),
};
});

describe("isCharCorrect", () => {
beforeEach(() => {
Expand All @@ -34,7 +39,6 @@ describe("isCharCorrect", () => {
null
);
(Strings.areCharactersVisuallyEqual as any).mockReturnValue(false);
(Strings.isSpace as any).mockReturnValue(false);
});

afterAll(() => {
Expand Down Expand Up @@ -133,7 +137,6 @@ describe("isCharCorrect", () => {

describe("shouldInsertSpaceCharacter", () => {
beforeEach(() => {
(Strings.isSpace as any).mockReturnValue(true);
replaceConfig({
mode: "time",
stopOnError: "off",
Expand All @@ -147,7 +150,6 @@ describe("shouldInsertSpaceCharacter", () => {
});

it("returns null if data is not a space", () => {
(Strings.isSpace as any).mockReturnValue(false);
expect(
shouldInsertSpaceCharacter({
data: "a",
Expand Down
10 changes: 5 additions & 5 deletions frontend/__tests__/utils/strings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -474,14 +474,14 @@ describe("string utils", () => {
["\u2003", 0x2003, "em space", true],
["\u2009", 0x2009, "thin space", true],
[" ", 0x3000, "ideographic space", true],
["\u00A0", 0x00a0, "non-breaking space", true],
["\u2007", 0x2007, "figure space", true],
["\u2008", 0x2008, "punctuation space", true],
["\u200A", 0x200a, "hair space", true],
["​", 0x200b, "zero-width space", true],

// Should return false for other characters
["\t", 0x0009, "tab", false],
["\u00A0", 0x00a0, "non-breaking space", false],
["\u2007", 0x2007, "figure space", false],
["\u2008", 0x2008, "punctuation space", false],
["\u200A", 0x200a, "hair space", false],
["​", 0x200b, "zero-width space", false],
["a", 0x0061, "letter a", false],
["A", 0x0041, "letter A", false],
["1", 0x0031, "digit 1", false],
Expand Down
6 changes: 6 additions & 0 deletions frontend/src/ts/commandline/commandline-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -703,6 +703,12 @@ export const commandlineConfigMetadata: CommandlineConfigMetadataObject = {
options: "fromSchema",
},
},
showPb: {
subgroup: {
options: "fromSchema",
},
alias: "pb",
},
monkeyPowerLevel: {
alias: "powermode",
isVisible: false,
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/ts/commandline/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const confidenceModeCommand = buildCommandForConfigKey("confidenceMode");
const lazyModeCommand = buildCommandForConfigKey("lazyMode");
const layoutCommand = buildCommandForConfigKey("layout");
const showAverageCommand = buildCommandForConfigKey("showAverage");
const showPbCommand = buildCommandForConfigKey("showPb");
const keymapLayoutCommand = buildCommandForConfigKey("keymapLayout");
const customThemeCommand = buildCommandForConfigKey("customTheme");
const adsCommand = buildCommandForConfigKey("ads");
Expand Down Expand Up @@ -216,6 +217,7 @@ export const commands: CommandsSubgroup = {
"showOutOfFocusWarning",
"capsLockWarning",
showAverageCommand,
showPbCommand,
"monkeyPowerLevel",
"monkey"
),
Expand Down Expand Up @@ -377,6 +379,7 @@ const lists = {
lazyMode: lazyModeCommand.subgroup,
paceCaretMode: paceCaretCommand.subgroup,
showAverage: showAverageCommand.subgroup,
showPb: showPbCommand.subgroup,
minWpm: minSpeedCommand.subgroup,
minAcc: minAccCommand.subgroup,
minBurst: MinBurstCommands[0]?.subgroup,
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/ts/config-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,11 @@ export const configMetadata: ConfigMetadataObject = {
displayString: "show average",
changeRequiresRestart: false,
},
showPb: {
icon: "fa-crown",
displayString: "show personal best",
changeRequiresRestart: false,
},

// other (hidden)
accountChart: {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/ts/constants/default-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ const obj: Config = {
britishEnglish: false,
lazyMode: false,
showAverage: "off",
showPb: false,
tapeMode: "off",
tapeMargin: 50,
maxLineWidth: 0,
Expand Down
47 changes: 33 additions & 14 deletions frontend/src/ts/elements/modes-notice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import { isAuthenticated } from "../firebase";
import * as CustomTextState from "../states/custom-text-name";
import { getLanguageDisplayString } from "../utils/strings";
import Format from "../utils/format";
import { getActiveFunboxNames } from "../test/funbox/list";
import { escapeHTML } from "../utils/misc";
import { getActiveFunboxes, getActiveFunboxNames } from "../test/funbox/list";
import { escapeHTML, getMode2 } from "../utils/misc";

ConfigEvent.subscribe((eventKey) => {
const configKeys: ConfigEvent.ConfigEventKey[] = [
Expand All @@ -26,6 +26,7 @@ ConfigEvent.subscribe((eventKey) => {
"confidenceMode",
"layout",
"showAverage",
"showPb",
"typingSpeedUnit",
"quickRestart",
"customPolyglot",
Expand Down Expand Up @@ -191,6 +192,36 @@ export async function update(): Promise<void> {
}
}

if (Config.showPb) {
if (!isAuthenticated()) {
return;
}
const mode2 = getMode2(Config, TestWords.currentQuote);
const pb = await DB.getLocalPB(
Config.mode,
mode2,
Config.punctuation,
Config.numbers,
Config.language,
Config.difficulty,
Config.lazyMode,
getActiveFunboxes()
);

let str = "no pb";

if (pb !== undefined) {
str = `${Format.typingSpeed(pb.wpm, {
showDecimalPlaces: true,
suffix: ` ${Config.typingSpeedUnit}`,
})} ${pb?.acc}% acc`;
}

$(".pageTest #testModesNotice").append(
`<button class="textButton" commands="showPb"><i class="fas fa-crown"></i>${str}</button>`
);
}

if (Config.minWpm !== "off") {
$(".pageTest #testModesNotice").append(
`<button class="textButton" commands="minWpm"><i class="fas fa-bomb"></i>min ${Format.typingSpeed(
Expand Down Expand Up @@ -277,15 +308,3 @@ export async function update(): Promise<void> {
}
} catch {}
}

if (import.meta.hot !== undefined) {
import.meta.hot.dispose(() => {
//
});
import.meta.hot.accept(() => {
//
});
import.meta.hot.on("vite:afterUpdate", () => {
void update();
});
}
4 changes: 4 additions & 0 deletions frontend/src/ts/event-handlers/global.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { focusWords } from "../test/test-ui";
import * as TestLogic from "../test/test-logic";
import { navigate } from "../controllers/route-controller";
import { isInputElementFocused } from "../input/input-element";
import * as ManualRestart from "../test/manual-restart-tracker";

document.addEventListener("keydown", (e) => {
if (PageTransition.get()) return;
Expand Down Expand Up @@ -74,6 +75,9 @@ document.addEventListener("keydown", (e) => {
) {
e.preventDefault();
if (ActivePage.get() === "test") {
if (e.shiftKey) {
ManualRestart.set();
}
TestLogic.restart();
} else {
void navigate("");
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/input/handlers/before-insert-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ export function onBeforeInsertText(data: string): boolean {
return true;
}

//only allow newlines if the test has newlines
if (data === "\n" && !TestWords.hasNewline) {
//only allow newlines if the test has newlines or in zen mode
if (data === "\n" && !TestWords.hasNewline && Config.mode !== "zen") {
return true;
}

Expand Down
1 change: 1 addition & 0 deletions frontend/src/ts/input/handlers/insert-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise<void> {
const result = await goToNextWord({
correctInsert: correct,
isCompositionEnding: isCompositionEnding === true,
zenNewline: charIsNewline && Config.mode === "zen",
});
lastBurst = result.lastBurst;
increasedWordIndex = result.increasedWordIndex;
Expand Down
12 changes: 12 additions & 0 deletions frontend/src/ts/input/handlers/keydown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import * as Notifications from "../../elements/notifications";
import * as KeyConverter from "../../utils/key-converter";
import * as ShiftTracker from "../../test/shift-tracker";
import * as CompositionState from "../../states/composition";
import * as ManualRestart from "../../test/manual-restart-tracker";
import { canQuickRestart } from "../../utils/quick-restart";
import * as CustomText from "../../test/custom-text";
import * as CustomTextState from "../../states/custom-text-name";
Expand All @@ -28,6 +29,9 @@ export async function handleTab(e: KeyboardEvent, now: number): Promise<void> {
if (Config.quickRestart === "tab") {
e.preventDefault();
if ((TestWords.hasTab && e.shiftKey) || !TestWords.hasTab) {
if (e.shiftKey) {
ManualRestart.set();
}
TestLogic.restart();
return;
}
Expand Down Expand Up @@ -81,6 +85,9 @@ export async function handleEnter(
if (Config.quickRestart === "enter") {
e.preventDefault();
if ((TestWords.hasNewline && e.shiftKey) || !TestWords.hasNewline) {
if (e.shiftKey) {
ManualRestart.set();
}
TestLogic.restart();
return;
}
Expand Down Expand Up @@ -206,6 +213,11 @@ export async function onKeydown(event: KeyboardEvent): Promise<void> {

if (event.key === "Escape" && Config.quickRestart === "esc") {
event.preventDefault();

if (event.shiftKey) {
ManualRestart.set();
}

TestLogic.restart();
return;
}
Expand Down
6 changes: 3 additions & 3 deletions frontend/src/ts/input/helpers/input-type.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
export type InsertInputType =
| "insertText"
| "insertCompositionText"
| "insertFromComposition" // safari firing a deprecated input type - thanks apple!
| "insertLineBreak";

export type DeleteInputType = "deleteWordBackward" | "deleteContentBackward";

export type SupportedInputType = InsertInputType | DeleteInputType;

type SupportedInputType = InsertInputType | DeleteInputType;
const SUPPORTED_INPUT_TYPES: Set<SupportedInputType> = new Set([
"insertText",
"insertCompositionText",
"insertFromComposition",
"insertLineBreak",
"deleteWordBackward",
"deleteContentBackward",
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/input/helpers/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function isCharCorrect(options: {
throw new Error("Failed to check if char is correct - data is undefined");
}

if (data === " ") {
if (isSpace(data)) {
return inputValue === targetWord;
}

Expand Down
8 changes: 7 additions & 1 deletion frontend/src/ts/input/helpers/word-navigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ type GoToNextWordParams = {
correctInsert: boolean;
// this is used to tell test ui to update the word before moving to the next word (in case of a composition that ends with a space)
isCompositionEnding: boolean;
zenNewline?: boolean;
};

type GoToNextWordReturn = {
Expand All @@ -31,13 +32,18 @@ type GoToNextWordReturn = {
export async function goToNextWord({
correctInsert,
isCompositionEnding,
zenNewline,
}: GoToNextWordParams): Promise<GoToNextWordReturn> {
const ret = {
increasedWordIndex: false,
lastBurst: 0,
};

TestUI.beforeTestWordChange("forward", correctInsert, isCompositionEnding);
TestUI.beforeTestWordChange(
"forward",
correctInsert,
isCompositionEnding || zenNewline === true
);

if (correctInsert) {
Replay.addReplayEvent("submitCorrectWord");
Expand Down
26 changes: 17 additions & 9 deletions frontend/src/ts/input/listeners/input.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { onDelete } from "../handlers/delete";
import { onInsertText } from "../handlers/insert-text";
import {
isSupportedInputType,
SupportedInputType,
} from "../helpers/input-type";
import { isSupportedInputType } from "../helpers/input-type";
import { getInputElement } from "../input-element";
import {
getLastInsertCompositionTextData,
Expand Down Expand Up @@ -56,7 +53,10 @@ inputEl.addEventListener("beforeinput", async (event) => {
inputType === "deleteContentBackward"
) {
onBeforeDelete(event);
} else if (inputType === "insertCompositionText") {
} else if (
inputType === "insertCompositionText" ||
inputType === "insertFromComposition"
) {
// firefox fires this extra event which we dont want to handle
if (!event.isComposing) {
event.preventDefault();
Expand All @@ -80,11 +80,16 @@ inputEl.addEventListener("input", async (event) => {
value: (event.target as HTMLInputElement).value,
});

// this shouldnt be neccesary because beforeinput already prevents default
// but some browsers (LIKE SAFARI) seem to ignore that, so just double checking here
if (!isSupportedInputType(event.inputType)) {
event.preventDefault();
return;
}

const now = performance.now();

// this is ok to cast because we are preventing default
// in the input listener for unsupported input types
const inputType = event.inputType as SupportedInputType;
const inputType = event.inputType;

if (
(inputType === "insertText" && event.data !== null) ||
Expand All @@ -105,7 +110,10 @@ inputEl.addEventListener("input", async (event) => {
inputType === "deleteContentBackward"
) {
onDelete(inputType);
} else if (inputType === "insertCompositionText") {
} else if (
inputType === "insertCompositionText" ||
inputType === "insertFromComposition"
) {
// in case the data is the same as the last one, just ignore it
if (getLastInsertCompositionTextData() !== event.data) {
setLastInsertCompositionTextData(event.data ?? "");
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/ts/test/test-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -597,6 +597,17 @@ async function init(): Promise<boolean> {
void Keymap.refresh();
}

if (
generatedWords
.join()
.normalize()
.match(
/[\uac00-\ud7af]|[\u1100-\u11ff]|[\u3130-\u318f]|[\ua960-\ua97f]|[\ud7b0-\ud7ff]/g
)
) {
TestInput.input.setKoreanStatus(true);
}

for (let i = 0; i < generatedWords.length; i++) {
TestWords.words.push(
generatedWords[i] as string,
Expand Down
Loading
Loading