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
2 changes: 2 additions & 0 deletions frontend/src/html/pages/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,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>
<mount data-component="testmodesnotice"></mount>

<div id="liveStatsTextTop" class="timerMain">
<div class="wrapper">
<div class="timerProgress hidden">1:00</div>
Expand Down
48 changes: 39 additions & 9 deletions frontend/src/ts/collections/results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
useLiveQuery,
} from "@tanstack/solid-db";
import { queryOptions } from "@tanstack/solid-query";
import { Accessor } from "solid-js";
import { Accessor, createMemo } from "solid-js";
import Ape from "../ape";
import { SnapshotResult } from "../constants/default-snapshot";
import { createEffectOn } from "../hooks/effects";
Expand All @@ -34,8 +34,12 @@ import {
getTagsOnce,
reconcileLocalTagPB,
saveLocalTagPB,
useActiveTagsLiveQuery,
} from "./tags";
import { applyIdWorkaround } from "./utils/misc";
import { getConfig } from "../config/store";
import { getMode2 } from "../utils/misc";
import { getCurrentQuote } from "../states/test";

export type ResultsQueryState = {
difficulty: SnapshotResult<Mode>["difficulty"][];
Expand Down Expand Up @@ -216,7 +220,6 @@ const resultsCollection = createCollection(
queryFn: async () => {
if (!isAuthenticated()) return [];
const tagIds = await getTagsOnce();

const knownTagIds = new Set([...tagIds.map((it) => it._id)]);
//const options = parseLoadSubsetOptions(ctx.meta?.loadSubsetOptions);

Expand Down Expand Up @@ -581,12 +584,40 @@ export type CurrentSettingsFilter = {
lazyMode: boolean;
};

export async function getUserAverage10(
// oxlint-disable-next-line typescript/explicit-function-return-type
export function useUserAverage10LiveQuery(options: {
isEnabled: Accessor<boolean>;
}) {
const queryOptions = createMemo(() => ({
...getConfig,
mode2: getMode2(getConfig, getCurrentQuote()),
}));

const activeTagsQuery = useActiveTagsLiveQuery();

return useLiveQuery((q) => {
//disable query
if (!options.isEnabled()) return undefined;

return q
.from({
//we use sub-query to filter first and then aggregate
last10: buildSettingsResultsQuery(queryOptions(), {
tagIds: activeTagsQuery().map((it) => it._id),
})
.orderBy(({ r }) => r.timestamp, "desc")
.limit(10),
})
.select(({ last10 }) => ({ wpm: avg(last10.wpm), acc: avg(last10.acc) }))
.findOne();
});
}

export async function getUserAverage10Once(
options: CurrentSettingsFilter,
): Promise<{ wpm: number; acc: number }> {
//exit early if there is no user. Don't init the result collection
if (!isAuthenticated()) return { wpm: 0, acc: 0 };

const tagIds = (await getActiveTagsOnce()).map((it) => it._id);

const result = await queryOnce((q) =>
Expand All @@ -597,15 +628,14 @@ export async function getUserAverage10(
.orderBy(({ r }) => r.timestamp, "desc")
.limit(10),
})
.select(({ last10 }) => ({ wpm: avg(last10.wpm), acc: avg(last10.acc) })),
.select(({ last10 }) => ({ wpm: avg(last10.wpm), acc: avg(last10.acc) }))
.findOne(),
);

return result.length === 1 && result[0] !== undefined
? result[0]
: { wpm: 0, acc: 0 };
return result ?? { wpm: 0, acc: 0 };
}

export async function getUserDailyBest(
export async function getUserDailyBestOnce(
options: CurrentSettingsFilter,
): Promise<{ wpm: number; acc: number }> {
//exit early if there is no user. Don't init the result collection
Expand Down
10 changes: 10 additions & 0 deletions frontend/src/ts/collections/tags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,16 @@ export async function getTagsOnce() {
});
}

// oxlint-disable-next-line typescript/explicit-function-return-type
export function useActiveTagsLiveQuery() {
return useLiveQuery((q) => {
return q
.from({ tag: tagsCollection })
.where(({ tag }) => eq(tag.active, true))
.orderBy(({ tag }) => tag.name, "asc");
});
}

type ActionType = {
insertTag: {
name: string;
Expand Down
15 changes: 8 additions & 7 deletions frontend/src/ts/commandline/commandline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,19 @@ import {
setCommandlineSubgroup,
} from "../states/core";
import { showLoaderBar, hideLoaderBar } from "../states/loader-bar";
import { Command, CommandsSubgroup, CommandWithValidation } from "./types";
import {
Command,
CommandlineSubgroupKey,
CommandsSubgroup,
CommandWithValidation,
} from "./types";
import { areSortedArraysEqual, areUnsortedArraysEqual } from "../utils/arrays";
import { parseIntOptional } from "../utils/numbers";
import { debounce } from "throttle-debounce";
import { intersect } from "@monkeytype/util/arrays";
import { createInputEventHandler } from "../elements/input-validation";
import { isInputElementFocused } from "../input/input-element";
import { qs } from "../utils/dom";
import { ConfigKey } from "@monkeytype/schemas/configs";
import { createEffect } from "solid-js";
import {
getModalVisibility,
Expand Down Expand Up @@ -82,10 +86,7 @@ function addCommandlineBackground(): void {
}

type ShowSettings = {
subgroupOverride?:
| CommandsSubgroup
| CommandlineLists.ListsObjectKeys
| ConfigKey;
subgroupOverride?: CommandsSubgroup | CommandlineSubgroupKey;
commandOverride?: string;
singleListOverride?: boolean;
};
Expand Down Expand Up @@ -123,7 +124,7 @@ export function show(
if (exists) {
showLoaderBar();
subgroupOverride = await CommandlineLists.getList(
overrideStringOrGroup as CommandlineLists.ListsObjectKeys,
overrideStringOrGroup as CommandlineSubgroupKey,
);
hideLoaderBar();
} else {
Expand Down
12 changes: 5 additions & 7 deletions frontend/src/ts/commandline/lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
} from "../states/notifications";
import * as VideoAdPopup from "../popups/video-ad-popup";
import * as TestStats from "../test/test-stats";
import { Command, CommandsSubgroup } from "./types";
import { Command, CommandlineListKey, CommandsSubgroup } from "./types";
import { buildCommandForConfigKey } from "./util";
import { CommandlineConfigMetadataObject } from "./commandline-metadata";
import { isAuthAvailable, signOut } from "../firebase";
Expand Down Expand Up @@ -376,7 +376,7 @@ export const commands: CommandsSubgroup = {
],
};

const lists = {
const lists: Record<CommandlineListKey, CommandsSubgroup | undefined> = {
themes: ThemesCommands[0]?.subgroup,
loadChallenge: LoadChallengeCommands[0]?.subgroup,
minBurst: MinBurstCommands[0]?.subgroup,
Expand All @@ -396,11 +396,11 @@ export function doesListExist(listName: string): boolean {
return true;
}

return lists[listName as ListsObjectKeys] !== undefined;
return lists[listName as CommandlineListKey] !== undefined;
}

export async function getList(
listName: ListsObjectKeys | ConfigKey,
listName: CommandlineListKey | ConfigKey,
): Promise<CommandsSubgroup> {
await Promise.allSettled([challengesPromise]);

Expand All @@ -409,7 +409,7 @@ export async function getList(
return subGroup;
}

const list = lists[listName as ListsObjectKeys];
const list = lists[listName as CommandlineListKey];
if (!list) {
showErrorNotification(`List not found: ${listName}`);
throw new Error(`List ${listName} not found`);
Expand All @@ -425,8 +425,6 @@ export function getStackLength(): number {
return stack.length;
}

export type ListsObjectKeys = keyof typeof lists;

export function setStackToDefault(): void {
setStack([commands]);
}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/commandline/lists/bail-out.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { Config } from "../../config/store";
import { getCustomTextIndicator } from "../../states/core";
import * as CustomText from "../../test/custom-text";
import * as TestLogic from "../../test/test-logic";
import * as TestState from "../../test/test-state";
import * as CustomTextState from "../../legacy-states/custom-text-name";
import { Command, CommandsSubgroup } from "../types";

function canBailOut(): boolean {
return (
(Config.mode === "custom" && CustomTextState.isCustomTextLong() === true) ||
(Config.mode === "custom" && getCustomTextIndicator()?.isLong === true) ||
(Config.mode === "custom" &&
(CustomText.getLimitMode() === "word" ||
CustomText.getLimitMode() === "section") &&
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/ts/commandline/lists/quote-favorites.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import {
} from "../../states/notifications";
import { isAuthenticated } from "../../states/core";
import { showLoaderBar, hideLoaderBar } from "../../states/loader-bar";
import * as TestWords from "../../test/test-words";
import { Command } from "../types";
import { getCurrentQuote } from "../../states/test";

const commands: Command[] = [
{
id: "addQuoteToFavorite",
display: "Add current quote to favorite",
icon: "fa-heart",
available: (): boolean => {
const quote = TestWords.currentQuote;
const quote = getCurrentQuote();
return (
isAuthenticated() &&
quote !== null &&
Expand All @@ -27,7 +27,7 @@ const commands: Command[] = [
try {
showLoaderBar();
await QuotesController.setQuoteFavorite(
TestWords.currentQuote as Quote,
getCurrentQuote() as Quote,
true,
);
hideLoaderBar();
Expand All @@ -43,7 +43,7 @@ const commands: Command[] = [
display: "Remove current quote from favorite",
icon: "fa-heart-broken",
available: (): boolean => {
const quote = TestWords.currentQuote;
const quote = getCurrentQuote();
return (
isAuthenticated() &&
quote !== null &&
Expand All @@ -55,7 +55,7 @@ const commands: Command[] = [
try {
showLoaderBar();
await QuotesController.setQuoteFavorite(
TestWords.currentQuote as Quote,
getCurrentQuote() as Quote,
false,
);
hideLoaderBar();
Expand Down
11 changes: 10 additions & 1 deletion frontend/src/ts/commandline/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Config } from "@monkeytype/schemas/configs";
import { Config, ConfigKey } from "@monkeytype/schemas/configs";
import AnimatedModal from "../utils/animated-modal";
import { Validation } from "../types/validation";

Expand Down Expand Up @@ -57,6 +57,15 @@ export type CommandsSubgroup = {
beforeList?: () => void;
};

export type CommandlineSubgroupKey = ConfigKey | CommandlineListKey;
export type CommandlineListKey =
| "themes"
| "loadChallenge"
| "minBurst"
| "funbox"
| "tags"
| "ads";

export function withValidation<T>(command: CommandWithValidation<T>): Command {
return command as unknown as Command;
}
18 changes: 9 additions & 9 deletions frontend/src/ts/components/modals/CustomTextModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import type { FaSolidIcon } from "../../types/font-awesome";
import { setConfig } from "../../config/setters";
import { Config } from "../../config/store";
import { restartTestEvent } from "../../events/test";
import * as CustomTextState from "../../legacy-states/custom-text-name";
import {
getCustomTextIndicator,
setCustomTextIndicator,
} from "../../states/core";
import { hideModalAndClearChain, showModal } from "../../states/modals";
import {
showNoticeNotification,
Expand Down Expand Up @@ -276,7 +279,7 @@ export function CustomTextModal(): JSXElement {
});
});

setLongTextWarning(CustomTextState.isCustomTextLong() ?? false);
setLongTextWarning(getCustomTextIndicator()?.isLong ?? false);
setChallengeWarning(getLoadedChallenge() !== null);
};

Expand All @@ -285,8 +288,8 @@ export function CustomTextModal(): JSXElement {
if (data === null) return;
setIncomingChainedData(null);

if (data.long !== true && CustomTextState.isCustomTextLong()) {
CustomTextState.setCustomTextName("", undefined);
if (data.long !== true && getCustomTextIndicator()?.isLong) {
setCustomTextIndicator(undefined);
showNoticeNotification("Disabled long custom text progress tracking", {
durationMs: 5000,
});
Expand Down Expand Up @@ -358,11 +361,8 @@ export function CustomTextModal(): JSXElement {
if (e.code === "Enter" && e.ctrlKey) {
void form.handleSubmit();
}
if (
CustomTextState.isCustomTextLong() &&
CustomTextState.getCustomTextName() !== ""
) {
CustomTextState.setCustomTextName("", undefined);
if (getCustomTextIndicator()?.isLong) {
setCustomTextIndicator(undefined);
setLongTextWarning(false);
showNoticeNotification("Disabled long custom text progress tracking", {
durationMs: 5000,
Expand Down
Loading
Loading