Skip to content

Commit 0d1ba6a

Browse files
committed
no legacy
1 parent 422ec59 commit 0d1ba6a

4 files changed

Lines changed: 105 additions & 169 deletions

File tree

bun.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/opencode/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@
130130
"bonjour-service": "1.3.0",
131131
"bun-pty": "0.4.8",
132132
"chokidar": "4.0.3",
133-
"cli-sound": "1.1.3",
134133
"clipboardy": "4.0.0",
135134
"cross-spawn": "catalog:",
136135
"decimal.js": "10.5.0",

packages/opencode/src/cli/cmd/tui/component/logo.tsx

Lines changed: 105 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,21 @@
1-
import { BoxRenderable, MouseButton, MouseEvent, RGBA, TextAttributes } from "@opentui/core"
1+
import {
2+
Audio,
3+
BoxRenderable,
4+
MouseButton,
5+
MouseEvent,
6+
RGBA,
7+
TextAttributes,
8+
type AudioSound,
9+
type AudioVoice,
10+
} from "@opentui/core"
211
import { useRenderer } from "@opentui/solid"
312
import { For, createMemo, createSignal, onCleanup, onMount, type JSX } from "solid-js"
413
import { useTheme, tint } from "@tui/context/theme"
5-
import * as Sound from "@tui/util/sound"
614
import { go, logo } from "@/cli/logo"
15+
import pulseA from "../asset/pulse-a.wav" with { type: "file" }
16+
import pulseB from "../asset/pulse-b.wav" with { type: "file" }
17+
import pulseC from "../asset/pulse-c.wav" with { type: "file" }
18+
import charge from "../asset/charge.wav" with { type: "file" }
719

820
export type LogoShape = {
921
left: string[]
@@ -88,6 +100,94 @@ const TAIL = 1.8
88100
const TRACE_IN = 200
89101
const GLOW_OUT = 1600
90102
const PEAK = RGBA.fromInts(255, 255, 255)
103+
const PULSE_SOUNDS = [pulseA, pulseB, pulseC]
104+
105+
let logoAudio: Audio | undefined
106+
let logoAudioSounds: Promise<{ charge: AudioSound | null; pulse: (AudioSound | null)[] }> | undefined
107+
let logoAudioVoice: AudioVoice | undefined
108+
let logoAudioTail: ReturnType<typeof setTimeout> | undefined
109+
let logoAudioSeq = 0
110+
let logoAudioShot = 0
111+
112+
function createLogoAudio() {
113+
if (logoAudio) return logoAudio
114+
try {
115+
logoAudio = Audio.create({ autoStart: false })
116+
logoAudio.on("error", () => undefined)
117+
return logoAudio
118+
} catch {
119+
return
120+
}
121+
}
122+
123+
function loadLogoSounds(audio: Audio) {
124+
logoAudioSounds ??= Promise.all([
125+
audio.loadSoundFile(charge).catch(() => null),
126+
Promise.all(PULSE_SOUNDS.map((file) => audio.loadSoundFile(file).catch(() => null))),
127+
]).then(([charge, pulse]) => ({ charge, pulse }))
128+
return logoAudioSounds
129+
}
130+
131+
function startLogoSound() {
132+
stopLogoSound()
133+
const id = ++logoAudioSeq
134+
const audio = createLogoAudio()
135+
if (!audio || (!audio.isStarted() && !audio.start())) return
136+
void loadLogoSounds(audio)
137+
.then((sounds) => {
138+
if (id !== logoAudioSeq || sounds.charge == null) return
139+
const voice = audio.play(sounds.charge, { volume: 0.24, loop: true })
140+
if (voice == null) return
141+
logoAudioVoice = voice
142+
})
143+
.catch(() => undefined)
144+
}
145+
146+
function clearLogoSoundTail() {
147+
if (!logoAudioTail) return
148+
clearTimeout(logoAudioTail)
149+
logoAudioTail = undefined
150+
}
151+
152+
function stopLogoSound(delay = 0) {
153+
logoAudioSeq++
154+
clearLogoSoundTail()
155+
if (logoAudioVoice === undefined) return
156+
const voice = logoAudioVoice
157+
if (delay <= 0) {
158+
logoAudioVoice = undefined
159+
logoAudio?.stopVoice(voice)
160+
return
161+
}
162+
logoAudioTail = setTimeout(() => {
163+
logoAudioTail = undefined
164+
if (logoAudioVoice !== voice) return
165+
logoAudioVoice = undefined
166+
logoAudio?.stopVoice(voice)
167+
}, delay)
168+
}
169+
170+
function pulseLogoSound(scale = 1) {
171+
stopLogoSound(140)
172+
const id = logoAudioSeq
173+
const audio = createLogoAudio()
174+
if (!audio || (!audio.isStarted() && !audio.start())) return
175+
void loadLogoSounds(audio)
176+
.then((sounds) => {
177+
if (id !== logoAudioSeq) return
178+
const sound = sounds.pulse[logoAudioShot++ % PULSE_SOUNDS.length]
179+
if (sound == null) return
180+
audio.play(sound, { volume: 0.26 + 0.14 * scale })
181+
})
182+
.catch(() => undefined)
183+
}
184+
185+
function disposeLogoSound() {
186+
stopLogoSound()
187+
logoAudio?.dispose()
188+
logoAudio = undefined
189+
logoAudioSounds = undefined
190+
}
91191

92192
type Ring = {
93193
x: number
@@ -577,7 +677,7 @@ export function Logo(props: { shape?: LogoShape; ink?: RGBA; idle?: boolean } =
577677
const item = hold()
578678
if (item && !hum && t - item.at >= HOLD) {
579679
hum = true
580-
Sound.start()
680+
startLogoSound()
581681
}
582682
if (item && t - item.at >= CHARGE) {
583683
burst(item.x, item.y)
@@ -606,7 +706,7 @@ export function Logo(props: { shape?: LogoShape; ink?: RGBA; idle?: boolean } =
606706
onCleanup(() => {
607707
stop()
608708
hum = false
609-
Sound.dispose()
709+
disposeLogoSound()
610710
})
611711

612712
onMount(() => {
@@ -655,7 +755,7 @@ export function Logo(props: { shape?: LogoShape; ink?: RGBA; idle?: boolean } =
655755
])
656756
setNow(t)
657757
start()
658-
Sound.pulse(lerp(0.8, 1, level))
758+
pulseLogoSound(lerp(0.8, 1, level))
659759
}
660760

661761
const frame = createMemo(() => {

packages/opencode/src/cli/cmd/tui/util/sound.ts

Lines changed: 0 additions & 156 deletions
This file was deleted.

0 commit comments

Comments
 (0)