Skip to content

Commit 214114e

Browse files
authored
chore: guard prompt reset timers (#4)
1 parent 7fb5785 commit 214114e

File tree

2 files changed

+21
-4
lines changed

2 files changed

+21
-4
lines changed

src/contentScript/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { doesUrlMatchPatterns } from '../shared/url'
88
const BLOCK_DATA_STATUS = 'coderchartStatus'
99
const BLOCK_DATA_SOURCE = 'coderchartSource'
1010
const PNG_PREPARING_LABEL = 'Preparing PNG…'
11+
const PROMPT_RESET_DELAY_MS = 2000
1112
let diagramCounter = 0
1213
let blockIdentifierCounter = 0
1314
let observer: MutationObserver | null = null
@@ -737,9 +738,10 @@ function createErrorNotice(doc: Document, err: unknown, source: string): HTMLEle
737738
}
738739

739740
setTimeout(() => {
741+
if (!promptButton.isConnected) return
740742
promptButton.disabled = false
741743
promptButton.textContent = defaultLabel
742-
}, 2000)
744+
}, PROMPT_RESET_DELAY_MS)
743745
})
744746

745747
promptSection.append(promptButton, promptStatus, promptPreview)

src/options/Options.tsx

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
import { FormEvent, useEffect, useMemo, useState } from 'react'
1+
import { FormEvent, useEffect, useMemo, useRef, useState } from 'react'
22
import { DEFAULT_SETTINGS, ExtensionSettings, getSettings, saveSettings, normalizeSettings } from '../shared/settings'
33

44
import './Options.css'
55

66
type SaveStatus = 'idle' | 'saving' | 'saved' | 'error'
77

88
const defaultState = cloneSettings(DEFAULT_SETTINGS)
9+
const SAVE_STATUS_RESET_DELAY_MS = 2400
910

1011
export const Options = () => {
1112
const [settings, setSettings] = useState<ExtensionSettings>(defaultState)
1213
const [newPattern, setNewPattern] = useState('')
1314
const [status, setStatus] = useState<SaveStatus>('idle')
1415
const [errorMessage, setErrorMessage] = useState<string | null>(null)
16+
const resetStatusTimeout = useRef<number | null>(null)
1517

1618
useEffect(() => {
1719
let mounted = true
@@ -31,6 +33,14 @@ export const Options = () => {
3133
}
3234
}, [])
3335

36+
useEffect(() => {
37+
return () => {
38+
if (resetStatusTimeout.current !== null) {
39+
window.clearTimeout(resetStatusTimeout.current)
40+
}
41+
}
42+
}, [])
43+
3444
const normalizedPatterns = useMemo(() => settings.hostPatterns.map((pattern) => pattern.trim()), [settings.hostPatterns])
3545

3646
const canAddPattern = useMemo(() => {
@@ -74,16 +84,21 @@ export const Options = () => {
7484

7585
const handleSubmit = async (event: FormEvent) => {
7686
event.preventDefault()
87+
if (resetStatusTimeout.current !== null) {
88+
window.clearTimeout(resetStatusTimeout.current)
89+
resetStatusTimeout.current = null
90+
}
7791
setStatus('saving')
7892
setErrorMessage(null)
7993
try {
8094
const normalized = normalizeSettings(settings)
8195
await saveSettings(normalized)
8296
setSettings(cloneSettings(normalized))
8397
setStatus('saved')
84-
setTimeout(() => {
98+
resetStatusTimeout.current = window.setTimeout(() => {
8599
setStatus('idle')
86-
}, 2400)
100+
resetStatusTimeout.current = null
101+
}, SAVE_STATUS_RESET_DELAY_MS)
87102
} catch (error) {
88103
console.error('Failed to save settings', error)
89104
setStatus('error')

0 commit comments

Comments
 (0)