mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-15 03:44:31 +08:00
implement color, opacity change config to a single signal
This commit is contained in:
parent
b3adfcc04f
commit
048c4a18d0
11 changed files with 330 additions and 440 deletions
|
|
@ -124,14 +124,8 @@
|
|||
<div id="memoryTimer">Time left to memorise all words: 0s</div>
|
||||
<div id="layoutfluidTimer">Time left to memorise all words: 0s</div>
|
||||
<div id="testModesNotice"></div>
|
||||
<div id="liveStatsTextTop" class="timerMain">
|
||||
<div class="wrapper">
|
||||
<div class="timerProgress hidden">1:00</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="liveStatsMini" class="full-width timerMain">
|
||||
<div class="time hidden">1:00</div>
|
||||
</div>
|
||||
<div id="liveStatsTextTop"></div>
|
||||
<div id="liveStatsMini" class="full-width"></div>
|
||||
<div id="wordsWrapper" class="content-grid full-width" translate="no">
|
||||
<textarea
|
||||
id="wordsInput"
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@
|
|||
display: grid;
|
||||
font-size: 10rem;
|
||||
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
justify-self: center;
|
||||
|
|
@ -163,8 +162,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
#liveStatsTextBottom.timerMain,
|
||||
#liveStatsTextTop.timerMain {
|
||||
#liveStatsTextBottom .colorMain,
|
||||
#liveStatsTextTop .colorMain {
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
|
|
@ -172,8 +171,8 @@
|
|||
background: var(--main-color);
|
||||
}
|
||||
|
||||
#liveStatsTextBottom.timerSub,
|
||||
#liveStatsTextTop.timerSub {
|
||||
#liveStatsTextBottom .colorSub,
|
||||
#liveStatsTextTop .colorSub {
|
||||
color: var(--sub-color);
|
||||
}
|
||||
|
||||
|
|
@ -181,8 +180,8 @@
|
|||
background: var(--sub-color);
|
||||
}
|
||||
|
||||
#liveStatsTextBottom.timerText,
|
||||
#liveStatsTextTop.timerText {
|
||||
#liveStatsTextBottom .colorText,
|
||||
#liveStatsTextTop .colorText {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
|
|
@ -1474,68 +1473,36 @@
|
|||
}
|
||||
}
|
||||
#liveStatsMini {
|
||||
width: 0;
|
||||
justify-content: start;
|
||||
height: 0;
|
||||
margin-left: 0.25em;
|
||||
display: flex;
|
||||
margin-top: -1.25em;
|
||||
color: black;
|
||||
.wrapper {
|
||||
width: 0;
|
||||
justify-content: start;
|
||||
height: 0;
|
||||
display: flex;
|
||||
margin-top: -1.25em;
|
||||
color: black;
|
||||
|
||||
div {
|
||||
font-size: 1em;
|
||||
line-height: 1em;
|
||||
}
|
||||
div {
|
||||
font-size: 1em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
.time,
|
||||
.speed,
|
||||
.acc {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
.time,
|
||||
.speed,
|
||||
.acc {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
.time,
|
||||
.speed,
|
||||
.acc,
|
||||
.burst {
|
||||
//opacity: 0;
|
||||
}
|
||||
&.colorMain {
|
||||
color: var(--main-color);
|
||||
}
|
||||
|
||||
&.timerMain {
|
||||
color: var(--main-color);
|
||||
}
|
||||
&.colorSub {
|
||||
color: var(--sub-color);
|
||||
}
|
||||
|
||||
&.timerSub {
|
||||
color: var(--sub-color);
|
||||
}
|
||||
|
||||
&.timerText {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
&.size125 {
|
||||
margin-top: -1.75rem;
|
||||
font-size: 1.25rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
&.size15 {
|
||||
margin-top: -2rem;
|
||||
font-size: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
&.size2 {
|
||||
margin-top: -2.5rem;
|
||||
font-size: 2rem;
|
||||
line-height: 2rem;
|
||||
}
|
||||
&.size3 {
|
||||
margin-top: -3.5rem;
|
||||
font-size: 3rem;
|
||||
line-height: 3rem;
|
||||
}
|
||||
&.size4 {
|
||||
margin-top: -4.5rem;
|
||||
font-size: 4rem;
|
||||
line-height: 4rem;
|
||||
&.colorText {
|
||||
color: var(--text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,15 +1,30 @@
|
|||
import { render } from "solid-js/web";
|
||||
import { qsr } from "../utils/dom";
|
||||
import { LiveStats } from "./test/LiveStats";
|
||||
import { getAcc, getBurst, getWpm } from "../signals/test";
|
||||
import {
|
||||
TextLiveStatsBottom,
|
||||
MiniLiveStats,
|
||||
TextLiveStatsTop,
|
||||
} from "./test/LiveStats";
|
||||
import { getAcc, getBurst, getProgress, getWpm } from "../signals/test";
|
||||
|
||||
export function mountComponents(): void {
|
||||
render(
|
||||
() => <LiveStats mode="mini" wpm={getWpm} acc={getAcc} burst={getBurst} />,
|
||||
() => (
|
||||
<MiniLiveStats
|
||||
progress={getProgress}
|
||||
wpm={getWpm}
|
||||
acc={getAcc}
|
||||
burst={getBurst}
|
||||
/>
|
||||
),
|
||||
qsr("#liveStatsMini").native,
|
||||
);
|
||||
render(
|
||||
() => <LiveStats mode="text" wpm={getWpm} acc={getAcc} burst={getBurst} />,
|
||||
() => <TextLiveStatsBottom wpm={getWpm} acc={getAcc} burst={getBurst} />,
|
||||
qsr("#liveStatsTextBottom").native,
|
||||
);
|
||||
render(
|
||||
() => <TextLiveStatsTop progress={getProgress} />,
|
||||
qsr("#liveStatsTextTop").native,
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
import { Accessor, JSXElement } from "solid-js";
|
||||
import {
|
||||
getLiveAccStyle,
|
||||
getLiveBurstStyle,
|
||||
getLiveSpeedStyle,
|
||||
} from "../../signals/config";
|
||||
|
||||
import { isFocused } from "../../test/focus";
|
||||
import {
|
||||
useVisibilityAnimation,
|
||||
VisibilityAnimationOptions,
|
||||
} from "../../hooks/useVisibilityAnimation";
|
||||
import { useRefWithUtils } from "../../hooks/useRefWithUtils";
|
||||
import { statsVisible } from "../../signals/test";
|
||||
import { getTestTime, statsVisible } from "../../signals/test";
|
||||
import Config from "../../config";
|
||||
import * as CustomText from "../../test/custom-text";
|
||||
import { getConfigSignal } from "../../signals/config";
|
||||
|
||||
function Stat(props: {
|
||||
value: Accessor<string>;
|
||||
visibilityOptions: Accessor<VisibilityAnimationOptions>;
|
||||
class?: string;
|
||||
style?: Record<string, string>;
|
||||
}): JSXElement {
|
||||
const [ref, element] = useRefWithUtils<HTMLDivElement>();
|
||||
|
||||
useVisibilityAnimation(element, props.visibilityOptions);
|
||||
|
||||
return (
|
||||
<div ref={ref} class={props.class}>
|
||||
<div ref={ref} class={props.class} style={props.style}>
|
||||
{props.value()}
|
||||
</div>
|
||||
);
|
||||
|
|
@ -37,8 +37,49 @@ const getStatsVisible = (
|
|||
});
|
||||
};
|
||||
|
||||
export function LiveStats(props: {
|
||||
mode: "mini" | "text";
|
||||
function getStatsColorClass(): string {
|
||||
const cfg = getConfigSignal();
|
||||
const configValue = cfg.timerColor;
|
||||
if (configValue === "main") {
|
||||
return "colorMain";
|
||||
} else if (configValue === "sub") {
|
||||
return "colorSub";
|
||||
} else if (configValue === "text") {
|
||||
return "colorText";
|
||||
} else if (configValue === "black") {
|
||||
return "colorBlack";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
function getFlashTimerOpacity(): string {
|
||||
let opacity = "1";
|
||||
const time = getTestTime();
|
||||
let maxtime = Config.time;
|
||||
if (Config.mode === "custom" && CustomText.getLimitMode() === "time") {
|
||||
maxtime = CustomText.getLimitValue();
|
||||
}
|
||||
|
||||
const timedTest =
|
||||
Config.mode === "time" ||
|
||||
(Config.mode === "custom" && CustomText.getLimitMode() === "time");
|
||||
|
||||
if (
|
||||
timedTest &&
|
||||
(getConfigSignal().timerStyle === "flash_mini" ||
|
||||
getConfigSignal().timerStyle === "flash_text")
|
||||
) {
|
||||
if ((maxtime - time) % 15 !== 0) {
|
||||
opacity = "0";
|
||||
} else {
|
||||
opacity = "1";
|
||||
}
|
||||
}
|
||||
return opacity;
|
||||
}
|
||||
|
||||
export function MiniLiveStats(props: {
|
||||
progress: Accessor<string>;
|
||||
wpm: Accessor<string>;
|
||||
acc: Accessor<string>;
|
||||
burst: Accessor<string>;
|
||||
|
|
@ -50,22 +91,113 @@ export function LiveStats(props: {
|
|||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
class="wrapper"
|
||||
classList={{
|
||||
[getStatsColorClass()]: true,
|
||||
}}
|
||||
style={{
|
||||
opacity: getConfigSignal().timerOpacity,
|
||||
}}
|
||||
>
|
||||
<Stat
|
||||
class="speed"
|
||||
class={"progress time"}
|
||||
value={props.progress}
|
||||
style={{ opacity: getFlashTimerOpacity() }}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() =>
|
||||
getConfigSignal().timerStyle === "mini" ||
|
||||
getConfigSignal().timerStyle === "flash_mini",
|
||||
)}
|
||||
/>
|
||||
<Stat
|
||||
class={"speed"}
|
||||
value={props.wpm}
|
||||
visibilityOptions={isVisible(getLiveSpeedStyle)}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveSpeedStyle === "mini",
|
||||
)}
|
||||
/>
|
||||
<Stat
|
||||
class="acc"
|
||||
class={"acc"}
|
||||
value={props.acc}
|
||||
visibilityOptions={isVisible(getLiveAccStyle)}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveAccStyle === "mini",
|
||||
)}
|
||||
/>
|
||||
<Stat
|
||||
class="burst"
|
||||
class={"burst"}
|
||||
value={props.burst}
|
||||
visibilityOptions={isVisible(getLiveBurstStyle)}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveBurstStyle === "mini",
|
||||
)}
|
||||
/>
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TextLiveStatsTop(props: {
|
||||
progress: Accessor<string>;
|
||||
}): JSXElement {
|
||||
return (
|
||||
<div
|
||||
class="wrapper"
|
||||
classList={{
|
||||
[getStatsColorClass()]: true,
|
||||
}}
|
||||
style={{
|
||||
opacity: getConfigSignal().timerOpacity,
|
||||
}}
|
||||
>
|
||||
<Stat
|
||||
class={"progress time"}
|
||||
value={props.progress}
|
||||
style={{ opacity: getFlashTimerOpacity() }}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() =>
|
||||
getConfigSignal().timerStyle === "text" ||
|
||||
getConfigSignal().timerStyle === "flash_text",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function TextLiveStatsBottom(props: {
|
||||
wpm: Accessor<string>;
|
||||
acc: Accessor<string>;
|
||||
burst: Accessor<string>;
|
||||
}): JSXElement {
|
||||
return (
|
||||
<div
|
||||
class="wrapper"
|
||||
classList={{
|
||||
[getStatsColorClass()]: true,
|
||||
}}
|
||||
style={{
|
||||
opacity: getConfigSignal().timerOpacity,
|
||||
}}
|
||||
>
|
||||
<Stat
|
||||
class={"liveSpeed"}
|
||||
value={props.wpm}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveSpeedStyle === "text",
|
||||
)}
|
||||
/>
|
||||
<Stat
|
||||
class={"liveAcc"}
|
||||
value={props.acc}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveAccStyle === "text",
|
||||
)}
|
||||
/>
|
||||
<Stat
|
||||
class={"liveBurst"}
|
||||
value={props.burst}
|
||||
visibilityOptions={getStatsVisible(
|
||||
() => getConfigSignal().liveBurstStyle === "text",
|
||||
)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,12 @@
|
|||
import { createSignal } from "solid-js";
|
||||
import * as ConfigEvent from "../observables/config-event";
|
||||
import config from "../config";
|
||||
import { Config } from "@monkeytype/schemas/configs";
|
||||
|
||||
const [getLiveSpeedStyle, setLiveSpeedStyle] = createSignal(
|
||||
config.liveSpeedStyle,
|
||||
);
|
||||
const [getLiveAccStyle, setLiveAccStyle] = createSignal(config.liveSpeedStyle);
|
||||
const [getLiveBurstStyle, setLiveBurstStyle] = createSignal(
|
||||
config.liveSpeedStyle,
|
||||
);
|
||||
const [getConfigSignal, setConfigSignal] = createSignal<Config>(config);
|
||||
|
||||
export { getLiveSpeedStyle, getLiveAccStyle, getLiveBurstStyle };
|
||||
export { getConfigSignal };
|
||||
|
||||
ConfigEvent.subscribe(({ key, newValue }) => {
|
||||
if (key === "liveSpeedStyle") {
|
||||
setLiveSpeedStyle(newValue);
|
||||
} else if (key === "liveAccStyle") {
|
||||
setLiveAccStyle(newValue);
|
||||
} else if (key === "liveBurstStyle") {
|
||||
setLiveBurstStyle(newValue);
|
||||
}
|
||||
ConfigEvent.subscribe(() => {
|
||||
setConfigSignal(structuredClone(config));
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,15 @@
|
|||
import { createSignal } from "solid-js";
|
||||
import { VisibilityAnimationOptions } from "../hooks/useVisibilityAnimation";
|
||||
import * as Time from "../states/time";
|
||||
import Config from "../config";
|
||||
import * as CustomText from "../test/custom-text";
|
||||
import * as DateTime from "../utils/date-and-time";
|
||||
import * as TestWords from "../test/test-words";
|
||||
import * as TestInput from "../test/test-input";
|
||||
import * as TestState from "../test/test-state";
|
||||
|
||||
export const [getTestTime, setTestTime] = createSignal(0);
|
||||
export const [getProgress, setLiveProgress] = createSignal("");
|
||||
export const [getWpm, setLiveStatWpm] = createSignal("0");
|
||||
export const [getAcc, setLiveStatAcc] = createSignal("100%");
|
||||
export const [getBurst, setLiveStatBurst] = createSignal("0");
|
||||
|
|
@ -10,3 +19,102 @@ export const [statsVisible, setStatsVisible] =
|
|||
visible: false,
|
||||
animate: true,
|
||||
});
|
||||
|
||||
function getCurrentCount(): number {
|
||||
if (Config.mode === "custom" && CustomText.getLimitMode() === "section") {
|
||||
return (
|
||||
(TestWords.words.sectionIndexList[TestState.activeWordIndex] as number) -
|
||||
1
|
||||
);
|
||||
} else {
|
||||
return TestInput.input.getHistory().length;
|
||||
}
|
||||
}
|
||||
|
||||
export function updateProgressSignal(): void {
|
||||
const time = Time.get();
|
||||
if (
|
||||
Config.mode === "time" ||
|
||||
(Config.mode === "custom" && CustomText.getLimitMode() === "time")
|
||||
) {
|
||||
let maxtime = Config.time;
|
||||
if (Config.mode === "custom" && CustomText.getLimitMode() === "time") {
|
||||
maxtime = CustomText.getLimitValue();
|
||||
}
|
||||
if (Config.timerStyle === "text") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
setLiveProgress(displayTime);
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
setLiveProgress(displayTime);
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
setLiveProgress(displayTime);
|
||||
} else if (Config.timerStyle === "mini") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
setLiveProgress(displayTime);
|
||||
}
|
||||
} else if (
|
||||
Config.mode === "words" ||
|
||||
Config.mode === "custom" ||
|
||||
Config.mode === "quote"
|
||||
) {
|
||||
let outof = TestWords.words.length;
|
||||
if (Config.mode === "words") {
|
||||
outof = Config.words;
|
||||
}
|
||||
if (Config.mode === "custom") {
|
||||
outof = CustomText.getLimitValue();
|
||||
}
|
||||
if (Config.mode === "quote") {
|
||||
outof = TestWords.currentQuote?.textSplit.length ?? 1;
|
||||
}
|
||||
if (Config.timerStyle === "text") {
|
||||
if (outof === 0) {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else {
|
||||
setLiveProgress(`${getCurrentCount()}/${outof}`);
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
if (outof === 0) {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else {
|
||||
setLiveProgress(`${getCurrentCount()}/${outof}`);
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
if (outof === 0) {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else {
|
||||
setLiveProgress(`${getCurrentCount()}/${outof}`);
|
||||
}
|
||||
} else if (Config.timerStyle === "mini") {
|
||||
if (outof === 0) {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else {
|
||||
setLiveProgress(`${getCurrentCount()}/${outof}`);
|
||||
}
|
||||
}
|
||||
} else if (Config.mode === "zen") {
|
||||
if (Config.timerStyle === "text") {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
} else {
|
||||
setLiveProgress(`${TestInput.input.getHistory().length}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { setTestTime } from "../signals/test";
|
||||
|
||||
let time = 0;
|
||||
|
||||
export function get(): number {
|
||||
|
|
@ -6,8 +8,10 @@ export function get(): number {
|
|||
|
||||
export function set(number: number): void {
|
||||
time = number;
|
||||
setTestTime(time);
|
||||
}
|
||||
|
||||
export function increment(): void {
|
||||
time++;
|
||||
setTestTime(time);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import * as Caret from "./caret";
|
||||
import * as TimerProgress from "./timer-progress";
|
||||
import * as PageTransition from "../states/page-transition";
|
||||
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";
|
||||
import { createSignal } from "solid-js";
|
||||
|
|
@ -63,7 +62,6 @@ export function set(value: boolean, withCursor = false): void {
|
|||
}
|
||||
|
||||
Caret.stopAnimation();
|
||||
TimerProgress.show();
|
||||
} else if (!value && state()) {
|
||||
setState(false);
|
||||
|
||||
|
|
@ -79,7 +77,6 @@ export function set(value: boolean, withCursor = false): void {
|
|||
}
|
||||
|
||||
Caret.startAnimation();
|
||||
TimerProgress.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
import Config, { setConfig } from "../config";
|
||||
import * as CustomText from "./custom-text";
|
||||
import * as TimerProgress from "./timer-progress";
|
||||
import * as TestStats from "./test-stats";
|
||||
import * as TestInput from "./test-input";
|
||||
import * as Monkey from "./monkey";
|
||||
|
|
@ -21,7 +20,7 @@ import { clearLowFpsMode, setLowFpsMode } from "../anim";
|
|||
import { createTimer } from "animejs";
|
||||
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";
|
||||
import Format from "../utils/format";
|
||||
import { setLiveStatWpm } from "../signals/test";
|
||||
import { setLiveStatWpm, updateProgressSignal } from "../signals/test";
|
||||
|
||||
let lastLoop = 0;
|
||||
const newTimer = createTimer({
|
||||
|
|
@ -235,7 +234,7 @@ function timerStep(): void {
|
|||
});
|
||||
|
||||
// already using raf
|
||||
TimerProgress.update();
|
||||
updateProgressSignal();
|
||||
setLiveStatWpm(
|
||||
Format.typingSpeed(Config.blindMode ? wpmAndRaw.raw : wpmAndRaw.wpm, {
|
||||
showDecimalPlaces: false,
|
||||
|
|
|
|||
|
|
@ -16,7 +16,6 @@ import * as Hangul from "hangul-js";
|
|||
import * as ResultWordHighlight from "../elements/result-word-highlight";
|
||||
import * as ActivePage from "../states/active-page";
|
||||
import Format from "../utils/format";
|
||||
import { TimerColor, TimerOpacity } from "@monkeytype/schemas/configs";
|
||||
import { convertRemToPixels } from "../utils/numbers";
|
||||
import {
|
||||
findSingleActiveFunboxWithFunction,
|
||||
|
|
@ -33,7 +32,6 @@ import * as Numbers from "@monkeytype/util/numbers";
|
|||
import * as TestStats from "./test-stats";
|
||||
import * as KeymapEvent from "../observables/keymap-event";
|
||||
import * as Focus from "../test/focus";
|
||||
import * as TimerProgress from "../test/timer-progress";
|
||||
import * as Monkey from "./monkey";
|
||||
import { animate } from "animejs";
|
||||
import {
|
||||
|
|
@ -56,10 +54,12 @@ import * as Last10Average from "../elements/last-10-average";
|
|||
import * as MemoryFunboxTimer from "./funbox/memory-funbox-timer";
|
||||
import { qsr } from "../utils/dom";
|
||||
import {
|
||||
setLiveProgress,
|
||||
setLiveStatAcc,
|
||||
setLiveStatBurst,
|
||||
setLiveStatWpm,
|
||||
setStatsVisible,
|
||||
updateProgressSignal,
|
||||
} from "../signals/test";
|
||||
|
||||
export const updateHintsPositionDebounced = Misc.debounceUntilResolved(
|
||||
|
|
@ -1586,48 +1586,6 @@ function updateLiveStatsMargin(): void {
|
|||
}
|
||||
}
|
||||
|
||||
function updateLiveStatsOpacity(value: TimerOpacity): void {
|
||||
$("#barTimerProgress").css("opacity", parseFloat(value as string));
|
||||
$("#liveStatsTextTop").css("opacity", parseFloat(value as string));
|
||||
$("#liveStatsTextBottom").css("opacity", parseFloat(value as string));
|
||||
$("#liveStatsMini").css("opacity", parseFloat(value as string));
|
||||
}
|
||||
|
||||
function updateLiveStatsColor(value: TimerColor): void {
|
||||
$("#barTimerProgress").removeClass("timerSub");
|
||||
$("#barTimerProgress").removeClass("timerText");
|
||||
$("#barTimerProgress").removeClass("timerMain");
|
||||
|
||||
$("#liveStatsTextTop").removeClass("timerSub");
|
||||
$("#liveStatsTextTop").removeClass("timerText");
|
||||
$("#liveStatsTextTop").removeClass("timerMain");
|
||||
|
||||
$("#liveStatsTextBottom").removeClass("timerSub");
|
||||
$("#liveStatsTextBottom").removeClass("timerText");
|
||||
$("#liveStatsTextBottom").removeClass("timerMain");
|
||||
|
||||
$("#liveStatsMini").removeClass("timerSub");
|
||||
$("#liveStatsMini").removeClass("timerText");
|
||||
$("#liveStatsMini").removeClass("timerMain");
|
||||
|
||||
if (value === "main") {
|
||||
$("#barTimerProgress").addClass("timerMain");
|
||||
$("#liveStatsTextTop").addClass("timerMain");
|
||||
$("#liveStatsTextBottom").addClass("timerMain");
|
||||
$("#liveStatsMini").addClass("timerMain");
|
||||
} else if (value === "sub") {
|
||||
$("#barTimerProgress").addClass("timerSub");
|
||||
$("#liveStatsTextTop").addClass("timerSub");
|
||||
$("#liveStatsTextBottom").addClass("timerSub");
|
||||
$("#liveStatsMini").addClass("timerSub");
|
||||
} else if (value === "text") {
|
||||
$("#barTimerProgress").addClass("timerText");
|
||||
$("#liveStatsTextTop").addClass("timerText");
|
||||
$("#liveStatsTextBottom").addClass("timerText");
|
||||
$("#liveStatsMini").addClass("timerText");
|
||||
}
|
||||
}
|
||||
|
||||
function showHideTestRestartButton(showHide: boolean): void {
|
||||
if (showHide) {
|
||||
$(".pageTest #restartTestButton").removeClass("hidden");
|
||||
|
|
@ -1688,7 +1646,8 @@ function afterAnyTestInput(
|
|||
}
|
||||
|
||||
if (Config.mode !== "time") {
|
||||
TimerProgress.update();
|
||||
// TimerProgress.update();
|
||||
updateProgressSignal();
|
||||
}
|
||||
|
||||
if (Config.keymapMode === "next") {
|
||||
|
|
@ -1819,8 +1778,7 @@ export async function afterTestWordChange(
|
|||
export function onTestStart(): void {
|
||||
Focus.set(true);
|
||||
Monkey.show();
|
||||
TimerProgress.show();
|
||||
TimerProgress.update();
|
||||
updateProgressSignal();
|
||||
setStatsVisible({
|
||||
visible: true,
|
||||
animate: true,
|
||||
|
|
@ -1837,11 +1795,10 @@ export function onTestRestart(source: "testPage" | "resultPage"): void {
|
|||
visible: false,
|
||||
animate: false,
|
||||
});
|
||||
setLiveProgress("0");
|
||||
setLiveStatWpm("0");
|
||||
setLiveStatBurst("0");
|
||||
setLiveStatAcc("100%");
|
||||
TimerProgress.instantHide();
|
||||
TimerProgress.reset();
|
||||
Monkey.instantHide();
|
||||
LayoutfluidFunboxTimer.instantHide();
|
||||
updatePremid();
|
||||
|
|
@ -1884,12 +1841,15 @@ export function onTestRestart(source: "testPage" | "resultPage"): void {
|
|||
|
||||
export function onTestFinish(): void {
|
||||
Caret.hide();
|
||||
TimerProgress.hide();
|
||||
OutOfFocus.hide();
|
||||
Monkey.hide();
|
||||
if (Config.playSoundOnClick === "16") {
|
||||
void SoundController.playFartReverb();
|
||||
}
|
||||
setStatsVisible({
|
||||
visible: false,
|
||||
animate: true,
|
||||
});
|
||||
}
|
||||
|
||||
$(".pageTest #copyWordsListButton").on("click", async () => {
|
||||
|
|
@ -2000,12 +1960,6 @@ ConfigEvent.subscribe(({ key, newValue }) => {
|
|||
if (key === "quickRestart") {
|
||||
showHideTestRestartButton(newValue === "off");
|
||||
}
|
||||
if (key === "timerOpacity") {
|
||||
updateLiveStatsOpacity(newValue);
|
||||
}
|
||||
if (key === "timerColor") {
|
||||
updateLiveStatsColor(newValue);
|
||||
}
|
||||
if (key === "showOutOfFocusWarning" && !newValue) {
|
||||
OutOfFocus.hide();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,269 +0,0 @@
|
|||
import Config from "../config";
|
||||
import * as CustomText from "./custom-text";
|
||||
import * as DateTime from "../utils/date-and-time";
|
||||
import * as TestWords from "./test-words";
|
||||
import * as TestInput from "./test-input";
|
||||
import * as Time from "../states/time";
|
||||
import * as TestState from "./test-state";
|
||||
import * as ConfigEvent from "../observables/config-event";
|
||||
import { applyReducedMotion } from "../utils/misc";
|
||||
import { requestDebouncedAnimationFrame } from "../utils/debounced-animation-frame";
|
||||
import { animate } from "animejs";
|
||||
|
||||
const barEl = document.querySelector("#barTimerProgress .bar") as HTMLElement;
|
||||
const barOpacityEl = document.querySelector(
|
||||
"#barTimerProgress .opacityWrapper",
|
||||
) as HTMLElement;
|
||||
const textEl = document.querySelector(
|
||||
"#liveStatsTextTop .timerProgress",
|
||||
) as HTMLElement;
|
||||
const miniEl = document.querySelector("#liveStatsMini .time") as HTMLElement;
|
||||
|
||||
export function show(): void {
|
||||
if (!TestState.isActive()) return;
|
||||
requestDebouncedAnimationFrame("timer-progress.show", () => {
|
||||
if (Config.mode !== "zen" && Config.timerStyle === "bar") {
|
||||
animate(barOpacityEl, {
|
||||
opacity: [0, 1],
|
||||
duration: applyReducedMotion(125),
|
||||
onBegin: () => {
|
||||
barOpacityEl.classList.remove("hidden");
|
||||
},
|
||||
});
|
||||
} else if (Config.timerStyle === "text") {
|
||||
animate(textEl, {
|
||||
opacity: [0, 1],
|
||||
duration: applyReducedMotion(125),
|
||||
onBegin: () => {
|
||||
textEl.classList.remove("hidden");
|
||||
},
|
||||
});
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
animate(miniEl, {
|
||||
opacity: [0, 1],
|
||||
duration: applyReducedMotion(125),
|
||||
onBegin: () => {
|
||||
miniEl.classList.remove("hidden");
|
||||
},
|
||||
});
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
animate(textEl, {
|
||||
opacity: [0, 1],
|
||||
duration: applyReducedMotion(125),
|
||||
onBegin: () => {
|
||||
textEl.classList.remove("hidden");
|
||||
},
|
||||
});
|
||||
} else if (Config.mode === "zen" || Config.timerStyle === "mini") {
|
||||
animate(miniEl, {
|
||||
opacity: [0, 1],
|
||||
duration: applyReducedMotion(125),
|
||||
onBegin: () => {
|
||||
miniEl.classList.remove("hidden");
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function reset(): void {
|
||||
requestDebouncedAnimationFrame("timer-progress.reset", () => {
|
||||
let width = "0vw";
|
||||
if (
|
||||
Config.mode === "time" ||
|
||||
(Config.mode === "custom" && CustomText.getLimitMode() === "time")
|
||||
) {
|
||||
width = "100vw";
|
||||
}
|
||||
|
||||
animate(barEl, {
|
||||
width,
|
||||
duration: 0,
|
||||
});
|
||||
miniEl.textContent = "0";
|
||||
textEl.textContent = "0";
|
||||
});
|
||||
}
|
||||
|
||||
export function hide(): void {
|
||||
requestDebouncedAnimationFrame("timer-progress.hide", () => {
|
||||
animate(barOpacityEl, {
|
||||
opacity: 0,
|
||||
duration: applyReducedMotion(125),
|
||||
});
|
||||
|
||||
animate(miniEl, {
|
||||
opacity: 0,
|
||||
duration: applyReducedMotion(125),
|
||||
onComplete: () => {
|
||||
miniEl.classList.add("hidden");
|
||||
},
|
||||
});
|
||||
|
||||
animate(textEl, {
|
||||
opacity: 0,
|
||||
duration: applyReducedMotion(125),
|
||||
onComplete: () => {
|
||||
textEl.classList.add("hidden");
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function instantHide(): void {
|
||||
barOpacityEl.style.opacity = "0";
|
||||
|
||||
miniEl.classList.add("hidden");
|
||||
miniEl.style.opacity = "0";
|
||||
|
||||
textEl.classList.add("hidden");
|
||||
textEl.style.opacity = "0";
|
||||
}
|
||||
|
||||
function getCurrentCount(): number {
|
||||
if (Config.mode === "custom" && CustomText.getLimitMode() === "section") {
|
||||
return (
|
||||
(TestWords.words.sectionIndexList[TestState.activeWordIndex] as number) -
|
||||
1
|
||||
);
|
||||
} else {
|
||||
return TestInput.input.getHistory().length;
|
||||
}
|
||||
}
|
||||
|
||||
export function update(): void {
|
||||
requestDebouncedAnimationFrame("timer-progress.update", () => {
|
||||
const time = Time.get();
|
||||
if (
|
||||
Config.mode === "time" ||
|
||||
(Config.mode === "custom" && CustomText.getLimitMode() === "time")
|
||||
) {
|
||||
let maxtime = Config.time;
|
||||
if (Config.mode === "custom" && CustomText.getLimitMode() === "time") {
|
||||
maxtime = CustomText.getLimitValue();
|
||||
}
|
||||
if (Config.timerStyle === "bar") {
|
||||
const percent = 100 - ((time + 1) / maxtime) * 100;
|
||||
|
||||
animate(barEl, {
|
||||
width: percent + "vw",
|
||||
duration: 1000,
|
||||
ease: "linear",
|
||||
});
|
||||
} else if (Config.timerStyle === "text") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
if (textEl !== null) {
|
||||
textEl.innerHTML = "<div>" + displayTime + "</div>";
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
if (miniEl !== null) {
|
||||
if ((maxtime - time) % 15 !== 0) {
|
||||
miniEl.style.opacity = "0";
|
||||
} else {
|
||||
miniEl.style.opacity = "1";
|
||||
}
|
||||
miniEl.innerHTML = "<div>" + displayTime + "</div>";
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
if (textEl !== null) {
|
||||
textEl.innerHTML =
|
||||
"<div>" +
|
||||
`${(maxtime - time) % 15 !== 0 ? "" : displayTime}` +
|
||||
"</div>";
|
||||
}
|
||||
} else if (Config.timerStyle === "mini") {
|
||||
let displayTime = DateTime.secondsToString(maxtime - time);
|
||||
if (maxtime === 0) {
|
||||
displayTime = DateTime.secondsToString(time);
|
||||
}
|
||||
if (miniEl !== null) {
|
||||
miniEl.innerHTML = displayTime;
|
||||
}
|
||||
}
|
||||
} else if (
|
||||
Config.mode === "words" ||
|
||||
Config.mode === "custom" ||
|
||||
Config.mode === "quote"
|
||||
) {
|
||||
let outof = TestWords.words.length;
|
||||
if (Config.mode === "words") {
|
||||
outof = Config.words;
|
||||
}
|
||||
if (Config.mode === "custom") {
|
||||
outof = CustomText.getLimitValue();
|
||||
}
|
||||
if (Config.mode === "quote") {
|
||||
outof = TestWords.currentQuote?.textSplit.length ?? 1;
|
||||
}
|
||||
if (Config.timerStyle === "bar") {
|
||||
const percent = Math.floor(
|
||||
((TestState.activeWordIndex + 1) / outof) * 100,
|
||||
);
|
||||
|
||||
animate(barEl, {
|
||||
width: percent + "vw",
|
||||
duration: 250,
|
||||
});
|
||||
} else if (Config.timerStyle === "text") {
|
||||
if (outof === 0) {
|
||||
textEl.innerHTML = `<div>${TestInput.input.getHistory().length}</div>`;
|
||||
} else {
|
||||
textEl.innerHTML = `<div>${getCurrentCount()}/${outof}</div>`;
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
if (outof === 0) {
|
||||
miniEl.innerHTML = `${TestInput.input.getHistory().length}`;
|
||||
} else {
|
||||
miniEl.innerHTML = `${getCurrentCount()}/${outof}`;
|
||||
}
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
if (outof === 0) {
|
||||
textEl.innerHTML = `<div>${TestInput.input.getHistory().length}</div>`;
|
||||
} else {
|
||||
textEl.innerHTML = `<div>${getCurrentCount()}/${outof}</div>`;
|
||||
}
|
||||
} else if (Config.timerStyle === "mini") {
|
||||
if (outof === 0) {
|
||||
miniEl.innerHTML = `${TestInput.input.getHistory().length}`;
|
||||
} else {
|
||||
miniEl.innerHTML = `${getCurrentCount()}/${outof}`;
|
||||
}
|
||||
}
|
||||
} else if (Config.mode === "zen") {
|
||||
if (Config.timerStyle === "text") {
|
||||
textEl.innerHTML = `<div>${TestInput.input.getHistory().length}</div>`;
|
||||
} else if (Config.timerStyle === "flash_mini") {
|
||||
miniEl.innerHTML = `${TestInput.input.getHistory().length}`;
|
||||
} else if (Config.timerStyle === "flash_text") {
|
||||
textEl.innerHTML = `<div>${TestInput.input.getHistory().length}</div>`;
|
||||
} else {
|
||||
miniEl.innerHTML = `${TestInput.input.getHistory().length}`;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function updateStyle(): void {
|
||||
if (!TestState.isActive()) return;
|
||||
hide();
|
||||
update();
|
||||
if (Config.timerStyle === "off") return;
|
||||
setTimeout(() => {
|
||||
show();
|
||||
}, 125);
|
||||
}
|
||||
|
||||
ConfigEvent.subscribe(({ key }) => {
|
||||
if (key === "timerStyle") updateStyle();
|
||||
});
|
||||
Loading…
Add table
Reference in a new issue