cleanup event listeners with solid-primitives/event-listener (#20619)

This commit is contained in:
Brendan Allan
2026-04-02 09:40:03 +00:00
committed by GitHub
parent 327f62526a
commit 69d047ae7d
22 changed files with 102 additions and 176 deletions
+16 -24
View File
@@ -1,6 +1,7 @@
import { createEffect, createMemo, Match, on, onCleanup, Switch } from "solid-js"
import { createEffect, createMemo, createSignal, Match, on, onCleanup, Switch } from "solid-js"
import { createStore } from "solid-js/store"
import { Dynamic } from "solid-js/web"
import { makeEventListener } from "@solid-primitives/event-listener"
import type { FileSearchHandle } from "@opencode-ai/ui/file"
import { useFileComponent } from "@opencode-ai/ui/context/file"
import { cloneSelectedLineRange, previewSelectedLines } from "@opencode-ai/ui/pierre/selection-bridge"
@@ -59,7 +60,7 @@ function createScrollSync(input: { tab: () => string; view: ReturnType<typeof us
let scrollFrame: number | undefined
let restoreFrame: number | undefined
let pending: ScrollPos | undefined
let code: HTMLElement[] = []
const [code, setCode] = createSignal<HTMLElement[]>([])
const getCode = () => {
const el = scroll
@@ -106,17 +107,9 @@ function createScrollSync(input: { tab: () => string; view: ReturnType<typeof us
const sync = () => {
const next = getCode()
if (next.length === code.length && next.every((el, i) => el === code[i])) return
for (const item of code) {
item.removeEventListener("scroll", onCodeScroll)
}
code = next
for (const item of code) {
item.addEventListener("scroll", onCodeScroll)
}
const current = code()
if (next.length === current.length && next.every((el, i) => el === current[i])) return
setCode(next)
}
const restore = () => {
@@ -128,14 +121,14 @@ function createScrollSync(input: { tab: () => string; view: ReturnType<typeof us
sync()
if (code.length > 0) {
for (const item of code) {
if (code().length > 0) {
for (const item of code()) {
if (item.scrollLeft !== pos.x) item.scrollLeft = pos.x
}
}
if (el.scrollTop !== pos.y) el.scrollTop = pos.y
if (code.length > 0) return
if (code().length > 0) return
if (el.scrollLeft !== pos.x) el.scrollLeft = pos.x
}
@@ -149,24 +142,24 @@ function createScrollSync(input: { tab: () => string; view: ReturnType<typeof us
}
const handleScroll = (event: Event & { currentTarget: HTMLDivElement }) => {
if (code.length === 0) sync()
if (code().length === 0) sync()
save({
x: code[0]?.scrollLeft ?? event.currentTarget.scrollLeft,
x: code()[0]?.scrollLeft ?? event.currentTarget.scrollLeft,
y: event.currentTarget.scrollTop,
})
}
createEffect(() => {
for (const item of code()) makeEventListener(item, "scroll", onCodeScroll)
})
const setViewport = (el: HTMLDivElement) => {
scroll = el
restore()
}
onCleanup(() => {
for (const item of code) {
item.removeEventListener("scroll", onCodeScroll)
}
if (scrollFrame !== undefined) cancelAnimationFrame(scrollFrame)
if (restoreFrame !== undefined) cancelAnimationFrame(restoreFrame)
})
@@ -358,8 +351,7 @@ export function FileTabContent(props: { tab: string }) {
find?.focus()
}
window.addEventListener("keydown", onKeyDown, { capture: true })
onCleanup(() => window.removeEventListener("keydown", onKeyDown, { capture: true }))
makeEventListener(window, "keydown", onKeyDown, { capture: true })
})
createEffect(