55 lines
1.6 KiB
TypeScript
55 lines
1.6 KiB
TypeScript
import AstalWp from "gi://AstalWp"
|
|
import { Variable, bind } from "astal"
|
|
import Dropdown from "./Dropdown"
|
|
|
|
const speaker = AstalWp.get_default().audio.default_speaker!
|
|
|
|
const icon = Variable.derive(
|
|
[bind(speaker, "volume"), bind(speaker, "mute")],
|
|
(volume, mute) => {
|
|
if (mute || volume <= 0.01) return "audio-volume-muted-symbolic"
|
|
if (volume < 0.33) return "audio-volume-low-symbolic"
|
|
if (volume < 0.66) return "audio-volume-medium-symbolic"
|
|
return "audio-volume-high-symbolic"
|
|
}
|
|
)
|
|
|
|
export function VolumeWidget(gdkmonitor: Gdk.Monitor) {
|
|
const open = Variable(false)
|
|
|
|
const button = (
|
|
<button
|
|
className="volume"
|
|
onClicked={() => open.set(!open.get())}
|
|
onScroll={(_, e) => {
|
|
const volume = Math.min(1, Math.max(0, speaker.volume - e.delta_y * 0.02))
|
|
speaker.volume = volume
|
|
}}
|
|
>
|
|
<icon icon={icon()} />
|
|
</button>
|
|
)
|
|
|
|
const popup = (
|
|
<Dropdown
|
|
gdkmonitor={gdkmonitor}
|
|
target={button}
|
|
open={open}
|
|
width={240}
|
|
vertical={false}
|
|
>
|
|
<button className="mute" onClicked={() => (speaker.mute = !speaker.mute)}>
|
|
<icon icon={icon()} />
|
|
</button>
|
|
<slider
|
|
className="vol-slider"
|
|
hexpand
|
|
value={bind(speaker, "volume")}
|
|
onDragged={(self) => (speaker.volume = self.value)}
|
|
/>
|
|
</Dropdown>
|
|
)
|
|
|
|
return { button, popup }
|
|
}
|