Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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/__tests__/setup-tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,8 @@ vi.mock("../src/ts/utils/dom", async (importOriginal) => {
getOffsetLeft: vi.fn().mockReturnValue(0),
animate: vi.fn().mockResolvedValue(null),
promiseAnimate: vi.fn().mockResolvedValue(null),
slideUp: vi.fn().mockResolvedValue(null),
slideDown: vi.fn().mockResolvedValue(null),
native: document.createElement("div"),
// @ts-expect-error - mocking private method
hasValue: vi.fn().mockReturnValue(false),
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/commandline/lists/result-screen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const commands: Command[] = [
display: "Toggle word history",
icon: "fa-align-left",
exec: (): void => {
TestUI.toggleResultWords();
void TestUI.toggleResultWords();
},
available: (): boolean => {
return TestState.resultVisible;
Expand Down
24 changes: 4 additions & 20 deletions frontend/src/ts/pages/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,30 +753,14 @@ function toggleSettingsGroup(groupName: string): void {

const groupEl = qs(`.pageSettings .settingsGroup.${groupName}`);
if (!groupEl?.hasClass("slideup")) {
groupEl?.setStyle({ overflow: "hidden" })?.animate({
height: 0,
duration: 250,
onComplete: () => {
groupEl
?.hide()
.setStyle({ height: "", overflow: "" })
.addClass("slideup");
},
});
void groupEl?.slideUp(250);
groupEl?.addClass("slideup");
$(`.pageSettings .sectionGroupTitle[group=${groupName}]`).addClass(
"rotateIcon",
);
} else {
groupEl?.show();
groupEl?.setStyle({ height: "", overflow: "hidden" });
const height = groupEl.getOffsetHeight();
groupEl?.animate({
height: [0, height],
duration: 250,
onComplete: () => {
groupEl?.setStyle({ height: "", overflow: "" }).removeClass("slideup");
},
});
void groupEl?.slideDown(250);
groupEl?.removeClass("slideup");
$(`.pageSettings .sectionGroupTitle[group=${groupName}]`).removeClass(
"rotateIcon",
);
Expand Down
24 changes: 6 additions & 18 deletions frontend/src/ts/test/replay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import config from "../config";
import * as Sound from "../controllers/sound-controller";
import * as TestInput from "./test-input";
import * as Arrays from "../utils/arrays";
import { qsr } from "../utils/dom";

type ReplayAction =
| "correctLetter"
Expand Down Expand Up @@ -30,6 +31,8 @@ let stopwatchList: NodeJS.Timeout[] = [];
const toggleButton = document.getElementById("playpauseReplayButton")
?.children[0];

const replayEl = qsr(".pageTest #resultReplay");

function replayGetWordsList(wordsListFromScript: string[]): void {
wordsList = wordsListFromScript;
}
Expand Down Expand Up @@ -187,24 +190,11 @@ function loadOldReplay(): number {
}

function toggleReplayDisplay(): void {
if ($("#resultReplay").stop(true, true).hasClass("hidden")) {
if (replayEl.isHidden()) {
initializeReplayPrompt();
loadOldReplay();
//show
if (!$("#watchReplayButton").hasClass("loaded")) {
$("#words").html(
`<div class="preloader"><i class="fas fa-fw fa-spin fa-circle-notch"></i></div>`,
);
$("#resultReplay")
.removeClass("hidden")
.css("display", "none")
.slideDown(250);
} else {
$("#resultReplay")
.removeClass("hidden")
.css("display", "none")
.slideDown(250);
}
void replayEl.slideDown(250);
} else {
//hide
if (
Expand All @@ -213,9 +203,7 @@ function toggleReplayDisplay(): void {
) {
pauseReplay();
}
$("#resultReplay").slideUp(250, () => {
$("#resultReplay").addClass("hidden");
});
void replayEl.slideUp(250);
}
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/test/result.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1121,7 +1121,7 @@ export async function update(
);

if (Config.alwaysShowWordsHistory && canQuickRestart && !GlarsesMode.get()) {
TestUI.toggleResultWords(true);
void TestUI.toggleResultWords(true);
}
AdController.updateFooterAndVerticalAds(true);
void Funbox.clear();
Expand Down
48 changes: 13 additions & 35 deletions frontend/src/ts/test/test-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import * as XPBar from "../elements/xp-bar";
import * as ModesNotice from "../elements/modes-notice";
import * as Last10Average from "../elements/last-10-average";
import * as MemoryFunboxTimer from "./funbox/memory-funbox-timer";
import { qsr } from "../utils/dom";

export const updateHintsPositionDebounced = Misc.debounceUntilResolved(
updateHintsPosition,
Expand All @@ -67,6 +68,7 @@ const wordsEl = document.querySelector(".pageTest #words") as HTMLElement;
const wordsWrapperEl = document.querySelector(
".pageTest #wordsWrapper",
) as HTMLElement;
const resultWordsHistoryEl = qsr(".pageTest #resultWordsHistory");

export let activeWordTop = 0;
export let activeWordHeight = 0;
Expand Down Expand Up @@ -1391,42 +1393,18 @@ async function loadWordsHistory(): Promise<boolean> {
return true;
}

export function toggleResultWords(noAnimation = false): void {
if (TestState.resultVisible) {
ResultWordHighlight.updateToggleWordsHistoryTime();
if ($("#resultWordsHistory").stop(true, true).hasClass("hidden")) {
//show

if ($("#resultWordsHistory .words .word").length === 0) {
void loadWordsHistory().then(() => {
if (Config.burstHeatmap) {
void applyBurstHeatmap();
}
$("#resultWordsHistory")
.removeClass("hidden")
.css("display", "none")
.slideDown(noAnimation ? 0 : 250, () => {
if (Config.burstHeatmap) {
void applyBurstHeatmap();
}
});
});
} else {
if (Config.burstHeatmap) {
void applyBurstHeatmap();
}
$("#resultWordsHistory")
.removeClass("hidden")
.css("display", "none")
.slideDown(noAnimation ? 0 : 250);
}
} else {
//hide
export async function toggleResultWords(noAnimation = false): Promise<void> {
if (!TestState.resultVisible) return;
ResultWordHighlight.updateToggleWordsHistoryTime();

$("#resultWordsHistory").slideUp(250, () => {
$("#resultWordsHistory").addClass("hidden");
});
if (resultWordsHistoryEl.isHidden()) {
if (resultWordsHistoryEl.qsa(".words .word").length === 0) {
await loadWordsHistory();
}
void resultWordsHistoryEl.slideDown(noAnimation ? 0 : 250);
void applyBurstHeatmap();
} else {
void resultWordsHistoryEl.slideUp(noAnimation ? 0 : 250);
}
}

Expand Down Expand Up @@ -2005,7 +1983,7 @@ $("#wordsInput").on("focusout", () => {
});

$(".pageTest").on("click", "#showWordHistoryButton", () => {
toggleResultWords();
void toggleResultWords();
});

$("#wordsWrapper").on("click", () => {
Expand Down
49 changes: 49 additions & 0 deletions frontend/src/ts/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,13 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
return this;
}

/**
* Check if the element has the "hidden" class
*/
isHidden(): boolean {
return this.hasClass("hidden");
}

/**
* Check if element is visible
*/
Expand Down Expand Up @@ -669,6 +676,48 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
});
}

/**
* Animate the element sliding down (expanding height from 0 to full height)
* @param duration The duration of the animation in milliseconds (default: 250ms)
*/
async slideDown(duration = 250): Promise<void> {
this.show().setStyle({ height: "", overflow: "hidden" });
const height = this.getOffsetHeight();
this.setStyle({ height: "0px" });
await this.promiseAnimate({
height: [0, height],
duration,
onComplete: () => {
this.setStyle({ height: "", overflow: "" });
},
});
}

/**
* Animate the element sliding up (collapsing height from full height to 0)
* @param duration The duration of the animation in milliseconds (default: 250ms)
*/
async slideUp(duration = 250): Promise<void> {
this.show().setStyle({ overflow: "hidden" });
const height = this.getOffsetHeight();
const marginTop = this.getStyle().marginTop;
const marginBottom = this.getStyle().marginBottom;
await this.promiseAnimate({
height: [height, 0],
marginTop: [marginTop, 0],
marginBottom: [marginBottom, 0],
duration,
onComplete: () => {
this.setStyle({
height: "",
overflow: "",
marginTop: "",
marginBottom: "",
}).hide();
},
});
}

/**
* Focus the element
*/
Expand Down