mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2025-12-29 11:26:13 +08:00
refactor: add url parameter handling to Page class (@fehmer) (#6668)
This commit is contained in:
parent
677c328bed
commit
36dcfe2f7f
3 changed files with 70 additions and 28 deletions
|
|
@ -15,7 +15,7 @@ import * as PageAccountSettings from "../pages/account-settings";
|
|||
import * as PageTransition from "../states/page-transition";
|
||||
import * as AdController from "../controllers/ad-controller";
|
||||
import * as Focus from "../test/focus";
|
||||
import { PageName } from "../pages/page";
|
||||
import { PageName, PageWithUrlParams } from "../pages/page";
|
||||
|
||||
type ChangeOptions = {
|
||||
force?: boolean;
|
||||
|
|
@ -110,6 +110,10 @@ export async function change(
|
|||
ActivePage.set(nextPage.id);
|
||||
|
||||
await previousPage?.afterHide();
|
||||
|
||||
if (nextPage instanceof PageWithUrlParams) {
|
||||
nextPage.readUrlParams();
|
||||
}
|
||||
await nextPage?.beforeShow({
|
||||
params: options.params,
|
||||
// @ts-expect-error for the future (i think)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import Page from "./page";
|
||||
import { PageWithUrlParams } from "./page";
|
||||
import * as Skeleton from "../utils/skeleton";
|
||||
import Config from "../config";
|
||||
import {
|
||||
|
|
@ -34,10 +34,6 @@ import { abbreviateNumber } from "../utils/numbers";
|
|||
import { formatDistanceToNow } from "date-fns/formatDistanceToNow";
|
||||
import { z } from "zod";
|
||||
import { LocalStorageWithSchema } from "../utils/local-storage-with-schema";
|
||||
import {
|
||||
safeParse as parseUrlSearchParams,
|
||||
serialize as serializeUrlSearchParams,
|
||||
} from "zod-urlsearchparams";
|
||||
import { UTCDateMini } from "@date-fns/utc";
|
||||
import * as ConfigEvent from "../observables/config-event";
|
||||
import * as ActivePage from "../states/active-page";
|
||||
|
|
@ -1135,34 +1131,17 @@ function updateGetParameters(): void {
|
|||
|
||||
params.page = state.page + 1;
|
||||
|
||||
const urlParams = serializeUrlSearchParams({
|
||||
schema: UrlParameterSchema,
|
||||
data: params,
|
||||
});
|
||||
|
||||
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
|
||||
window.history.replaceState({}, "", newUrl);
|
||||
page.setUrlParams(params);
|
||||
|
||||
selectorLS.set(state);
|
||||
}
|
||||
|
||||
function readGetParameters(): void {
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
if (urlParams.size === 0) {
|
||||
function readGetParameters(params: UrlParameter | null): void {
|
||||
if (params === null) {
|
||||
Object.assign(state, selectorLS.get());
|
||||
return;
|
||||
}
|
||||
|
||||
const parsed = parseUrlSearchParams({
|
||||
schema: UrlParameterSchema,
|
||||
input: urlParams,
|
||||
});
|
||||
if (!parsed.success) {
|
||||
return;
|
||||
}
|
||||
const params = parsed.data;
|
||||
|
||||
if (params.type !== undefined) {
|
||||
state.type = params.type;
|
||||
}
|
||||
|
|
@ -1288,10 +1267,14 @@ $(".page.pageLeaderboards .buttonGroup.secondary").on(
|
|||
}
|
||||
);
|
||||
|
||||
export const page = new Page({
|
||||
export const page = new PageWithUrlParams({
|
||||
id: "leaderboards",
|
||||
element: $(".page.pageLeaderboards"),
|
||||
path: "/leaderboards",
|
||||
urlParams: {
|
||||
schema: UrlParameterSchema,
|
||||
onUrlParamUpdate: readGetParameters,
|
||||
},
|
||||
afterHide: async (): Promise<void> => {
|
||||
Skeleton.remove("pageLeaderboards");
|
||||
stopTimer();
|
||||
|
|
@ -1299,7 +1282,6 @@ export const page = new Page({
|
|||
beforeShow: async (): Promise<void> => {
|
||||
Skeleton.append("pageLeaderboards", "main");
|
||||
// await appendLanguageButtons(); //todo figure out this race condition
|
||||
readGetParameters();
|
||||
startTimer();
|
||||
updateTypeButtons();
|
||||
updateTitle();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
import { z } from "zod";
|
||||
import {
|
||||
safeParse as parseUrlSearchParams,
|
||||
serialize as serializeUrlSearchParams,
|
||||
} from "zod-urlsearchparams";
|
||||
|
||||
export type PageName =
|
||||
| "loading"
|
||||
| "test"
|
||||
|
|
@ -35,6 +41,7 @@ export default class Page<T> {
|
|||
public display: string | undefined;
|
||||
public element: JQuery;
|
||||
public pathname: string;
|
||||
|
||||
public beforeHide: () => Promise<void>;
|
||||
public afterHide: () => Promise<void>;
|
||||
public beforeShow: (options: Options<T>) => Promise<void>;
|
||||
|
|
@ -51,3 +58,52 @@ export default class Page<T> {
|
|||
this.afterShow = props.afterShow ?? empty;
|
||||
}
|
||||
}
|
||||
|
||||
type UrlParamsSchema = z.ZodObject<Record<string, z.ZodTypeAny>>;
|
||||
type PagePropertiesWithUrlParams<
|
||||
T,
|
||||
U extends UrlParamsSchema
|
||||
> = PageProperties<T> & {
|
||||
urlParams: {
|
||||
schema: U;
|
||||
onUrlParamUpdate?: (params: z.infer<U> | null) => void;
|
||||
};
|
||||
};
|
||||
|
||||
export class PageWithUrlParams<T, U extends UrlParamsSchema> extends Page<T> {
|
||||
private urlSchema: U;
|
||||
private onUrlParamUpdate?: (params: z.infer<U> | null) => void;
|
||||
|
||||
constructor(props: PagePropertiesWithUrlParams<T, U>) {
|
||||
super(props);
|
||||
this.urlSchema = props.urlParams.schema;
|
||||
this.onUrlParamUpdate = props.urlParams.onUrlParamUpdate;
|
||||
}
|
||||
|
||||
public readUrlParams(): void {
|
||||
if (this.onUrlParamUpdate === undefined) {
|
||||
return;
|
||||
}
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
|
||||
const parsed = parseUrlSearchParams({
|
||||
schema: this.urlSchema,
|
||||
input: urlParams,
|
||||
});
|
||||
|
||||
if (!parsed.success) {
|
||||
this.onUrlParamUpdate?.(null);
|
||||
return;
|
||||
}
|
||||
|
||||
this.onUrlParamUpdate?.(parsed.data);
|
||||
}
|
||||
public setUrlParams(params: z.infer<U>): void {
|
||||
const urlParams = serializeUrlSearchParams({
|
||||
schema: this.urlSchema,
|
||||
data: params,
|
||||
});
|
||||
const newUrl = `${window.location.pathname}?${urlParams.toString()}`;
|
||||
window.history.replaceState({}, "", newUrl);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue