fix(ext/popup): bind form escHandlers to teardown to stop listener leak
This commit is contained in:
@@ -10,12 +10,17 @@ import {
|
||||
const CARD_KINDS: CardKind[] = ['credit', 'debit', 'gift', 'loyalty', 'other'];
|
||||
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
export function teardown(): void {
|
||||
if (activeKeyHandler) {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
function brandFromNumber(num: string): string {
|
||||
@@ -187,11 +192,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
@@ -8,12 +8,17 @@ import {
|
||||
} from '../fields';
|
||||
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
export function teardown(): void {
|
||||
if (activeKeyHandler) {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
function initials(name: string | undefined): string {
|
||||
@@ -142,11 +147,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
@@ -9,12 +9,17 @@ import {
|
||||
} from '../fields';
|
||||
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
export function teardown(): void {
|
||||
if (activeKeyHandler) {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function renderDetail(app: HTMLElement, item: Item): Promise<void> {
|
||||
@@ -141,11 +146,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
@@ -20,6 +20,10 @@ export function teardown(): void {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -174,6 +178,7 @@ export async function renderDetail(app: HTMLElement, item: Item): Promise<void>
|
||||
|
||||
let totpTickerId: ReturnType<typeof setInterval> | null = null;
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
function stopTotpTicker(): void {
|
||||
if (totpTickerId !== null) { clearInterval(totpTickerId); totpTickerId = null; }
|
||||
}
|
||||
@@ -259,11 +264,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
@@ -8,12 +8,17 @@ import {
|
||||
} from '../fields';
|
||||
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
export function teardown(): void {
|
||||
if (activeKeyHandler) {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function renderDetail(app: HTMLElement, item: Item): Promise<void> {
|
||||
@@ -112,11 +117,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
|
||||
let totpTickerId: ReturnType<typeof setInterval> | null = null;
|
||||
let activeKeyHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
let activeFormEscHandler: ((e: KeyboardEvent) => void) | null = null;
|
||||
|
||||
function stopTotpTicker(): void {
|
||||
if (totpTickerId !== null) { clearInterval(totpTickerId); totpTickerId = null; }
|
||||
@@ -28,6 +29,10 @@ export function teardown(): void {
|
||||
document.removeEventListener('keydown', activeKeyHandler);
|
||||
activeKeyHandler = null;
|
||||
}
|
||||
if (activeFormEscHandler) {
|
||||
document.removeEventListener('keydown', activeFormEscHandler);
|
||||
activeFormEscHandler = null;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
@@ -248,11 +253,11 @@ export function renderForm(app: HTMLElement, mode: 'add' | 'edit', existing: Ite
|
||||
|
||||
const escHandler = (e: KeyboardEvent) => {
|
||||
if (e.key === 'Escape') {
|
||||
document.removeEventListener('keydown', escHandler);
|
||||
setState({ error: null });
|
||||
navigate(mode === 'edit' ? 'detail' : 'list');
|
||||
}
|
||||
};
|
||||
activeFormEscHandler = escHandler;
|
||||
document.addEventListener('keydown', escHandler);
|
||||
|
||||
(document.getElementById('f-title') as HTMLInputElement | null)?.focus();
|
||||
|
||||
Reference in New Issue
Block a user