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
2 changes: 1 addition & 1 deletion frontend/src/ts/components/layout/header/Logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export function Logo(): JSXElement {
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="-680 -1030 300 180"
class={cn("fill-[currentColor] text-main transition-colors", {
class={cn("h-full fill-[currentColor] text-main transition-colors", {
"text-sub": getFocus(),
})}
>
Expand Down
42 changes: 41 additions & 1 deletion frontend/src/ts/components/layout/header/Nav.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
import { useQuery } from "@tanstack/solid-query";
import { createMemo, JSXElement, Show } from "solid-js";
import {
createMemo,
createSignal,
JSXElement,
onCleanup,
Show,
} from "solid-js";

import { restartTestEvent } from "../../../events/test";
import { createEffectOn } from "../../../hooks/effects";
import { useRefWithUtils } from "../../../hooks/useRefWithUtils";
import {
prefetchAboutPage,
prefetchLeaderboardPage,
Expand All @@ -27,6 +34,19 @@ import { AccountMenu } from "./AccountMenu";
import { AccountXpBar } from "./AccountXpBar";

export function Nav(): JSXElement {
const [getAccountMenuOpen, setAccountMenuOpen] = createSignal(false);
const isCoarse = () => window.matchMedia("(pointer: coarse)").matches;
const [accountMenuRef, accountMenuEl] = useRefWithUtils<HTMLDivElement>();

const handleClickOutside = (e: MouseEvent) => {
const el = accountMenuEl();
if (getAccountMenuOpen() && el && !el.native.contains(e.target as Node)) {
setAccountMenuOpen(false);
}
};
document.addEventListener("click", handleClickOutside);
onCleanup(() => document.removeEventListener("click", handleClickOutside));

const buttonClass = () =>
cn("aspect-square", {
"opacity-(--nav-focus-opacity)": getFocus(),
Expand Down Expand Up @@ -154,12 +174,27 @@ export function Nav(): JSXElement {
then={(snap) => (
<>
<div
ref={accountMenuRef}
class={cn(
"relative",
!getFocus() &&
"hover:**:data-[ui-element='accountMenu']:pointer-events-auto hover:**:data-[ui-element='accountMenu']:opacity-100",
"has-focus-visible:**:data-[ui-element='accountMenu']:pointer-events-auto has-focus-visible:**:data-[ui-element='accountMenu']:opacity-100",
getAccountMenuOpen() &&
"**:data-[ui-element='accountMenu']:pointer-events-auto **:data-[ui-element='accountMenu']:opacity-100",
)}
// oxlint-disable-next-line react/no-unknown-property
on:click={(e: MouseEvent) => {
if (isCoarse()) {
if (e.target instanceof HTMLAnchorElement) {
if (e.target.dataset["navItem"] === "account") {
e.preventDefault();
e.stopPropagation();
}
setAccountMenuOpen((prev) => !prev);
}
}
}}
>
<Button
variant="text"
Expand Down Expand Up @@ -187,6 +222,11 @@ export function Nav(): JSXElement {
</Button>
<AccountMenu
showFriendsNotificationBubble={showFriendsNotificationBubble()}
// onClick={() => {
// if (isCoarse()) {
// setAccountMenuOpen(false);
// }
// }}
/>
</div>
<div class="relative">
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/ts/components/pages/test/TestConfig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ export function TestConfig(): JSXElement {
<Mode2 />
</div>
<Button
class={cn("flex place-self-center px-4 py-2 text-sub sm:hidden")}
class={cn(
"mx-auto flex place-self-center px-4 py-2 text-sub sm:hidden",
)}
variant="button"
onClick={() => {
showModal("MobileTestConfig");
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/ts/controllers/challenge-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -375,9 +375,9 @@ export async function setup(challengeName: string): Promise<boolean> {
qs(".page.pageTest")?.show();

if (notitext === undefined) {
showNoticeNotification(`Challenge '${challenge.display}' loaded.`);
showSuccessNotification(`Challenge '${challenge.display}' loaded.`);
} else {
showNoticeNotification("Challenge loaded. " + notitext);
showSuccessNotification("Challenge loaded. " + notitext);
}
setLoadedChallenge(challenge);
challengeLoading = false;
Expand Down
29 changes: 13 additions & 16 deletions frontend/src/ts/controllers/url-handler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -309,35 +309,32 @@ export function loadTestSettingsFromUrl(getOverride?: string): void {
}
}

export function loadChallengeFromUrl(getOverride?: string): void {
export async function loadChallengeFromUrl(
getOverride?: string,
): Promise<void> {
const getValue = (
Misc.findGetParameter("challenge", getOverride) ?? ""
).toLowerCase();
if (getValue === "") return;

showNoticeNotification("Loading challenge");
ChallengeController.setup(getValue)
.then((result) => {
if (result) {
showSuccessNotification("Challenge loaded");
restartTest({
nosave: true,
});
}
})
.catch((e: unknown) => {
showErrorNotification("Failed to load challenge");
console.error(e);
const result = await ChallengeController.setup(getValue);
if (result) {
restartTest({
nosave: true,
});
}
}

authEvent.subscribe((event) => {
authEvent.subscribe(async (event) => {
if (event.type === "authStateChanged") {
const search = window.location.search;
const hash = window.location.hash;

await event.data.loadPromise;

loadCustomThemeFromUrl(search);
loadTestSettingsFromUrl(search);
loadChallengeFromUrl(search);
void loadChallengeFromUrl(search);
void linkDiscord(hash);
}
});
4 changes: 2 additions & 2 deletions frontend/src/ts/dev/signal-tracker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,14 @@ type SolidOwner = {
function getCallerInfo(): { isUserCode: boolean; source: string } {
const stack = new Error().stack;
if (stack === undefined) return { isUserCode: false, source: "" };
const frames = stack.split("\n").slice(1);
const frames = stack.split("\n");

if (frames.some((f) => f.includes("useRefWithUtils"))) {
return { isUserCode: false, source: "" };
}

for (const frame of frames.toReversed()) {
if (frame === "") continue;
if (frame === "" || frame === "Error") continue;
if (frame.includes("signal-tracker")) continue;
if (frame.includes("solid-js")) continue;
if (frame.includes("@solid-refresh")) continue;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/elements/settings/fps-limit-section.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export function update(): void {
}

function save(value: number): void {
if (setfpsLimit(value)) {
if (getfpsLimit() !== value && setfpsLimit(value)) {
showNoticeNotification("FPS limit updated");
}
update();
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/test/test-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ async function joinOverlappingHints(
activeWordLetters: ElementsWithUtils,
hintElements: HTMLCollection,
): Promise<void> {
const [isWordRightToLeft, _isFullMatch] = Strings.isWordRightToLeft(
const [isWordRightToLeft] = Strings.isWordRightToLeft(
TestWords.words.getCurrent(),
TestState.isLanguageRightToLeft,
TestState.isDirectionReversed,
Expand Down
Loading