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
3 changes: 3 additions & 0 deletions frontend/src/html/pages/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,9 @@
<div id="premidTestMode" class="hidden"></div>
<div id="premidSecondsLeft" class="hidden"></div>
</div>
<div class="loading hidden">
<i class="fas fa-circle-notch fa-spin"></i>
</div>
<div id="result" class="content-grid full-width hidden" tabindex="-1">
<div class="wrapper">
<div class="stats">
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<load src="html/warnings.html" />
<div id="fpsCounter" class="hidden"></div>
<div class="customBackground"></div>
<div id="backgroundLoader" style="display: none"></div>
<div id="backgroundLoader" class="hidden"></div>
<div id="bannerCenter" class="focus"></div>
<div id="notificationCenter">
<div class="clearAll button invisible" style="display: none">
Expand Down
9 changes: 9 additions & 0 deletions frontend/src/styles/animations.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
}
}

@keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

@keyframes caretFlashSmooth {
0%,
100% {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/styles/core.scss
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ body {
background: var(--main-color);
animation: loader 2s cubic-bezier(0.38, 0.16, 0.57, 0.82) infinite;
z-index: 9999;
opacity: 0;
}

key {
Expand Down
18 changes: 17 additions & 1 deletion frontend/src/styles/test.scss
Original file line number Diff line number Diff line change
Expand Up @@ -589,7 +589,7 @@
}

#wordsInput {
width: 1ch;
width: 0;
font-size: 1em;
height: 1em;
opacity: 0;
Expand Down Expand Up @@ -631,6 +631,22 @@
}
}

.pageTest > .loading {
text-align: center;
& > i {
font-size: 2rem;
color: var(--main-color);
}
opacity: 0;
&:not(.hidden) {
animation-name: fadeIn;
animation-duration: 0.125s;
animation-delay: 0.5s;
animation-fill-mode: forwards;
animation-timing-function: ease;
}
}

