Compare commits

..

No commits in common. "a61945477a2d86858d43977b6ac98494d93bf778" and "4692ca3377d5a899805773f071c6e11cf8f33156" have entirely different histories.

2 changed files with 88 additions and 63 deletions

View File

@ -5,9 +5,7 @@ $radius: 12px; // keep in sync with RADIUS in Bar.tsx
$spacing: 8px; $spacing: 8px;
$padding: 8px; $padding: 8px;
$border-width: 1px; $border-width: 1px;
// one step lighter than the card fill so section outlines read against $border-color: $base02;
// the dropdown background and the widgets they surround
$border-color: $base03;
$border: $border-width solid $border-color; $border: $border-width solid $border-color;
$transition: 180ms; $transition: 180ms;
$fg: $base05; $fg: $base05;
@ -213,7 +211,7 @@ scrollbar {
.volume, .volume,
.microphone, .microphone,
.brightness { .brightness {
padding: 0 4px; padding: 2px 4px;
} }
button { button {
@ -391,6 +389,30 @@ scale {
background: $hover-overlay; background: $hover-overlay;
} }
} }
switch {
background: $base03;
border-radius: 999px;
min-width: 34px;
min-height: 16px;
margin: 1px 0;
slider {
background: $base05;
border-radius: 999px;
min-width: 12px;
min-height: 12px;
margin: 2px;
}
}
switch:checked {
background: $primary-bg;
slider {
background: $primary-fg;
}
}
} }
.wifi-status, .wifi-status,
@ -420,9 +442,15 @@ scale {
} }
} }
.device-row { .device-item {
padding: 5px 7px;
border-radius: 6px;
margin: 1px 0; margin: 1px 0;
icon {
font-size: 16px;
}
.device-name { .device-name {
margin: 0 6px; margin: 0 6px;
} }
@ -438,6 +466,10 @@ scale {
opacity: 0.7; opacity: 0.7;
margin-right: 2px; margin-right: 2px;
} }
&:hover {
background: $hover-overlay;
}
} }
// media player card // media player card

View File

@ -48,42 +48,14 @@ const pillLabel = Variable.derive(
) )
// ported from AlfheimOS: icon, name, battery, busy icon while connecting, // ported from AlfheimOS: icon, name, battery, busy icon while connecting,
// whole row toggles the bluez connected state // switch reflecting the bluez connected state
function DeviceItem(device: AstalBluetooth.Device) { function DeviceItem(device: AstalBluetooth.Device) {
const battery = bind(device, "battery_percentage") const battery = bind(device, "battery_percentage")
const connecting = bind(device, "connecting") const connecting = bind(device, "connecting")
const connected = Variable.derive(
[bind(device, "connected"), connecting],
(c, busy) => c && !busy,
)
// bluez reports br-connection-busy when attempts pile up, so debounce // bluez reports br-connection-busy when attempts pile up, so debounce
let lastAttempt = 0 let lastAttempt = 0
function toggle() {
if (connecting.get()) return
// skip retries within the debounce window
const now = Date.now()
if (now - lastAttempt < 1500) return
lastAttempt = now
const state = !device.connected
// bluez rejects connects while the controller is busy scanning
if (state) setDiscovery(false)
// vala async: begin with a callback, finish() throws
const done = (_source: AstalBluetooth.Device, res: Gio.AsyncResult) => {
try {
if (state) device.connect_device_finish(res)
else device.disconnect_device_finish(res)
} catch (e) {
console.error(e)
}
}
if (state) device.connect_device(done)
else device.disconnect_device(done)
}
return ( return (
<button className="device-row" onClicked={toggle}> <box className="device-item">
<box>
<icon <icon
icon={ icon={
device.icon device.icon
@ -107,12 +79,33 @@ function DeviceItem(device: AstalBluetooth.Device) {
icon="view-refresh-symbolic" icon="view-refresh-symbolic"
visible={connecting} visible={connecting}
/> />
<icon <switch
visible={connected()} visible={connecting.as((c) => !c)}
icon="object-select-symbolic" active={bind(device, "connected")}
onStateSet={(_, state) => {
// bluez rejects connects while the controller is busy scanning
if (state) setDiscovery(false)
// skip no-ops and retries within the debounce window
const now = Date.now()
if (state === device.connected || now - lastAttempt < 1500) {
return true
}
lastAttempt = now
// vala async: begin with a callback, finish() throws
const done = (_source: AstalBluetooth.Device, res: Gio.AsyncResult) => {
try {
if (state) device.connect_device_finish(res)
else device.disconnect_device_finish(res)
} catch (e) {
console.error(e)
}
}
if (state) device.connect_device(done)
else device.disconnect_device(done)
return true
}}
/> />
</box> </box>
</button>
) )
} }