Skip to content
Draft
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
13 changes: 1 addition & 12 deletions frontend/src/html/pages/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@

<div id="compositionDisplay"></div>
<mount data-component="keymap"></mount>
<mount data-component="monkey"></mount>

<button
id="restartTestButton"
Expand All @@ -81,18 +82,6 @@
<div class="liveBurst hidden">1</div>
</div>
</div>
<div id="monkey" class="hidden">
<div class="up"></div>
<div class="left hidden"></div>
<div class="right hidden"></div>
<div class="both hidden"></div>
<div class="fast">
<div class="up"></div>
<div class="left hidden"></div>
<div class="right hidden"></div>
<div class="both hidden"></div>
</div>
</div>
<div id="premidTestMode" class="hidden"></div>
<div id="premidSecondsLeft" class="hidden"></div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/styles/index.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

@layer custom-styles {
@import "buttons", "ads", "test-activity", "animations", "caret",
"commandline", "core", "fonts", "inputs", "monkey", "popups", "scroll",
"test", "loading", "media-queries";
"commandline", "core", "fonts", "inputs", "popups", "scroll", "test",
"loading", "media-queries";

.chartCanvas {
width: 100% !important;
Expand Down
37 changes: 0 additions & 37 deletions frontend/src/styles/monkey.scss

This file was deleted.

4 changes: 4 additions & 0 deletions frontend/src/styles/tailwind.css
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,8 @@
filter: invert(1);
}
}

.animate-shake {
animation: shake 0.1s ease-in-out infinite;
}
}
2 changes: 2 additions & 0 deletions frontend/src/ts/components/mount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { ProfileSearchPage } from "./pages/profile/ProfileSearchPage";
import { SettingsPage } from "./pages/settings/SettingsPage";
import { Keymap } from "./pages/test/Keymap";
import { TestModesNotice } from "./pages/test/modes-notice/TestModesNotice";
import { Monkey } from "./pages/test/Monkey";
import { TestConfig } from "./pages/test/TestConfig";
import { Popups } from "./popups/Popups";

Expand All @@ -50,6 +51,7 @@ const components: Record<string, () => JSXElement> = {
notfoundpage: () => <NotFoundPage />,
accountsettingspage: () => <AccountSettingsPage />,
keymap: () => <Keymap />,
monkey: () => <Monkey />,
};