#result {
&:focus-visible {
outline: none;
Expand Down
92 changes: 49 additions & 43 deletions frontend/src/ts/elements/keymap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { getActiveFunboxNames } from "../test/funbox/list";
import { areSortedArraysEqual } from "../utils/arrays";
import { LayoutObject } from "@monkeytype/schemas/layouts";
import { animate } from "animejs";
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";

export const keyDataDelimiter = "\uE000";

Expand Down Expand Up @@ -72,62 +73,67 @@ function findKeyElements(char: string): JQuery {

function highlightKey(currentKey: string): void {
if (Config.mode === "zen") return;
if (currentKey === "") currentKey = " ";
try {
$(".activeKey").removeClass("activeKey");
requestDebouncedAnimationFrame("keymap.highlightKey", async () => {
if (currentKey === "") currentKey = " ";
try {
document
.querySelectorAll(".activeKey")
.forEach((el) => el.classList.remove("activeKey"));

if (Config.language.startsWith("korean")) {
currentKey = Hangul.disassemble(currentKey)[0] ?? currentKey;
}
if (Config.language.startsWith("korean")) {
currentKey = Hangul.disassemble(currentKey)[0] ?? currentKey;
}

const $target = findKeyElements(currentKey);
$target.addClass("activeKey");
} catch (e) {
if (e instanceof Error) {
console.log("could not update highlighted keymap key: " + e.message);
const $target = findKeyElements(currentKey);
$target.addClass("activeKey");
} catch (e) {
if (e instanceof Error) {
console.log("could not update highlighted keymap key: " + e.message);
}
}
}
});
}

async function flashKey(key: string, correct?: boolean): Promise<void> {
if (key === undefined) return;
requestDebouncedAnimationFrame(`keymap.flashKey.${key}`, async () => {
const $target = findKeyElements(key);

const $target = findKeyElements(key);

const elements = $target.toArray();
if (elements.length === 0) return;
const elements = $target.toArray();
if (elements.length === 0) return;

const themecolors = await ThemeColors.getAll();
const themecolors = await ThemeColors.getAll();

try {
let startingStyle = {
color: themecolors.bg,
backgroundColor: themecolors.sub,
borderColor: themecolors.sub,
};

if (correct || Config.blindMode) {
startingStyle = {
color: themecolors.bg,
backgroundColor: themecolors.main,
borderColor: themecolors.main,
};
} else {
startingStyle = {
try {
let startingStyle = {
color: themecolors.bg,
backgroundColor: themecolors.error,
borderColor: themecolors.error,
backgroundColor: themecolors.sub,
borderColor: themecolors.sub,
};
}

animate(elements, {
color: [startingStyle.color, themecolors.sub],
backgroundColor: [startingStyle.backgroundColor, themecolors.subAlt],
borderColor: [startingStyle.borderColor, themecolors.sub],
duration: 250,
easing: "out(5)",
});
} catch (e) {}
if (correct || Config.blindMode) {
startingStyle = {
color: themecolors.bg,
backgroundColor: themecolors.main,
borderColor: themecolors.main,
};
} else {
startingStyle = {
color: themecolors.bg,
backgroundColor: themecolors.error,
borderColor: themecolors.error,
};
}

animate(elements, {
color: [startingStyle.color, themecolors.sub],
backgroundColor: [startingStyle.backgroundColor, themecolors.subAlt],
borderColor: [startingStyle.borderColor, themecolors.sub],
duration: 250,
easing: "out(5)",
});
} catch (e) {}
});
}

export function hide(): void {
Expand Down
48 changes: 24 additions & 24 deletions frontend/src/ts/elements/loader.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
const element = $("#backgroundLoader");
let timeout: NodeJS.Timeout | null = null;
let visible = false;
import { animate, JSAnimation } from "animejs";
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";

function clearTimeout(): void {
if (timeout !== null) {
window.clearTimeout(timeout);
timeout = null;
}
}
const element = document.querySelector("#backgroundLoader") as HTMLElement;
let showAnim: JSAnimation | null = null;

export function show(instant = false): void {
if (visible) return;

if (instant) {
element.stop(true, true).show();
visible = true;
} else {
timeout = setTimeout(() => {
element.stop(true, true).show();
}, 125);
visible = true;
}
requestDebouncedAnimationFrame("loader.show", () => {
showAnim = animate(element, {
opacity: 1,
duration: 125,
delay: instant ? 0 : 125,
onBegin: () => {
element.classList.remove("hidden");
},
});
});
}

export function hide(): void {
if (!visible) return;
clearTimeout();
element.stop(true, true).fadeOut(125);
visible = false;
requestDebouncedAnimationFrame("loader.hide", () => {
showAnim?.pause();
animate(element, {
opacity: 0,
duration: 125,
onComplete: () => {
element.classList.add("hidden");
},
});
});
}
102 changes: 52 additions & 50 deletions frontend/src/ts/elements/monkey-power.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import * as ThemeColors from "./theme-colors";
import * as SlowTimer from "../states/slow-timer";
import Config from "../config";
import { isSafeNumber } from "@monkeytype/util/numbers";
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";

const html = document.querySelector("html") as HTMLElement;
const body = document.body;

type Particle = {
x: number;
Expand All @@ -14,7 +18,7 @@ type Particle = {

type CTX = {
particles: Particle[];
caret?: JQuery;
caret?: HTMLElement;
canvas?: HTMLCanvasElement;
context2d?: CanvasRenderingContext2D;
rendering: boolean;
Expand Down Expand Up @@ -118,7 +122,7 @@ function updateParticle(particle: Particle): void {
}

export function init(): void {
ctx.caret = $("#caret");
ctx.caret = document.querySelector("#caret") as HTMLElement;
ctx.canvas = createCanvas();
ctx.context2d = ctx.canvas.getContext("2d") as CanvasRenderingContext2D;
}
Expand Down Expand Up @@ -155,7 +159,7 @@ function render(): void {
}
ctx.particles = keep;

if (ctx.particles.length && !SlowTimer.get()) {
if (ctx.particles.length) {
requestAnimationFrame(render);
} else {
ctx.context2d.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
Expand All @@ -168,14 +172,13 @@ export function reset(immediate = false): void {
delete ctx.resetTimeOut;

clearTimeout(ctx.resetTimeOut);
const body = $(document.body);
body.css("transition", "all .25s, transform 0.8s");
body.css("transform", `translate(0,0)`);
body.style.transition = "all .25s, transform 0.8s";
body.style.transform = `translate(0,0)`;
setTimeout(
() => {
body.css("transition", "all .25s, transform .05s");
$("html").css("overflow", "inherit");
$("html").css("overflow-y", "scroll");
body.style.transition = "all .25s, transform .05s";
html.style.overflow = "inherit";
html.style.overflowY = "scroll";
},
immediate ? 0 : 1000,
);
Expand All @@ -201,47 +204,46 @@ function randomColor(): string {
export async function addPower(good = true, extra = false): Promise<void> {
if (Config.monkeyPowerLevel === "off" || SlowTimer.get()) return;

if (Config.blindMode) good = true;

// Shake
if (["3", "4"].includes(Config.monkeyPowerLevel)) {
$("html").css("overflow", "hidden");
const shake = [
Math.round(shakeAmount - Math.random() * shakeAmount),
Math.round(shakeAmount - Math.random() * shakeAmount),
requestDebouncedAnimationFrame("monkey-power.addPower", async () => {
if (Config.blindMode) good = true;

// Shake
if (["3", "4"].includes(Config.monkeyPowerLevel)) {
html.style.overflow = "hidden";
const shake = [
Math.round(shakeAmount - Math.random() * shakeAmount),
Math.round(shakeAmount - Math.random() * shakeAmount),
];
body.style.transform = `translate(${shake[0]}px, ${shake[1]}px)`;
if (isSafeNumber(ctx.resetTimeOut)) clearTimeout(ctx.resetTimeOut);
ctx.resetTimeOut = setTimeout(reset, 2000) as unknown as number;
}

// Sparks
const offset = ctx.caret?.getBoundingClientRect();
const coords = [
offset?.left ?? 0,
(offset?.top ?? 0) + (ctx.caret?.offsetHeight ?? 0) / 2,
];
$(document.body).css(
"transform",
`translate(${shake[0]}px, ${shake[1]}px)`,
);
if (isSafeNumber(ctx.resetTimeOut)) clearTimeout(ctx.resetTimeOut);
ctx.resetTimeOut = setTimeout(reset, 2000) as unknown as number;
}

// Sparks
const offset = ctx.caret?.offset();
const coords = [
offset?.left ?? 0,
(offset?.top ?? 0) + (ctx.caret?.height() ?? 0),
];

for (
let i = Math.round(
(particleCreateCount[0] + Math.random() * particleCreateCount[1]) *
(extra ? 2 : 1),
);
i > 0;
i--
) {
const color = ["2", "4"].includes(Config.monkeyPowerLevel)
? randomColor()
: good
? await ThemeColors.get("caret")
: await ThemeColors.get("error");
ctx.particles.push(
createParticle(...(coords as [x: number, y: number]), color),
);
}

startRender();
for (
let i = Math.round(
(particleCreateCount[0] + Math.random() * particleCreateCount[1]) *
(extra ? 2 : 1),
);
i > 0;
i--
) {
const color = ["2", "4"].includes(Config.monkeyPowerLevel)
? randomColor()
: good
? await ThemeColors.get("caret")
: await ThemeColors.get("error");
ctx.particles.push(
createParticle(...(coords as [x: number, y: number]), color),
);
}

startRender();
});
}
Loading
Loading