Touch up network menu and finish bluetooth menu rework.

This commit is contained in:
Jas Singh
2024-06-30 04:02:38 -07:00
parent de72c05088
commit 9cf5b0f5ea
19 changed files with 907 additions and 491 deletions

View File

@@ -8,6 +8,7 @@ export const Padding = (name) =>
child: Widget.Box(), child: Widget.Box(),
setup: (w) => w.on("button-press-event", () => App.toggleWindow(name)), setup: (w) => w.on("button-press-event", () => App.toggleWindow(name)),
}); });
const moveBoxToCursor = (self, minWidth, minHeight, fixed) => { const moveBoxToCursor = (self, minWidth, minHeight, fixed) => {
globalMousePos.connect("changed", ({ value }) => { globalMousePos.connect("changed", ({ value }) => {
let monWidth = hyprland.monitors[hyprland.active.monitor.id].width; let monWidth = hyprland.monitors[hyprland.active.monitor.id].width;
@@ -85,7 +86,7 @@ export default ({
child: Widget.Box({ child: Widget.Box({
class_name: "dropdown-menu-container", class_name: "dropdown-menu-container",
can_focus: true, can_focus: true,
children: [Padding(name), child], children: [child],
}), }),
}), }),
}), }),

View File

@@ -12,7 +12,7 @@ const activeDevices = () => {
child: Widget.Label({ child: Widget.Label({
class_name: "menu-label audio volume", class_name: "menu-label audio volume",
hexpand: true, hexpand: true,
hpack: "center", hpack: "start",
label: "Volume", label: "Volume",
}), }),
}), }),

View File

@@ -16,7 +16,7 @@ const availableDevices = () => {
child: Widget.Label({ child: Widget.Label({
class_name: "menu-label audio playback", class_name: "menu-label audio playback",
hexpand: true, hexpand: true,
hpack: "center", hpack: "start",
label: "Playback Devices", label: "Playback Devices",
}), }),
}), }),
@@ -50,7 +50,7 @@ const availableDevices = () => {
child: Widget.Label({ child: Widget.Label({
class_name: "menu-label audio playback", class_name: "menu-label audio playback",
hexpand: true, hexpand: true,
hpack: "center", hpack: "start",
label: "Input Devices", label: "Input Devices",
}), }),
}), }),

View File

