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