function mountToMountpoint(name: string, component: () => JSXElement): void {
Expand Down
68 changes: 68 additions & 0 deletions frontend/src/ts/components/pages/test/Monkey.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { mapRange } from "@monkeytype/util/numbers";
import { Show } from "solid-js";

import { getConfig } from "../../../config/store";
import { getMonkeyState } from "../../../states/monkey";
import { currentLiveStats, isTestActive } from "../../../states/test";

const MIN_WPM = 130;
const MAX_WPM = 180;

export function Monkey() {
const speed = () =>
(getConfig.blindMode ? currentLiveStats.raw : currentLiveStats.wpm) ?? 0;

const fastOpacity = () => mapRange(speed(), MIN_WPM, MAX_WPM, 0, 1);

const animDuration = () => {
const duration = mapRange(speed(), MIN_WPM, MAX_WPM, 0.25, 0.01);
return duration === 0.25 ? 0 : duration;
};

const state = () => {
const { left, right } = getMonkeyState();
if (left && !right) return "left" as const;
if (right && !left) return "right" as const;
if (!left && !right) return "none" as const;
return "both" as const;
};

const monkeyImages = (suffix?: string) => {
const cur = state();
return [
<img
src={`/images/monkey/m1${suffix ?? ""}.png`}
class={cur === "left" ? "visible" : "hidden"}
/>,
<img
src={`/images/monkey/m2${suffix ?? ""}.png`}
class={cur === "right" ? "visible" : "hidden"}
/>,
<img
src={`/images/monkey/m3${suffix ?? ""}.png`}
class={cur === "none" ? "visible" : "hidden"}
/>,
<img
src={`/images/monkey/m4${suffix ?? ""}.png`}
class={cur === "both" ? "visible" : "hidden"}
/>,
];
};

return (
<Show when={getConfig.monkey && isTestActive()}>
<div
class="animate-shake flex w-full justify-center"
style={{ "animation-duration": `${animDuration()}s` }}
>
{monkeyImages()}
<div
class="fixed transition-all duration-1000"
style={{ opacity: fastOpacity() }}
>
{monkeyImages("_fast")}
</div>
</div>
</Show>
);
}
6 changes: 3 additions & 3 deletions frontend/src/ts/config/setters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import {
canSetConfigWithCurrentFunboxes,
canSetFunboxWithConfig,
} from "./funbox-validation";
import * as TestState from "../test/test-state";
import { typedKeys, triggerResize, escapeHTML } from "../utils/misc";
import { camelCaseToWords, capitalizeFirstLetter } from "../utils/strings";
import { Config, setConfigStore } from "./store";
import { FunboxName } from "@monkeytype/schemas/configs";
import { isTestActive } from "../states/test";

export function setConfig<T extends keyof ConfigSchemas.Config>(
key: T,
Expand All @@ -40,7 +40,7 @@ export function setConfig<T extends keyof ConfigSchemas.Config>(

if (
metadata.changeRequiresRestart &&
TestState.isActive &&
isTestActive() &&
Config.funbox.includes("no_quit")
) {
showNoticeNotification(
Expand Down Expand Up @@ -153,7 +153,7 @@ export function setQuoteLengthAll(nosave?: boolean): boolean {
}

export function toggleFunbox(funbox: FunboxName, nosave?: boolean): boolean {
if (TestState.isActive && Config.funbox.includes("no_quit")) {
if (isTestActive() && Config.funbox.includes("no_quit")) {
showNoticeNotification(
"No quit funbox is active. Please finish the test.",
{
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/controllers/ad-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import { debounce } from "throttle-debounce";
import { configEvent } from "../events/config";
import { Config } from "../config/store";
import * as TestState from "../test/test-state";
import * as EG from "./eg-ad-controller";
import * as PW from "./pw-ad-controller";
import { onDOMReady, qs } from "../utils/dom";
import { isTestActive } from "../states/test";
// import { createEffect } from "solid-js";

const breakpoint = 900;
Expand Down Expand Up @@ -41,7 +41,7 @@ function init(): void {
}

setInterval(() => {
if (TestState.isActive) {
if (isTestActive()) {
return;
}
if (choice === "eg") {
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/ts/controllers/route-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import * as TestState from "../test/test-state";
import { showNoticeNotification } from "../states/notifications";
import { navigationEvent, type NavigateOptions } from "../events/navigation";
import { authEvent } from "../events/auth";
import { isTestActive } from "../states/test";

//source: https://www.youtube.com/watch?v=OstALBk-jTc
// https://www.youtube.com/watch?v=OstALBk-jTc
Expand Down Expand Up @@ -176,7 +177,7 @@ export async function navigate(
}

const noQuit = isFunboxActive("no_quit");
if (TestState.isActive && noQuit) {
if (isTestActive() && noQuit) {
showNoticeNotification(
"No quit funbox is active. Please finish the test.",
{
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/ts/input/handlers/before-delete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import { getInputElementValue } from "../input-element";
import * as TestUI from "../../test/test-ui";
import { isAwaitingNextWord } from "../state";
import { getInputForWord } from "../../test/events/data";
import { isTestActive } from "../../states/test";

export function onBeforeDelete(event: InputEvent): void {
if (!TestState.isActive) {
if (!isTestActive()) {
event.preventDefault();
return;
}
Expand Down
3 changes: 2 additions & 1 deletion frontend/src/ts/input/handlers/insert-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
shouldInsertSpaceCharacter,
} from "../helpers/validation";
import { getCurrentInput, logTestEvent } from "../../test/events/data";
import { isTestActive } from "../../states/test";

const charOverrides = new Map<string, string>([
["…", "..."],
Expand Down Expand Up @@ -139,7 +140,7 @@ export async function onInsertText(options: OnInsertTextParams): Promise<void> {
const data = normalizedData ?? options.data;

// start if needed
if (!TestState.isActive) {
if (!isTestActive()) {
TestLogic.startTest(now);
}

Expand Down
9 changes: 0 additions & 9 deletions frontend/src/ts/input/handlers/keydown.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Config } from "../../config/store";
import * as TestLogic from "../../test/test-logic";
import { getCharFromEvent } from "../../test/layout-emulator";
import * as Monkey from "../../test/monkey";
import { emulateInsertText } from "./insert-text";
import * as TestState from "../../test/test-state";
import {
Expand Down Expand Up @@ -155,14 +154,6 @@ export async function onKeydown(event: KeyboardEvent): Promise<void> {
return;
}

if (!event.repeat) {
//delaying because type() is called before show()
// meaning the first keypress of the test is not animated
setTimeout(() => {
Monkey.type(event);
}, 0);
}

if (Config.layout !== "default") {
const emulatedChar = await getCharFromEvent(event);
if (emulatedChar !== null) {
Expand Down
5 changes: 0 additions & 5 deletions frontend/src/ts/input/handlers/keyup.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { Config } from "../../config/store";
import * as Monkey from "../../test/monkey";
import { logTestEvent } from "../../test/events/data";
import { getTestEventCode } from "../../test/events/helpers";

Expand All @@ -25,8 +24,4 @@ export async function onKeyup(event: KeyboardEvent): Promise<void> {
event.preventDefault();
return;
}

setTimeout(() => {
Monkey.stop(event);
}, 0);
}
3 changes: 2 additions & 1 deletion frontend/src/ts/input/listeners/composition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { setLastInsertCompositionTextData } from "../state";
import * as CompositionDisplay from "../../elements/composition-display";
import { onInsertText } from "../handlers/insert-text";
import { logTestEvent } from "../../test/events/data";
import { isTestActive } from "../../states/test";

const inputEl = getInputElement();

Expand All @@ -21,7 +22,7 @@ inputEl.addEventListener("compositionstart", (event) => {
CompositionState.setComposing(true);
CompositionState.setData("");
setLastInsertCompositionTextData("");
if (!TestState.isActive) {
if (!isTestActive()) {
TestLogic.startTest(now);
}

Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/legacy-states/connection.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { debounce } from "throttle-debounce";
import { showSuccessNotification } from "../states/notifications";
import { connectionEvent } from "../events/connection";
import * as TestState from "../test/test-state";
import { onDOMReady } from "../utils/dom";
import { addBanner, removeBanner } from "../states/banners";
import { isTestActive } from "../states/test";

let state = navigator.onLine;

Expand Down Expand Up @@ -38,7 +38,7 @@ const throttledHandleState = debounce(5000, () => {
noInternetBannerId = undefined;
}
bannerAlreadyClosed = false;
} else if (!TestState.isActive) {
} else if (!isTestActive()) {
showOfflineBanner();
}
});
Expand Down
Loading
Loading