refactor: add cleanup function to animated modals

this fixes issues with drop downs causing performance / duplication issues
This commit is contained in:
Miodec 2025-01-15 13:09:26 +01:00
parent 3a065313bf
commit 64cc59116c
6 changed files with 48 additions and 33 deletions

View file

@ -60,11 +60,6 @@ export async function show(
async function hide(clearChain = false): Promise<void> {
void modal.hide({
clearModalChain: clearChain,
afterAnimation: async () => {
CaptchaController.reset("quoteReportModal");
state.reasonSelect?.destroy();
state.reasonSelect = undefined;
},
});
}
@ -131,7 +126,14 @@ async function setup(modalEl: HTMLElement): Promise<void> {
});
}
async function cleanup(): Promise<void> {
CaptchaController.reset("quoteReportModal");
state.reasonSelect?.destroy();
state.reasonSelect = undefined;
}
const modal = new AnimatedModal({
dialogId: "quoteReportModal",
setup,
cleanup,
});

View file

@ -312,10 +312,6 @@ export async function show(showOptions?: ShowOptions): Promise<void> {
function hide(clearChain = false): void {
void modal.hide({
clearModalChain: clearChain,
afterAnimation: async () => {
lengthSelect?.destroy();
lengthSelect = undefined;
},
});
}
@ -456,7 +452,13 @@ async function setup(modalEl: HTMLElement): Promise<void> {
});
}
async function cleanup(): Promise<void> {
lengthSelect?.destroy();
lengthSelect = undefined;
}
const modal = new AnimatedModal({
dialogId: "quoteSearchModal",
setup,
cleanup,
});

View file

@ -82,11 +82,6 @@ export async function show(showOptions: ShowOptions): Promise<void> {
function hide(clearModalChain: boolean): void {
void modal.hide({
clearModalChain,
afterAnimation: async () => {
CaptchaController.reset("submitQuote");
select?.destroy();
select = undefined;
},
});
}
@ -97,7 +92,14 @@ async function setup(modalEl: HTMLElement): Promise<void> {
});
}
async function cleanup(): Promise<void> {
CaptchaController.reset("submitQuote");
select?.destroy();
select = undefined;
}
const modal = new AnimatedModal({
dialogId: "quoteSubmitModal",
setup,
cleanup,
});

View file

@ -64,13 +64,7 @@ export async function show(options: ShowOptions): Promise<void> {
}
async function hide(): Promise<void> {
void modal.hide({
afterAnimation: async () => {
select?.destroy();
select = undefined;
CaptchaController.reset("userReportModal");
},
});
void modal.hide();
}
async function submitReport(): Promise<void> {
@ -140,4 +134,9 @@ const modal = new AnimatedModal({
void submitReport();
});
},
cleanup: async (): Promise<void> => {
select?.destroy();
select = undefined;
CaptchaController.reset("userReportModal");
},
});

View file

@ -185,14 +185,6 @@ export async function show(showOptions?: ShowOptions): Promise<void> {
function hide(hideOptions?: HideOptions<OutgoingData>): void {
void modal.hide({
...hideOptions,
afterAnimation: async () => {
languageSelect?.destroy();
layoutSelect?.destroy();
presetSelect?.destroy();
languageSelect = undefined;
layoutSelect = undefined;
presetSelect = undefined;
},
});
}
@ -326,6 +318,15 @@ async function setup(): Promise<void> {
});
}
async function cleanup(): Promise<void> {
languageSelect?.destroy();
layoutSelect?.destroy();
presetSelect?.destroy();
languageSelect = undefined;
layoutSelect = undefined;
presetSelect = undefined;
}
type OutgoingData = {
text: string;
set: boolean;
@ -334,4 +335,5 @@ type OutgoingData = {
const modal = new AnimatedModal<unknown, OutgoingData>({
dialogId: "wordFilterModal",
setup,
cleanup,
});

View file

@ -48,6 +48,7 @@ type ConstructorParams<T> = {
customEscapeHandler?: (e: KeyboardEvent) => void;
customWrapperClickHandler?: (e: MouseEvent) => void;
setup?: (modal: HTMLElement) => Promise<void>;
cleanup?: () => Promise<void>;
};
const DEFAULT_ANIMATION_DURATION = 125;
@ -73,6 +74,7 @@ export default class AnimatedModal<
private customEscapeHandler: ((e: KeyboardEvent) => void) | undefined;
private customWrapperClickHandler: ((e: MouseEvent) => void) | undefined;
private setup: ((modal: HTMLElement) => Promise<void>) | undefined;
private cleanup: (() => Promise<void>) | undefined;
constructor(constructorParams: ConstructorParams<IncomingModalChainData>) {
if (constructorParams.dialogId.startsWith("#")) {
@ -123,6 +125,7 @@ export default class AnimatedModal<
this.customWrapperClickHandler =
constructorParams?.customWrapperClickHandler;
this.setup = constructorParams?.setup;
this.cleanup = constructorParams?.cleanup;
Skeleton.save(this.dialogId);
}
@ -132,24 +135,26 @@ export default class AnimatedModal<
}
async runSetup(): Promise<void> {
this.wrapperEl.addEventListener("keydown", (e) => {
this.wrapperEl.addEventListener("keydown", async (e) => {
if (e.key === "Escape" && isPopupVisible(this.dialogId)) {
e.preventDefault();
e.stopPropagation();
if (this.customEscapeHandler !== undefined) {
this.customEscapeHandler(e);
void this.cleanup?.();
} else {
void this.hide();
await this.hide();
}
}
});
this.wrapperEl.addEventListener("mousedown", (e) => {
this.wrapperEl.addEventListener("mousedown", async (e) => {
if (e.target === this.wrapperEl) {
if (this.customWrapperClickHandler !== undefined) {
this.customWrapperClickHandler(e);
void this.cleanup?.();
} else {
void this.hide();
await this.hide();
}
}
});
@ -392,6 +397,7 @@ export default class AnimatedModal<
Skeleton.remove(this.dialogId);
this.open = false;
await options?.afterAnimation?.(this.modalEl);
void this.cleanup?.();
if (
this.previousModalInChain !== undefined &&
@ -428,6 +434,7 @@ export default class AnimatedModal<
Skeleton.remove(this.dialogId);
this.open = false;
await options?.afterAnimation?.(this.modalEl);
void this.cleanup?.();
if (
this.previousModalInChain !== undefined &&
@ -453,6 +460,7 @@ export default class AnimatedModal<
destroy(): void {
this.wrapperEl.close();
this.wrapperEl.classList.add("hidden");
void this.cleanup?.();
Skeleton.remove(this.dialogId);
this.open = false;
}