@@ -0,0 +1,76 @@
const connectedControls = (dev, connectedDevices) => {
if (!connectedDevices.includes(dev.address)) {
return Widget.Box({});
}
return Widget.Box({
vpack: "start",
class_name: "bluetooth-controls",
children: [
Widget.Button({
class_name: "menu-icon-button unpair bluetooth",
child: Widget.Label({
tooltip_text: dev.paired ? "unpair" : "pair",
class_name: "menu-icon-button-label unpair bluetooth",
label: dev.paired ? "" : "",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button disconnect bluetooth",
child: Widget.Label({
tooltip_text: dev.connected ? "disconnect" : "connect",
class_name: "menu-icon-button-label disconnect bluetooth",
label: dev.connected ? "󱘖" : "",
}),
on_primary_click: () => dev.setConnection(!dev.connected),
}),
Widget.Button({
class_name: "menu-icon-button untrust bluetooth",
child: Widget.Label({
tooltip_text: dev.trusted ? "untrust" : "trust",
class_name: "menu-icon-button-label untrust bluetooth",
label: dev.trusted ? "" : "󱖡",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button delete bluetooth",
child: Widget.Label({
tooltip_text: "delete",
class_name: "menu-icon-button-label delete bluetooth",
label: "󰆴",
}),
on_primary_click: () => {
Utils.execAsync([
"bash",
"-c",
`bluetoothctl remove ${dev.address}`,
]).catch((err) => console.error("Bluetooth Remove", err));
},
}),
],
});
};
export { connectedControls };

View File

@@ -0,0 +1,134 @@
import { connectedControls } from "./connectedControls.js";
const devices = (bluetooth, self) => {
return self.hook(bluetooth, () => {
if (!bluetooth.enabled) {
return (self.child = Widget.Box({
class_name: "bluetooth-items",
vertical: true,
expand: true,
vpack: "center",
hpack: "center",
children: [
Widget.Label({
class_name: "dim",
hexpand: true,
label: "Bluetooth is disabled",
}),
],
}));
}
const availableDevices = bluetooth.devices
.filter(
(btDev) => btDev.name !== null,
)
.sort((a, b) => {
if (a.connected || a.paired) {
return -1;
}
if (b.connected || b.paired) {
return -1;
}
return b.name - a.name;
});
const conDevNames = availableDevices
.filter((d) => d.connected || d.paired)
.map((d) => d.address);
if (!availableDevices.length) {
return (self.child = Widget.Box({
class_name: "bluetooth-items",
vertical: true,
expand: true,
vpack: "center",
hpack: "center",
children: [
Widget.Label({
class_name: "dim",
hexpand: true,
label: "No devices currently found",
}),
Widget.Label({
class_name: "dim",
hexpand: true,
label: "Press '󰑐' to search",
}),
],
}));
}
return (self.child = Widget.Box({
vertical: true,
children: availableDevices.map((device) => {
return Widget.Box({
children: [
Widget.Button({
hexpand: true,
class_name: `bluetooth-element-item ${device}`,
on_primary_click: () => {
if (!conDevNames.includes(device.address))
device.setConnection(true);
},
child: Widget.Box({
hexpand: true,
children: [
Widget.Box({
hexpand: true,
hpack: "start",
children: [
Widget.Icon({
vpack: "start",
class_name: `menu-button-icon bluetooth ${conDevNames.includes(device.address) ? "active" : ""}`,
icon: `${device["icon-name"]}-symbolic`,
}),
Widget.Box({
vertical: true,
children: [
Widget.Label({
vpack: "center",
hpack: "start",
class_name: "menu-button-name bluetooth",
truncate: "end",
wrap: true,
label: device.alias,
}),
Widget.Revealer({
hpack: "start",
reveal_child: device.connected || device.paired,
child: Widget.Label({
hpack: "start",
class_name: "connection-status dim",
label: device.connected ? "Connected" : "Paired",
}),
}),
],
}),
],
}),
Widget.Box({
hpack: "end",
children: device.connecting
? [
Widget.Spinner({
vpack: "start",
class_name: "spinner bluetooth",
}),
]
: [],
}),
],
}),
}),
connectedControls(device, conDevNames),
],
});
}),
}));
});
};
export { devices };

View File

@@ -0,0 +1,26 @@
const bluetooth = await Service.import("bluetooth");
import { label } from "./label.js";
import { devices } from "./devicelist.js";
const Devices = () => {
return Widget.Box({
class_name: "menu-section-container",
vertical: true,
children: [
label(bluetooth),
Widget.Box({
class_name: "menu-items-section",
vertical: true,
child: Widget.Box({
class_name: "menu-content",
vertical: true,
setup: (self) => {
devices(bluetooth, self);
},
}),
}),
],
});
};
export { Devices };

View File

@@ -0,0 +1,74 @@
const label = (bluetooth) => {
const searchInProgress = Variable(false);
const startRotation = () => {
searchInProgress.value = true;
setTimeout(() => {
searchInProgress.value = false;
}, 10 * 1000);
};
return Widget.Box({
class_name: "menu-label-container",
hpack: "fill",
vpack: "start",
children: [
Widget.Label({
class_name: "menu-label",
vpack: "start",
hpack: "start",
label: "Bluetooth",
}),
Widget.Box({
class_name: "controls-container",
vpack: "start",
children: [
Widget.Switch({
class_name: "menu-switch bluetooth",
hexpand: true,
hpack: "end",
active: bluetooth.bind("enabled"),
on_activate: ({ active }) => {
searchInProgress.value = false;
Utils.execAsync([
"bash",
"-c",
`bluetoothctl power ${active ? "on" : "off"}`,
]).catch((err) =>
console.error(
`bluetoothctl power ${active ? "on" : "off"}`,
err,
),
);
},
}),
Widget.Separator({
class_name: "menu-separator bluetooth",
}),
Widget.Button({
vpack: "center",
class_name: "menu-icon-button search",
on_primary_click: () => {
startRotation();
Utils.execAsync([
"bash",
"-c",
"bluetoothctl --timeout 120 scan on",
]).catch((err) => {
searchInProgress.value = false;
console.error("bluetoothctl --timeout 120 scan on", err);
});
},
child: Widget.Icon({
class_name: searchInProgress
.bind("value")
.as((v) => (v ? "spinning" : "")),
icon: "view-refresh-symbolic",
}),
}),
],
}),
],
});
};
export { label };

View File

@@ -0,0 +1,383 @@
const bluetooth = await Service.import("bluetooth");
import DropdownMenu from "../DropdownMenu.js";
export default () => {
const connectedDevices = (btDevices) => {
const noDevices = () => {
return Widget.Box({
hpack: "center",
hexpand: true,
child: Widget.Label({
class_name: "dim",
label: "No devices connected",
}),
});
};
const deviceList = () => {
return Widget.Box({
vertical: true,
children: btDevices.map((dev) =>
Widget.Box({
child: Widget.Box({
children: [
Widget.Box({
hpack: "start",
vertical: true,
children: [
Widget.Box({
children: [
Widget.Button({
child: Widget.Icon(`${dev["icon-name"]}-symbolic`),
}),
Widget.Label({
class_name: "menu-button-name bluetooth",
truncate: "end",
wrap: true,
label: dev.alias,
}),
],
}),
Widget.Box({
class_name: "menu-button-name-container status dim",
children: [
Widget.Label({
class_name: "menu-button-name status dim",
label: dev.connected
? "Connected"
: dev.paired
? "Paired"
: "",
}),
],
}),
],
}),
Widget.Box({
hpack: "end",
expand: true,
children: [
Widget.Button({
class_name: "menu-icon-button unpair bluetooth",
child: Widget.Label({
tooltip_text: dev.paired ? "unpair" : "pair",
class_name: "menu-icon-button-label unpair bluetooth",
label: dev.paired ? "" : "",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button disconnect bluetooth",
child: Widget.Label({
tooltip_text: dev.connected ? "disconnect" : "connect",
class_name:
"menu-icon-button-label disconnect bluetooth",
label: dev.connected ? "󱘖" : "",
}),
on_primary_click: () => dev.setConnection(false),
}),
Widget.Button({
class_name: "menu-icon-button untrust bluetooth",
child: Widget.Label({
tooltip_text: dev.trusted ? "untrust" : "trust",
class_name: "menu-icon-button-label untrust bluetooth",
label: dev.trusted ? "" : "󱖡",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button delete bluetooth",
child: Widget.Label({
tooltip_text: "delete",
class_name: "menu-icon-button-label delete bluetooth",
label: "󰆴",
}),
on_primary_click: () => {
Utils.execAsync([
"bash",
"-c",
`bluetoothctl remove ${dev.address}`,
]).catch((err) =>
console.error("Bluetooth Remove", err),
);
},
}),
],
}),
],
}),
}),
),
});
};
return btDevices.length === 0 ? noDevices() : deviceList();
};
const renderDevices = () => {
return Widget.Box({
class_name: "search-devices-container",
vertical: true,
setup: (self) =>
self.hook(bluetooth, () => {
const availableDevices = bluetooth.devices.filter(
(device) =>
device.name !== null &&
!bluetooth.connected_devices.find(
(dev) => dev.address === device.address,
),
);
if (availableDevices.length === 0) {
return (self.children = [
Widget.Box({
class_name: "empty-bt-devices-container dim",
vertical: true,
children: [
Widget.Label({
hexpand: true,
label: "No devices currently found",
}),
Widget.Label({
hexpand: true,
label: "Press '󰑐' to search",
}),
],
}),
]);
}
return (self.children = bluetooth.devices
.filter(
(device) =>
device.name !== null &&
!bluetooth.connected_devices.find(
(dev) => dev.address === device.address,
),
)
.map((device) => {
return Widget.Button({
hexpand: true,
class_name: `menu-button bluetooth ${device}`,
on_primary_click: () => {
device.setConnection(true);
},
child: Widget.Box({
children: [
Widget.Box({
hpack: "start",
children: [
Widget.Icon({
class_name: "menu-button-icon bluetooth",
icon: `${device["icon-name"]}-symbolic`,
}),
Widget.Label({
hexpand: true,
class_name: "menu-button-name bluetooth",
truncate: "end",
wrap: true,
label: device.alias,
}),
],
}),
Widget.Box({
hpack: "end",
children: device.connecting
? [
Widget.Label({
class_name: "bluetooth-isconnecting",
label: "󰲼",
}),
]
: [],
}),
],
}),
});
}));
}),
});
};
const bluetoothOnModule = () => {
return Widget.Box({
vertical: true,
children: [
Widget.Box({
class_name: "menu-container bluetooth",
children: [
Widget.Box({
vertical: true,
children: [
Widget.Box({
class_name: "menu-label-container bluetooth",
children: [
Widget.Box({
hpack: "start",
child: Widget.Label({
class_name: "menu-label bluetooth",
label: "Devices",
}),
}),
Widget.Box({
hexpand: true,
hpack: "end",
child: Widget.Button({
class_name: "menu-icon-button",
on_primary_click: () => {
Utils.execAsync([
"bash",
"-c",
"bluetoothctl --timeout 120 scan on",
]).catch((err) =>
console.error(
"bluetoothctl --timeout 120 scan on",
err,
),
);
},
child: Widget.Icon("view-refresh-symbolic"),
}),
}),
],
}),
Widget.Box({
child: renderDevices(),
}),
],
}),
],
}),
],
});
};
const bluetoothOffModule = () => {
return Widget.Box({
class_name: "bluetooth-disabled-menu",
vertical: true,
children: [
Widget.Label({
hexpand: true,
vexpand: true,
label: bluetooth
.bind("state")
.as((state) =>
state === "turning-off"
? "Bluetooth is turning off..."
: "Bluetooth is disabled",
),
}),
],
});
};
return DropdownMenu({
name: "bluetoothmenu",
transition: "crossfade",
minWidth: 350,
child: Widget.Box({
class_name: "menu-items",
child: Widget.Box({
vertical: true,
class_name: "menu-items-container",
children: [
Widget.Box({
class_name: "menu-dropdown-label-container",
children: [
Widget.Box({
hexpand: true,
hpack: "start",
child: Widget.Label({
class_name: "menu-dropdown-label bluetooth",
label: "Bluetooth",
}),
}),
Widget.Box({
hexpand: true,
hpack: "end",
children: [
// NOTE: Do we want to add this back to restart bluetooth service if it every hangs?
// Widget.Button({
// class_name: "menu-icon-button restart-bluetooth-service",
// tooltip_text: "Restart Bluetooth Service",
// on_primary_click: () => Utils.execAsync('systemctl restart bluetooth'),
// child: Widget.Label({
// class_name: "menu-icon-button-label",
// label: "󱄌"
// })
// }),
Widget.Switch({
class_name: "menu-switch bluetooth",
active: bluetooth.bind("enabled"),
on_activate: ({ active }) =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl power ${active ? "on" : "off"}`,
]).catch((err) =>
console.error(
`bluetoothctl power ${active ? "on" : "off"}`,
err,
),
),
}),
],
}),
],
}),
Widget.Box({
vertical: true,
children: bluetooth.bind("enabled").as((isOn) =>
isOn
? [
Widget.Box({
class_name: "menu-label-container",
child: Widget.Label({
class_name: "menu-label bluetooth",
hpack: "start",
label: "My Devices",
}),
}),
Widget.Box({
vertical: true,
class_name: "menu-item-box",
child: bluetooth
.bind("connected_devices")
.as((btConDevs) => connectedDevices(btConDevs)),
}),
]
: [],
),
}),
Widget.Box({
vertical: true,
child: bluetooth
.bind("enabled")
.as((btEnabled) =>
btEnabled ? bluetoothOnModule() : bluetoothOffModule(),
),
}),
],
}),
}),
});
};

View File

@@ -1,382 +1,21 @@
const bluetooth = await Service.import("bluetooth"); const bluetooth = await Service.import("bluetooth");
import DropdownMenu from "../DropdownMenu.js"; import DropdownMenu from "../DropdownMenu.js";
import { Devices } from "./devices/index.js";
export default () => { export default () => {
const connectedDevices = (btDevices) => {
const noDevices = () => {
return Widget.Box({
hpack: "center",
hexpand: true,
child: Widget.Label({
class_name: "dim",
label: "No devices connected",
}),
});
};
const deviceList = () => {
return Widget.Box({
vertical: true,
children: btDevices.map((dev) =>
Widget.Box({
child: Widget.Box({
children: [
Widget.Box({
hpack: "start",
vertical: true,
children: [
Widget.Box({
children: [
Widget.Button({
child: Widget.Icon(`${dev["icon-name"]}-symbolic`),
}),
Widget.Label({
class_name: "menu-button-name bluetooth",
truncate: "end",
wrap: true,
label: dev.alias,
}),
],
}),
Widget.Box({
class_name: "menu-button-name-container status dim",
children: [
Widget.Label({
class_name: "menu-button-name status dim",
label: dev.connected
? "Connected"
: dev.paired
? "Paired"
: "",
}),
],
}),
],
}),
Widget.Box({
hpack: "end",
expand: true,
children: [
Widget.Button({
class_name: "menu-icon-button unpair bluetooth",
child: Widget.Label({
tooltip_text: dev.paired ? "unpair" : "pair",
class_name: "menu-icon-button-label unpair bluetooth",
label: dev.paired ? "" : "",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.paired ? "unpair" : "pair"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button disconnect bluetooth",
child: Widget.Label({
tooltip_text: dev.connected ? "disconnect" : "connect",
class_name:
"menu-icon-button-label disconnect bluetooth",
label: dev.connected ? "󱘖" : "",
}),
on_primary_click: () => dev.setConnection(false),
}),
Widget.Button({
class_name: "menu-icon-button untrust bluetooth",
child: Widget.Label({
tooltip_text: dev.trusted ? "untrust" : "trust",
class_name: "menu-icon-button-label untrust bluetooth",
label: dev.trusted ? "" : "󱖡",
}),
on_primary_click: () =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
]).catch((err) =>
console.error(
`bluetoothctl ${dev.trusted ? "untrust" : "trust"} ${dev.address}`,
err,
),
),
}),
Widget.Button({
class_name: "menu-icon-button delete bluetooth",
child: Widget.Label({
tooltip_text: "delete",
class_name: "menu-icon-button-label delete bluetooth",
label: "󰆴",
}),
on_primary_click: () => {
Utils.execAsync([
"bash",
"-c",
`bluetoothctl remove ${dev.address}`,
]).catch((err) =>
console.error("Bluetooth Remove", err),
);
},
}),
],
}),
],
}),
}),
),
});
};
return btDevices.length === 0 ? noDevices() : deviceList();
};
const renderDevices = () => {
return Widget.Box({
class_name: "search-devices-container",
vertical: true,
setup: (self) =>
self.hook(bluetooth, () => {
const availableDevices = bluetooth.devices.filter(
(device) =>
device.name !== null &&
!bluetooth.connected_devices.find(
(dev) => dev.address === device.address,
),
);
if (availableDevices.length === 0) {
return (self.children = [
Widget.Box({
class_name: "empty-bt-devices-container dim",
vertical: true,
children: [
Widget.Label({
hexpand: true,
label: "No devices currently found",
}),
Widget.Label({
hexpand: true,
label: "Press '󰑐' to search",
}),
],
}),
]);
}
return (self.children = bluetooth.devices
.filter(
(device) =>
device.name !== null &&
!bluetooth.connected_devices.find(
(dev) => dev.address === device.address,
),
)
.map((device) => {
return Widget.Button({
hexpand: true,
class_name: `menu-button bluetooth ${device}`,
on_primary_click: () => {
device.setConnection(true);
},
child: Widget.Box({
children: [
Widget.Box({
hpack: "start",
children: [
Widget.Icon({
class_name: "menu-button-icon bluetooth",
icon: `${device["icon-name"]}-symbolic`,
}),
Widget.Label({
hexpand: true,
class_name: "menu-button-name bluetooth",
truncate: "end",
wrap: true,
label: device.alias,
}),
],
}),
Widget.Box({
hpack: "end",
children: device.connecting
? [
Widget.Label({
class_name: "bluetooth-isconnecting",
label: "󰲼",
}),
]
: [],
}),
],
}),
});
}));
}),
});
};
const bluetoothOnModule = () => {
return Widget.Box({
vertical: true,
children: [
Widget.Box({
class_name: "menu-container bluetooth",
children: [
Widget.Box({
vertical: true,
children: [
Widget.Box({
class_name: "menu-label-container bluetooth",
children: [
Widget.Box({
hpack: "start",
child: Widget.Label({
class_name: "menu-label bluetooth",
label: "Devices",
}),
}),
Widget.Box({
hexpand: true,
hpack: "end",
child: Widget.Button({
class_name: "menu-icon-button",
on_primary_click: () => {
Utils.execAsync([
"bash",
"-c",
"bluetoothctl --timeout 120 scan on",
]).catch((err) =>
console.error(
"bluetoothctl --timeout 120 scan on",
err,
),
);
},
child: Widget.Icon("view-refresh-symbolic"),
}),
}),
],
}),
Widget.Box({
child: renderDevices(),
}),
],
}),
],
}),
],
});
};
const bluetoothOffModule = () => {
return Widget.Box({
class_name: "bluetooth-disabled-menu",
vertical: true,
children: [
Widget.Label({
hexpand: true,
vexpand: true,
label: bluetooth
.bind("state")
.as((state) =>
state === "turning-off"
? "Bluetooth is turning off..."
: "Bluetooth is disabled",
),
}),
],
});
};
return DropdownMenu({ return DropdownMenu({
name: "bluetoothmenu", name: "bluetoothmenu",
transition: "crossfade", transition: "crossfade",
minWidth: 350,
child: Widget.Box({ child: Widget.Box({
class_name: "menu-items", class_name: "menu-items",
hpack: "fill",
hexpand: true,
child: Widget.Box({ child: Widget.Box({
vertical: true, vertical: true,
class_name: "menu-items-container", hpack: "fill",
children: [ hexpand: true,
Widget.Box({ class_name: "menu-items-container bluetooth",
class_name: "menu-dropdown-label-container", child: Devices(),
children: [
Widget.Box({
hexpand: true,
hpack: "start",
child: Widget.Label({
class_name: "menu-dropdown-label bluetooth",
label: "Bluetooth",
}),
}),
Widget.Box({
hexpand: true,
hpack: "end",
children: [
// NOTE: Do we want to add this back to restart bluetooth service if it every hangs?
// Widget.Button({
// class_name: "menu-icon-button restart-bluetooth-service",
// tooltip_text: "Restart Bluetooth Service",
// on_primary_click: () => Utils.execAsync('systemctl restart bluetooth'),
// child: Widget.Label({
// class_name: "menu-icon-button-label",
// label: "󱄌"
// })
// }),
Widget.Switch({
class_name: "menu-switch bluetooth",
active: bluetooth.bind("enabled"),
on_activate: ({ active }) =>
Utils.execAsync([
"bash",
"-c",
`bluetoothctl power ${active ? "on" : "off"}`,
]).catch((err) =>
console.error(
`bluetoothctl power ${active ? "on" : "off"}`,
err,
),
),
}),
],
}),
],
}),
Widget.Box({
vertical: true,
children: bluetooth.bind("enabled").as((isOn) =>
isOn
? [
Widget.Box({
class_name: "menu-label-container",
child: Widget.Label({
class_name: "menu-label bluetooth",
hpack: "start",
label: "My Devices",
}),
}),
Widget.Box({
vertical: true,
class_name: "menu-item-box",
child: bluetooth
.bind("connected_devices")
.as((btConDevs) => connectedDevices(btConDevs)),
}),
]
: [],
),
}),
Widget.Box({
vertical: true,
child: bluetooth
.bind("enabled")
.as((btEnabled) =>
btEnabled ? bluetoothOnModule() : bluetoothOffModule(),
),
}),
],
}), }),
}), }),
}); });

View File

@@ -11,54 +11,52 @@ const Ethernet = () => {
child: Widget.Label({ child: Widget.Label({
class_name: "menu-label", class_name: "menu-label",
hexpand: true, hexpand: true,
hpack: "center", hpack: "start",
label: "Ethernet", label: "Ethernet",
}), }),
}), }),
Widget.Box({ Widget.Box({
class_name: "menu-items-section", class_name: "menu-items-section",
vertical: true, vertical: true,
children: [ child: Widget.Box({
Widget.Box({ class_name: "menu-content",
class_name: "menu-content", vertical: true,
vertical: true, child: network.bind("wired").as((wired) => {
child: network.bind("wired").as((wired) => { return Widget.Box({
return Widget.Box({ class_name: "network-element-item",
class_name: "network-element-item", child: Widget.Box({
child: Widget.Box({ hpack: "start",
hpack: "start", children: [
children: [ Widget.Icon({
Widget.Icon({ class_name: `network-icon ethernet ${network.wired.state === "activated" ? "active" : ""}`,
class_name: `network-icon ethernet ${network.wired.state === "activated" ? "active" : ""}`, tooltip_text: wired.internet,
tooltip_text: wired.internet, icon: `${wired["icon_name"]}`,
icon: `${wired["icon_name"]}`, }),
}), Widget.Box({
Widget.Box({ class_name: "connection-container",
class_name: "connection-container", vertical: true,
vertical: true, children: [
children: [ Widget.Label({
Widget.Label({ class_name: "active-connection",
class_name: "active-connection", hpack: "start",
hpack: "start", truncate: "end",
truncate: "end", wrap: true,
wrap: true, label: `Ethernet Connection ${typeof wired.speed === "number" ? `(${wired.speed / 1000} Gbps)` : ""}`,
label: `Ethernet Connection ${typeof wired.speed === "number" ? `(${wired.speed / 1000} Gbps)` : ""}`, }),
}), Widget.Label({
Widget.Label({ hpack: "start",
hpack: "start", class_name: "connection-status dim",
class_name: "connection-status dim", label:
label: wired.internet.charAt(0).toUpperCase() +
wired.internet.charAt(0).toUpperCase() + wired.internet.slice(1),
wired.internet.slice(1), }),
}), ],
], }),
}), ],
], }),
}), });
});
}),
}), }),
], }),
}), }),
], ],
}); });

View File

@@ -1,6 +1,5 @@
const renderWapStaging = (self, network, staging, connecting) => { const renderWapStaging = (self, network, staging, connecting) => {
Utils.merge([network.bind("wifi"), staging.bind("value")], () => { Utils.merge([network.bind("wifi"), staging.bind("value")], () => {
console.log(JSON.stringify(network, null, 2));
if (!Object.keys(staging.value).length) { if (!Object.keys(staging.value).length) {
return (self.child = Widget.Box()); return (self.child = Widget.Box());
} }

View File

@@ -16,7 +16,7 @@ const Wifi = () => {
child: Widget.Label({ child: Widget.Label({
class_name: "menu-label", class_name: "menu-label",
hexpand: true, hexpand: true,
hpack: "center", hpack: "start",
label: "Wi-Fi", label: "Wi-Fi",
}), }),
}), }),

View File

@@ -82,8 +82,6 @@ export default () => {
vertical: true, vertical: true,
setup: (self) => { setup: (self) => {
self.hook(notifs, () => { self.hook(notifs, () => {
console.log(JSON.stringify(notifs, null, 2));
const notifHasImg = (notif) => { const notifHasImg = (notif) => {
return notif.image !== undefined && notif.image.length; return notif.image !== undefined && notif.image.length;
}; };

View File

@@ -1,3 +1,5 @@
@import "../colors";
menu { menu {
margin: 6px; margin: 6px;
padding: 6px; padding: 6px;
@@ -201,8 +203,8 @@ tooltip {
} }
tooltip.background { tooltip.background {
background-color: $primary_bg; background-color: $crust;
color: $default_fg; color: $text;
border-radius: 6px; border-radius: 6px;
} }

View File

@@ -1,47 +1,91 @@
@import "../colors"; @import "../colors";
.menu-dropdown-label.bluetooth { .menu-items-container.bluetooth {
color: $sky; font-size: 1.3em;
} .menu-section-container {
margin: 1.35em 0em;
}
.menu-label.bluetooth { .menu-label-container {
color: $sky; .menu-label {
} color: $sky;
}
.menu-button-isactive.bluetooth { .controls-container {
color: $sky; margin: 0.5em 1em;
} }
}
.menu-button.bluetooth {
&:hover { .menu-items-section {
min-height: 20em;
font-size: 1em;
}
button {
margin-right: 0.5em;
&.search {
@keyframes spin {
to { -gtk-icon-transform: rotate(1turn); }
}
image.spinning {
animation-name: spin;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
image {
color: $text;
}
&:hover image {
color: $sky;
}
font-size: 0.8em;
margin-bottom: 0em;
}
&:hover {
color: $sky;
}
}
.bluetooth-element-item {
margin-bottom: 0.5em;
// background: $teal;
&:hover {
color: $sky;
}
image {
// background: $red;
margin-right: 0em;
margin-top: 0.0em;
min-height: 1em;
min-width: 1em;
&.active {
color: $sky;
}
}
label {
// background: $yellow;
font-size: 1em;
}
.connection-status {
font-size: 0.9em;
margin-left: 0.8em;
}
}
spinner {
min-height: 1.3em;
min-width: 1.3em;
color: $sky; color: $sky;
} }
}
.menu-items { .menu-separator {
min-width: 350px; margin: 0em 1em;
}
.menu-icon-button {
font-size: 1.2rem;
min-width: 2rem;
&:hover {
color: $sky;
} }
} }
.menu-icon-button.delete {
margin-left: 0.5rem;
}
.menu-icon-button-label {
font-size: 1.3rem;
}
.menu-button-name.status {
margin-left: 2.1rem;
}
.bluetooth-isconnecting {
color: $sky;
}

View File

@@ -239,11 +239,14 @@ tooltip label {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.dropdown-menu-container { .dropdown-menu-container {
// margin: 1.5em; min-height: 10em;
// box-shadow: 0 0 0.6em $mantle;
} }
.top-right-event-box_top *{ .top-right-event-box_top *{
min-height: 0em; min-height: 0em;
margin-top: 2.5em; margin-top: 2.5em;
} }
.menu-label {
margin: 0.5em 1em;
color: $sky;
}

View File

@@ -29,7 +29,7 @@
} }
.menu-section-container.wifi { .menu-section-container.wifi {
.menu-items-section { .menu-items-section {
min-height: 3em; min-height: 12em;
} }
} }

101
style.css
View File

@@ -207,8 +207,8 @@ tooltip {
} }
tooltip.background { tooltip.background {
background-color: #0e0e1e; background-color: #11111b;
color: #CDD6F4; color: #cdd6f4;
border-radius: 6px; border-radius: 6px;
} }
@@ -633,11 +633,20 @@ tooltip label {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;
} }
.dropdown-menu-container {
min-height: 10em;
}
.top-right-event-box_top * { .top-right-event-box_top * {
min-height: 0em; min-height: 0em;
margin-top: 2.5em; margin-top: 2.5em;
} }
.menu-label {
margin: 0.5em 1em;
color: #89dceb;
}
window#powermenu, window#powermenu,
window#verification { window#verification {
background-color: rgba(0, 0, 0, 0.4); background-color: rgba(0, 0, 0, 0.4);
@@ -851,7 +860,7 @@ window#powermenu .powermenu.box {
font-size: 0.9em; font-size: 0.9em;
} }
.menu-items-container.network .menu-section-container.wifi .menu-items-section { .menu-items-container.network .menu-section-container.wifi .menu-items-section {
min-height: 3em; min-height: 12em;
} }
.menu-items-container.network .network-element-item:not(:last-child) { .menu-items-container.network .network-element-item:not(:last-child) {
margin-bottom: 0.5em; margin-bottom: 0.5em;
@@ -888,49 +897,79 @@ window#powermenu .powermenu.box {
color: #eba0ac; color: #eba0ac;
} }
.menu-dropdown-label.bluetooth { .menu-items-container.bluetooth {
font-size: 1.3em;
}
.menu-items-container.bluetooth .menu-section-container {
margin: 1.35em 0em;
}
.menu-items-container.bluetooth .menu-label-container .menu-label {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth .menu-label-container .controls-container {
.menu-label.bluetooth { margin: 0.5em 1em;
}
.menu-items-container.bluetooth .menu-items-section {
min-height: 20em;
font-size: 1em;
}
.menu-items-container.bluetooth button {
margin-right: 0.5em;
}
.menu-items-container.bluetooth button.search {
font-size: 0.8em;
margin-bottom: 0em;
}
@keyframes spin {
to {
-gtk-icon-transform: rotate(1turn);
}
}
.menu-items-container.bluetooth button.search image.spinning {
animation-name: spin;
animation-duration: 1s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
.menu-items-container.bluetooth button.search image {
color: #cdd6f4;
}
.menu-items-container.bluetooth button.search:hover image {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth button:hover {
.menu-button-isactive.bluetooth {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth .bluetooth-element-item {
.menu-button.bluetooth:hover { margin-bottom: 0.5em;
}
.menu-items-container.bluetooth .bluetooth-element-item:hover {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth .bluetooth-element-item image {
.menu-items { margin-right: 0em;
min-width: 350px; margin-top: 0em;
min-height: 1em;
min-width: 1em;
} }
.menu-items-container.bluetooth .bluetooth-element-item image.active {
.menu-icon-button {
font-size: 1.2rem;
min-width: 2rem;
}
.menu-icon-button:hover {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth .bluetooth-element-item label {
.menu-icon-button.delete { font-size: 1em;
margin-left: 0.5rem;
} }
.menu-items-container.bluetooth .bluetooth-element-item .connection-status {
.menu-icon-button-label { font-size: 0.9em;
font-size: 1.3rem; margin-left: 0.8em;
} }
.menu-items-container.bluetooth spinner {
.menu-button-name.status { min-height: 1.3em;
margin-left: 2.1rem; min-width: 1.3em;
}
.bluetooth-isconnecting {
color: #89dceb; color: #89dceb;
} }
.menu-items-container.bluetooth .menu-separator {
margin: 0em 1em;
}
.media-indicator-container { .media-indicator-container {
min-width: 35rem; min-width: 35rem;

File diff suppressed because one or more lines are too long