mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-02 05:24:50 +08:00
refactor: use ElementWithUtils in page class (@fehmer) (#7223)
This commit is contained in:
parent
735740da98
commit
2b380bb931
16 changed files with 50 additions and 25 deletions
|
|
@ -64,6 +64,7 @@ vi.mock("../src/ts/utils/dom", () => {
|
|||
getOffsetTop: vi.fn().mockReturnValue(0),
|
||||
getOffsetLeft: vi.fn().mockReturnValue(0),
|
||||
animate: vi.fn().mockResolvedValue(null),
|
||||
promiseAnimate: vi.fn().mockResolvedValue(null),
|
||||
native: document.createElement("div"),
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -59,14 +59,14 @@ async function showSyncLoading({
|
|||
loadingOptions: LoadingOptions[];
|
||||
totalDuration: number;
|
||||
}): Promise<void> {
|
||||
PageLoading.page.element.removeClass("hidden").css("opacity", 0);
|
||||
PageLoading.page.element.show().setStyle({ opacity: "0" });
|
||||
await PageLoading.page.beforeShow({});
|
||||
|
||||
const fillDivider = loadingOptions.length;
|
||||
const fillOffset = 100 / fillDivider;
|
||||
|
||||
//void here to run the loading promise as soon as possible
|
||||
void Misc.promiseAnimate(PageLoading.page.element[0] as HTMLElement, {
|
||||
void PageLoading.page.element.promiseAnimate({
|
||||
opacity: "1",
|
||||
duration: totalDuration / 2,
|
||||
});
|
||||
|
|
@ -97,13 +97,13 @@ async function showSyncLoading({
|
|||
}
|
||||
}
|
||||
|
||||
await Misc.promiseAnimate(PageLoading.page.element[0] as HTMLElement, {
|
||||
await PageLoading.page.element.promiseAnimate({
|
||||
opacity: "0",
|
||||
duration: totalDuration / 2,
|
||||
});
|
||||
|
||||
await PageLoading.page.afterHide();
|
||||
PageLoading.page.element.addClass("hidden");
|
||||
PageLoading.page.element.hide();
|
||||
}
|
||||
|
||||
// Global abort controller for keyframe promises
|
||||
|
|
@ -206,12 +206,12 @@ export async function change(
|
|||
|
||||
//previous page
|
||||
await previousPage?.beforeHide?.();
|
||||
previousPage.element.removeClass("hidden").css("opacity", 1);
|
||||
await Misc.promiseAnimate(previousPage.element[0] as HTMLElement, {
|
||||
previousPage.element.show().setStyle({ opacity: "1" });
|
||||
await previousPage.element.promiseAnimate({
|
||||
opacity: "0",
|
||||
duration: totalDuration / 2,
|
||||
});
|
||||
previousPage.element.addClass("hidden");
|
||||
previousPage.element.hide();
|
||||
await previousPage?.afterHide();
|
||||
|
||||
// we need to evaluate and store next page loading mode in case options.loadingOptions.loadingMode is sync
|
||||
|
|
@ -281,8 +281,8 @@ export async function change(
|
|||
});
|
||||
}
|
||||
|
||||
nextPage.element.removeClass("hidden").css("opacity", 0);
|
||||
await Misc.promiseAnimate(nextPage.element[0] as HTMLElement, {
|
||||
nextPage.element.show().setStyle({ opacity: "0" });
|
||||
await nextPage.element.promiseAnimate({
|
||||
opacity: "1",
|
||||
duration: totalDuration / 2,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import Page from "./page";
|
||||
import * as Skeleton from "../utils/skeleton";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
export const page = new Page({
|
||||
id: "404",
|
||||
element: $(".page.page404"),
|
||||
element: qsr(".page.page404"),
|
||||
path: "/404",
|
||||
afterHide: async (): Promise<void> => {
|
||||
Skeleton.remove("page404");
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import * as Skeleton from "../utils/skeleton";
|
|||
import { TypingStats, SpeedHistogram } from "@monkeytype/schemas/public";
|
||||
import { getNumberWithMagnitude, numberWithSpaces } from "../utils/numbers";
|
||||
import { tryCatch } from "@monkeytype/util/trycatch";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
function reset(): void {
|
||||
$(".pageAbout .contributors").empty();
|
||||
|
|
@ -199,7 +200,7 @@ function getHistogramDataBucketed(data: Record<string, number>): {
|
|||
|
||||
export const page = new Page({
|
||||
id: "about",
|
||||
element: $(".page.pageAbout"),
|
||||
element: qsr(".page.pageAbout"),
|
||||
path: "/about",
|
||||
afterHide: async (): Promise<void> => {
|
||||
reset();
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import * as BlockedUserTable from "../elements/account-settings/blocked-user-tab
|
|||
import * as Notifications from "../elements/notifications";
|
||||
import { z } from "zod";
|
||||
import * as AuthEvent from "../observables/auth-event";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
const pageElement = $(".page.pageAccountSettings");
|
||||
|
||||
|
|
@ -229,7 +230,7 @@ AuthEvent.subscribe((event) => {
|
|||
export const page = new PageWithUrlParams({
|
||||
id: "accountSettings",
|
||||
display: "Account Settings",
|
||||
element: pageElement,
|
||||
element: qsr(".page.pageAccountSettings"),
|
||||
path: "/account-settings",
|
||||
urlParamsSchema: UrlParameterSchema,
|
||||
afterHide: async (): Promise<void> => {
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import { SnapshotResult } from "../constants/default-snapshot";
|
|||
import Ape from "../ape";
|
||||
import { AccountChart } from "@monkeytype/schemas/configs";
|
||||
import { SortedTableWithLimit } from "../utils/sorted-table";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
let filterDebug = false;
|
||||
//toggle filterdebug
|
||||
|
|
@ -1195,7 +1196,7 @@ ConfigEvent.subscribe(({ key }) => {
|
|||
|
||||
export const page = new Page<undefined>({
|
||||
id: "account",
|
||||
element: $(".page.pageAccount"),
|
||||
element: qsr(".page.pageAccount"),
|
||||
path: "/account",
|
||||
loadingOptions: {
|
||||
loadingMode: () => {
|
||||
|
|
|
|||
|
|
@ -30,8 +30,7 @@ import { Friend, UserNameSchema } from "@monkeytype/schemas/users";
|
|||
import * as Loader from "../elements/loader";
|
||||
import { LocalStorageWithSchema } from "../utils/local-storage-with-schema";
|
||||
import { remoteValidation } from "../utils/remote-validation";
|
||||
|
||||
const pageElement = $(".page.pageFriends");
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
let friendsTable: SortedTable<Friend> | undefined = undefined;
|
||||
|
||||
|
|
@ -499,7 +498,7 @@ function update(): void {
|
|||
export const page = new Page<undefined>({
|
||||
id: "friends",
|
||||
display: "Friends",
|
||||
element: pageElement,
|
||||
element: qsr(".page.pageFriends"),
|
||||
path: "/friends",
|
||||
loadingOptions: {
|
||||
loadingMode: () => {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ import { isSafeNumber } from "@monkeytype/util/numbers";
|
|||
import { Mode, Mode2, ModeSchema } from "@monkeytype/schemas/shared";
|
||||
import * as ServerConfiguration from "../ape/server-configuration";
|
||||
import { getAvatarElement } from "../utils/discord-avatar";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
const LeaderboardTypeSchema = z.enum(["allTime", "weekly", "daily"]);
|
||||
type LeaderboardType = z.infer<typeof LeaderboardTypeSchema>;
|
||||
|
|
@ -1489,7 +1490,7 @@ $(".page.pageLeaderboards .buttonGroup.friendsOnlyButtons").on(
|
|||
|
||||
export const page = new PageWithUrlParams({
|
||||
id: "leaderboards",
|
||||
element: $(".page.pageLeaderboards"),
|
||||
element: qsr(".page.pageLeaderboards"),
|
||||
path: "/leaderboards",
|
||||
urlParamsSchema: UrlParameterSchema,
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import Page from "./page";
|
||||
import * as Skeleton from "../utils/skeleton";
|
||||
import { promiseAnimate } from "../utils/misc";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
const pageEl = $(".page.pageLoading");
|
||||
const barEl = pageEl.find(".bar");
|
||||
|
|
@ -45,7 +46,7 @@ export async function showBar(): Promise<void> {
|
|||
|
||||
export const page = new Page({
|
||||
id: "loading",
|
||||
element: pageEl,
|
||||
element: qsr(".page.pageLoading"),
|
||||
path: "/",
|
||||
afterHide: async (): Promise<void> => {
|
||||
Skeleton.remove("pageLoading");
|
||||
|
|
|
|||
|
|
@ -208,7 +208,7 @@ new ValidatedHtmlInputElement(passwordVerifyInputEl, {
|
|||
|
||||
export const page = new Page({
|
||||
id: "login",
|
||||
element: $(".page.pageLogin"),
|
||||
element: qsr(".page.pageLogin"),
|
||||
path: "/login",
|
||||
afterHide: async (): Promise<void> => {
|
||||
hidePreloader();
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import {
|
|||
safeParse as parseUrlSearchParams,
|
||||
serialize as serializeUrlSearchParams,
|
||||
} from "zod-urlsearchparams";
|
||||
import { ElementWithUtils } from "../utils/dom";
|
||||
|
||||
export type PageName =
|
||||
| "loading"
|
||||
|
|
@ -69,7 +70,7 @@ export type LoadingOptions = {
|
|||
type PageProperties<T> = {
|
||||
id: PageName;
|
||||
display?: string;
|
||||
element: JQuery;
|
||||
element: ElementWithUtils;
|
||||
path: string;
|
||||
loadingOptions?: LoadingOptions;
|
||||
beforeHide?: () => Promise<void>;
|
||||
|
|
@ -84,7 +85,7 @@ async function empty(): Promise<void> {
|
|||
export default class Page<T> {
|
||||
public id: PageName;
|
||||
public display: string | undefined;
|
||||
public element: JQuery;
|
||||
public element: ElementWithUtils;
|
||||
public pathname: string;
|
||||
public loadingOptions: LoadingOptions | undefined;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function disableButton(): void {
|
|||
|
||||
export const page = new Page({
|
||||
id: "profileSearch",
|
||||
element: $(".page.pageProfileSearch"),
|
||||
element: qsr(".page.pageProfileSearch"),
|
||||
path: "/profile",
|
||||
afterHide: async (): Promise<void> => {
|
||||
Skeleton.remove("pageProfileSearch");
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import * as TestActivity from "../elements/test-activity";
|
|||
import { TestActivityCalendar } from "../elements/test-activity-calendar";
|
||||
import { getFirstDayOfTheWeek } from "../utils/date-and-time";
|
||||
import { addFriend } from "./friends";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
const firstDayOfTheWeek = getFirstDayOfTheWeek();
|
||||
|
||||
|
|
@ -260,7 +261,7 @@ $(".page.pageProfile").on("click", ".profile .addFriendButton", async () => {
|
|||
|
||||
export const page = new Page<undefined | UserProfile>({
|
||||
id: "profile",
|
||||
element: $(".page.pageProfile"),
|
||||
element: qsr(".page.pageProfile"),
|
||||
path: "/profile",
|
||||
afterHide: async (): Promise<void> => {
|
||||
Skeleton.remove("pageProfile");
|
||||
|
|
|
|||
|
|
@ -1011,7 +1011,7 @@ AuthEvent.subscribe((event) => {
|
|||
|
||||
export const page = new PageWithUrlParams({
|
||||
id: "settings",
|
||||
element: $(".page.pageSettings"),
|
||||
element: qsr(".page.pageSettings"),
|
||||
path: "/settings",
|
||||
urlParamsSchema: StateSchema,
|
||||
afterHide: async (): Promise<void> => {
|
||||
|
|
|
|||
|
|
@ -9,10 +9,11 @@ import * as Keymap from "../elements/keymap";
|
|||
import * as TestConfig from "../test/test-config";
|
||||
import * as ScrollToTop from "../elements/scroll-to-top";
|
||||
import { blurInputElement } from "../input/input-element";
|
||||
import { qsr } from "../utils/dom";
|
||||
|
||||
export const page = new Page({
|
||||
id: "test",
|
||||
element: $(".page.pageTest"),
|
||||
element: qsr(".page.pageTest"),
|
||||
path: "/",
|
||||
beforeHide: async (): Promise<void> => {
|
||||
blurInputElement();
|
||||
|
|
|
|||
|
|
@ -514,6 +514,22 @@ export class ElementWithUtils<T extends HTMLElement = HTMLElement> {
|
|||
animate(animationParams: AnimationParams): JSAnimation {
|
||||
return animejsAnimate(this.native, animationParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate the element using Anime.js
|
||||
* @param animationParams The Anime.js animation parameters
|
||||
*/
|
||||
async promiseAnimate(animationParams: AnimationParams): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
animejsAnimate(this.native, {
|
||||
...animationParams,
|
||||
onComplete: (self, e) => {
|
||||
animationParams.onComplete?.(self, e);
|
||||
resolve();
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue