Update bluetooth battery indicator padding and provide option to define when to show battery icon. (#403)

* Update bluetooth battery indicator visuals and behavior.

* Remove log

* Update default battery state to paired.

* Change to connected
This commit is contained in:
Jas Singh
2024-10-30 02:34:04 -07:00
committed by GitHub
parent 9bb582c8cf
commit 776e07b7bc
6 changed files with 225 additions and 177 deletions

View File

@@ -215,3 +215,5 @@ export type ColorMapKey = keyof typeof defaultColorMap;
export type ColorMapValue = (typeof defaultColorMap)[ColorMapKey]; export type ColorMapValue = (typeof defaultColorMap)[ColorMapKey];
export type ScalingPriority = 'gdk' | 'hyprland' | 'both'; export type ScalingPriority = 'gdk' | 'hyprland' | 'both';
export type BluetoothBatteryState = 'paired' | 'connected' | 'always';

View File

@@ -13,7 +13,11 @@ const formatFrequency = (frequency: number): string => {
}; };
const formatWifiInfo = (wifi: Wifi): string => { const formatWifiInfo = (wifi: Wifi): string => {
return `Network: ${wifi.ssid === '' ? 'None' : wifi.ssid} \nSignal Strength: ${wifi.strength >= 0 ? wifi.strength : '--'}% \nFrequency: ${wifi.frequency >= 0 ? formatFrequency(wifi.frequency) : '--'}`; const netSsid = wifi.ssid === '' ? 'None' : wifi.ssid;
const wifiStrength = wifi.strength >= 0 ? wifi.strength : '--';
const wifiFreq = wifi.frequency >= 0 ? formatFrequency(wifi.frequency) : '--';
return `Network: ${netSsid} \nSignal Strength: ${wifiStrength}% \nFrequency: ${wifiFreq}`;
}; };
const { const {

View File

@@ -1,12 +1,13 @@
import { Bluetooth } from 'types/service/bluetooth.js'; import { Bluetooth, BluetoothDevice } from 'types/service/bluetooth.js';
import Box from 'types/widgets/box.js'; import Box from 'types/widgets/box.js';
import { connectedControls } from './connectedControls.js'; import { connectedControls } from './connectedControls.js';
import { getBluetoothIcon } from '../utils.js'; import { getBluetoothIcon } from '../utils.js';
import Gtk from 'types/@girs/gtk-3.0/gtk-3.0.js'; import Gtk from 'types/@girs/gtk-3.0/gtk-3.0.js';
import { Attribute, Child } from 'lib/types/widget.js'; import { Attribute, Child } from 'lib/types/widget.js';
import options from 'options'; import options from 'options';
import Label from 'types/widgets/label.js';
const { showBattery, batteryIcon } = options.menus.bluetooth; const { showBattery, batteryIcon, batteryState } = options.menus.bluetooth;
const devices = (bluetooth: Bluetooth, self: Box<Gtk.Widget, unknown>): Box<Child, Attribute> => { const devices = (bluetooth: Bluetooth, self: Box<Gtk.Widget, unknown>): Box<Child, Attribute> => {
return self.hook(bluetooth, () => { return self.hook(bluetooth, () => {
@@ -65,6 +66,33 @@ const devices = (bluetooth: Bluetooth, self: Box<Gtk.Widget, unknown>): Box<Chil
})); }));
} }
const getConnectionStatusLabel = (device: BluetoothDevice): Label<Attribute> => {
return Widget.Label({
hpack: 'start',
class_name: 'connection-status dim',
label: device.connected ? 'Connected' : 'Paired',
});
};
const getBatteryInfo = (device: BluetoothDevice, batIcon: string): Gtk.Widget[] => {
if (typeof device.battery_percentage === 'number' && device.battery_percentage >= 0) {
return [
Widget.Separator({
class_name: 'menu-separator bluetooth-battery',
}),
Widget.Label({
class_name: 'connection-status txt-icon',
label: `${batIcon}`,
}),
Widget.Label({
class_name: 'connection-status battery',
label: `${device.battery_percentage}%`,
}),
];
}
return [];
};
return (self.child = Widget.Box({ return (self.child = Widget.Box({
vertical: true, vertical: true,
children: availableDevices.map((device) => { children: availableDevices.map((device) => {
@@ -107,50 +135,24 @@ const devices = (bluetooth: Bluetooth, self: Box<Gtk.Widget, unknown>): Box<Chil
child: Widget.Box({ child: Widget.Box({
hpack: 'start', hpack: 'start',
children: Utils.merge( children: Utils.merge(
[showBattery.bind('value'), batteryIcon.bind('value')], [
(showBat, batIcon) => { showBattery.bind('value'),
if (!showBat) { batteryIcon.bind('value'),
return [ batteryState.bind('value'),
Widget.Label({ ],
hpack: 'start', (showBat, batIcon, batState) => {
class_name: 'connection-status dim', if (
label: device.connected !showBat ||
? 'Connected' (batState === 'paired' && !device.paired) ||
: 'Paired', (batState === 'connected' && !device.connected)
}), ) {
]; return [getConnectionStatusLabel(device)];
} }
return [ return [
Widget.Label({ getConnectionStatusLabel(device),
hpack: 'start',
class_name: 'connection-status dim',
label: device.connected
? 'Connected'
: 'Paired',
}),
Widget.Box({ Widget.Box({
children: children: getBatteryInfo(device, batIcon),
typeof device.battery_percentage ===
'number' &&
device.battery_percentage >= 0
? [
Widget.Separator({
class_name:
'menu-separator',
}),
Widget.Label({
class_name:
'connection-status txt-icon',
label: `${batIcon}`,
}),
Widget.Label({
class_name:
'connection-status battery',
label: `${device.battery_percentage}%`,
}),
]
: [],
}), }),
]; ];
}, },

View File

@@ -5,6 +5,7 @@ import {
ActiveWsIndicator, ActiveWsIndicator,
BarButtonStyles, BarButtonStyles,
BarLocation, BarLocation,
BluetoothBatteryState,
NotificationAnchor, NotificationAnchor,
OSDAnchor, OSDAnchor,
OSDOrientation, OSDOrientation,
@@ -1057,6 +1058,7 @@ const options = mkOptions(OPTIONS, {
transitionTime: opt(200), transitionTime: opt(200),
bluetooth: { bluetooth: {
showBattery: opt(false), showBattery: opt(false),
batteryState: opt<BluetoothBatteryState>('connected'),
batteryIcon: opt('󰥉'), batteryIcon: opt('󰥉'),
}, },
volume: { volume: {

View File

@@ -1,165 +1,197 @@
.menu-items-container.bluetooth * { .menu-items-container.bluetooth * {
font-size: $font-size * $bar-menus-menu-bluetooth-scaling * 0.01; font-size: $font-size * $bar-menus-menu-bluetooth-scaling * 0.01;
} }
@import "./menu.scss"; @import './menu.scss';
.menu-items.bluetooth { .menu-items.bluetooth {
background: if($bar-menus-monochrome, $bar-menus-background, $bar-menus-menu-bluetooth-background-color); background: if($bar-menus-monochrome, $bar-menus-background, $bar-menus-menu-bluetooth-background-color);
border-color: if($bar-menus-monochrome, $bar-menus-border-color, $bar-menus-menu-bluetooth-border-color); border-color: if($bar-menus-monochrome, $bar-menus-border-color, $bar-menus-menu-bluetooth-border-color);
opacity: $bar-menus-opacity * 0.01; opacity: $bar-menus-opacity * 0.01;
font-size: $font-size * $bar-menus-menu-bluetooth-scaling * 0.01; font-size: $font-size * $bar-menus-menu-bluetooth-scaling * 0.01;
} }
.menu-items-container.bluetooth { .menu-items-container.bluetooth {
min-width: 18em * $bar-menus-menu-bluetooth-scaling * 0.01;
min-width: 18em * $bar-menus-menu-bluetooth-scaling * 0.01; font-size: 1.3em;
font-size: 1.3em; .menu-section-container {
margin: 1em 0em;
.menu-section-container {
margin: 1em 0em;
}
.menu-label-container {
background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-bluetooth-card-color);
.menu-label {
color: if($bar-menus-monochrome, $bar-menus-label, $bar-menus-menu-bluetooth-label-color);
} }
.controls-container { .menu-label-container {
margin: 0.5em 1em; background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-bluetooth-card-color);
.menu-label {
color: if($bar-menus-monochrome, $bar-menus-label, $bar-menus-menu-bluetooth-label-color);
}
.controls-container {
margin: 0.5em 1em;
}
} }
}
.menu-items-section {
background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-bluetooth-card-color);
min-height: 20em * $bar-menus-menu-bluetooth-scaling * 0.01;
font-size: 1em;
}
.menu-items-section { button {
background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-bluetooth-card-color); margin-right: 0.5em;
min-height: 20em * $bar-menus-menu-bluetooth-scaling * 0.01;
font-size: 1em;
}
button { &.search {
margin-right: 0.5em; image {
color: if(
$bar-menus-monochrome,
$bar-menus-iconbuttons-passive,
$bar-menus-menu-bluetooth-iconbutton-passive
);
}
&.search { &:hover image {
image { color: if(
$bar-menus-monochrome,
$bar-menus-iconbuttons-active,
$bar-menus-menu-bluetooth-iconbutton-active
);
}
font-size: 0.8em;
margin-bottom: 0em;
}
&:hover {
color: if(
$bar-menus-monochrome,
$bar-menus-iconbuttons-active,
$bar-menus-menu-bluetooth-iconbutton-active
);
}
}
.menu-icon-button.bluetooth {
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-bluetooth-iconbutton-passive); color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-bluetooth-iconbutton-passive);
}
&:hover image { &:hover {
color: if(
$bar-menus-monochrome,
$bar-menus-iconbuttons-active,
$bar-menus-menu-bluetooth-iconbutton-active
);
}
}
.bluetooth-element-item {
margin-bottom: 0.4em;
&:hover {
.menu-button-icon,
.menu-button-name {
color: if(
$bar-menus-monochrome,
$bar-menus-iconbuttons-active,
$bar-menus-menu-bluetooth-iconbutton-active
);
}
}
image {
margin-right: 0em;
margin-top: 0em;
min-height: 1em;
min-width: 1em;
&.active {
color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-bluetooth-icons-active);
}
}
label {
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text);
font-size: 1em;
}
.menu-button-icon {
font-size: 1.5em;
color: if($bar-menus-monochrome, $bar-menus-icons-passive, $bar-menus-menu-bluetooth-icons-passive);
&.active {
color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-bluetooth-icons-active);
}
}
.connection-status {
font-size: 0.9em;
margin-left: 0.6rem;
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text);
opacity: 0.4;
}
.battery {
opacity: 0.6;
}
}
spinner {
min-height: 1.3em;
min-width: 1.3em;
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active); color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active);
}
font-size: 0.8em;
margin-bottom: 0em;
} }
&:hover { .menu-separator {
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active); margin: 0em 1em;
}
}
.menu-icon-button.bluetooth {
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-bluetooth-iconbutton-passive);
&:hover {
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active);
}
}
.bluetooth-element-item {
margin-bottom: 0.4em;
&:hover {
.menu-button-icon,
.menu-button-name {
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active);
}
} }
image { .menu-switch.bluetooth {
margin-right: 0em; background-color: if(
margin-top: 0.0em; $bar-menus-monochrome,
min-height: 1em; $bar-menus-switch-disabled,
min-width: 1em; $bar-menus-menu-bluetooth-switch-disabled
);
&.active { &:checked {
color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-bluetooth-icons-active); background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-bluetooth-switch-enabled);
} }
slider {
background-color: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-bluetooth-switch-puck);
}
&:hover {
trough {
background: if(
$bar-menus-monochrome,
$bar-menus-switch-disabled,
$bar-menus-menu-bluetooth-switch-disabled
);
}
slider {
background: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-bluetooth-switch-puck);
}
}
&:active {
background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-bluetooth-switch-enabled);
}
} }
label { .no-bluetooth-devices.dim,
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text); .search-bluetooth-label.dim,
font-size: 1em; .bluetooth-disabled.dim {
&:last-child {
margin-bottom: 2em;
}
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text);
opacity: 0.5;
} }
.menu-separator.bluetooth-battery {
.menu-button-icon { margin: 0.2em 0.5em;
font-size: 1.5em; min-width: 0.1em;
color: if($bar-menus-monochrome, $bar-menus-icons-passive, $bar-menus-menu-bluetooth-icons-passive);
&.active {
color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-bluetooth-icons-active);
}
} }
.connection-status.txt-icon {
.connection-status { margin-left: 0.2em;
font-size: 0.9em;
margin-left: 0.6rem;
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text);
opacity: 0.4;
} }
.battery{
opacity: 0.6;
}
}
spinner {
min-height: 1.3em;
min-width: 1.3em;
color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-bluetooth-iconbutton-active);
}
.menu-separator {
margin: 0em 1em;
}
.menu-switch.bluetooth {
background-color: if($bar-menus-monochrome, $bar-menus-switch-disabled, $bar-menus-menu-bluetooth-switch-disabled);
&:checked {
background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-bluetooth-switch-enabled);
}
slider {
background-color: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-bluetooth-switch-puck);
}
&:hover {
trough {
background: if($bar-menus-monochrome, $bar-menus-switch-disabled, $bar-menus-menu-bluetooth-switch-disabled);
}
slider {
background: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-bluetooth-switch-puck);
}
}
&:active {
background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-bluetooth-switch-enabled);
}
}
.no-bluetooth-devices.dim,
.search-bluetooth-label.dim,
.bluetooth-disabled.dim {
&:last-child {
margin-bottom: 2em;
}
color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-bluetooth-text);
opacity: 0.5;
}
} }

View File

@@ -18,6 +18,12 @@ export const BluetoothMenuSettings = (): Scrollable<Child, Attribute> => {
title: 'Show Battery Percentage for Connected Devices (If Supported)', title: 'Show Battery Percentage for Connected Devices (If Supported)',
type: 'boolean', type: 'boolean',
}), }),
Option({
opt: options.menus.bluetooth.batteryState,
title: 'Show Battery When',
type: 'enum',
enums: ['connected', 'paired', 'always'],
}),
Option({ Option({
opt: options.menus.bluetooth.batteryIcon, opt: options.menus.bluetooth.batteryIcon,
title: 'Battery Icon', title: 'Battery Icon',