feat(ags): add bluetooth stuff and some refactor
This commit is contained in:
parent
5dba231074
commit
a76d920a57
19 changed files with 328 additions and 278 deletions
|
@ -1,14 +0,0 @@
|
||||||
final: prev: {
|
|
||||||
blueberry = prev.blueberry.overrideAttrs (o: {
|
|
||||||
patches =
|
|
||||||
(o.patches or [])
|
|
||||||
++ [
|
|
||||||
./wayland.patch
|
|
||||||
];
|
|
||||||
buildInputs =
|
|
||||||
(o.buildInputs or [])
|
|
||||||
++ [
|
|
||||||
prev.libappindicator
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -1,95 +0,0 @@
|
||||||
# https://github.com/linuxmint/blueberry/issues/120
|
|
||||||
--- /usr/lib/blueberry/blueberry-tray.py.org 2021-12-13 01:02:56.923349069 -0800
|
|
||||||
+++ /usr/lib/blueberry/blueberry-tray.py 2021-12-13 02:21:23.253300141 -0800
|
|
||||||
@@ -5,8 +5,8 @@
|
|
||||||
import gi
|
|
||||||
gi.require_version('Gtk', '3.0')
|
|
||||||
gi.require_version('GnomeBluetooth', '1.0')
|
|
||||||
-gi.require_version('XApp', '1.0')
|
|
||||||
-from gi.repository import Gtk, Gdk, GnomeBluetooth, Gio, XApp
|
|
||||||
+gi.require_version('AppIndicator3', '0.1')
|
|
||||||
+from gi.repository import AppIndicator3, Gtk, Gdk, GnomeBluetooth, Gio
|
|
||||||
import rfkillMagic
|
|
||||||
import setproctitle
|
|
||||||
import subprocess
|
|
||||||
@@ -53,12 +53,16 @@
|
|
||||||
self.model.connect('row-deleted', self.update_icon_callback)
|
|
||||||
self.model.connect('row-inserted', self.update_icon_callback)
|
|
||||||
|
|
||||||
- self.icon = XApp.StatusIcon()
|
|
||||||
- self.icon.set_name("blueberry")
|
|
||||||
- self.icon.set_tooltip_text(_("Bluetooth"))
|
|
||||||
- self.icon.connect("activate", self.on_statusicon_activated)
|
|
||||||
- self.icon.connect("button-release-event", self.on_statusicon_released)
|
|
||||||
-
|
|
||||||
+ self.paired_devices = {}
|
|
||||||
+
|
|
||||||
+ self.icon = AppIndicator3.Indicator.new(
|
|
||||||
+ 'BlueBerry',
|
|
||||||
+ 'blueberry',
|
|
||||||
+ AppIndicator3.IndicatorCategory.SYSTEM_SERVICES
|
|
||||||
+ )
|
|
||||||
+ self.icon.set_status(AppIndicator3.IndicatorStatus.ACTIVE)
|
|
||||||
+ self.icon.set_menu(self.build_menu())
|
|
||||||
+
|
|
||||||
self.update_icon_callback(None, None, None)
|
|
||||||
|
|
||||||
def on_settings_changed_cb(self, setting, key, data=None):
|
|
||||||
@@ -71,21 +75,23 @@
|
|
||||||
return
|
|
||||||
|
|
||||||
if self.rfkill.hard_block or self.rfkill.soft_block:
|
|
||||||
- self.icon.set_icon_name(self.tray_disabled_icon)
|
|
||||||
- self.icon.set_tooltip_text(_("Bluetooth is disabled"))
|
|
||||||
+ self.icon.set_title(_("Bluetooth is disabled"))
|
|
||||||
+ self.icon.set_icon(self.tray_disabled_icon)
|
|
||||||
+ self.icon.set_menu(self.build_menu())
|
|
||||||
else:
|
|
||||||
- self.icon.set_icon_name(self.tray_icon)
|
|
||||||
+ self.icon.set_icon(self.tray_icon)
|
|
||||||
+ self.icon.set_menu(self.build_menu())
|
|
||||||
self.update_connected_state()
|
|
||||||
|
|
||||||
def update_connected_state(self):
|
|
||||||
self.get_devices()
|
|
||||||
|
|
||||||
if len(self.connected_devices) > 0:
|
|
||||||
- self.icon.set_icon_name(self.tray_active_icon)
|
|
||||||
- self.icon.set_tooltip_text(_("Bluetooth: Connected to %s") % (", ".join(self.connected_devices)))
|
|
||||||
+ self.icon.set_title(_("Bluetooth: Connected to %s") % (", ".join(self.connected_devices)))
|
|
||||||
+ self.icon.set_icon(self.tray_active_icon)
|
|
||||||
else:
|
|
||||||
- self.icon.set_icon_name(self.tray_icon)
|
|
||||||
- self.icon.set_tooltip_text(_("Bluetooth"))
|
|
||||||
+ self.icon.set_title(_("Bluetooth"))
|
|
||||||
+ self.icon.set_icon(self.tray_icon)
|
|
||||||
|
|
||||||
def get_devices(self):
|
|
||||||
self.connected_devices = []
|
|
||||||
@@ -117,13 +118,11 @@
|
|
||||||
|
|
||||||
iter = self.model.iter_next(iter)
|
|
||||||
|
|
||||||
- def on_statusicon_activated(self, icon, button, time):
|
|
||||||
- if button == Gdk.BUTTON_PRIMARY:
|
|
||||||
- subprocess.Popen(["blueberry"])
|
|
||||||
+ def start_blueberry(self, _ignored):
|
|
||||||
+ subprocess.Popen(["blueberry"])
|
|
||||||
|
|
||||||
- def on_statusicon_released(self, icon, x, y, button, time, position):
|
|
||||||
- if button == 3:
|
|
||||||
+ def build_menu(self):
|
|
||||||
menu = Gtk.Menu()
|
|
||||||
|
|
||||||
if not self.rfkill.hard_block:
|
|
||||||
if self.rfkill.soft_block:
|
|
||||||
@@ -168,7 +170,7 @@
|
|
||||||
menu.append(item)
|
|
||||||
|
|
||||||
menu.show_all()
|
|
||||||
- icon.popup_menu(menu, x, y, button, time, position)
|
|
||||||
+ return menu
|
|
||||||
|
|
||||||
def toggle_connect_cb(self, item, data = None):
|
|
||||||
proxy = self.paired_devices[data]
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
];
|
];
|
||||||
|
|
||||||
nixpkgs.overlays = [
|
nixpkgs.overlays = [
|
||||||
(import ./blueberry)
|
|
||||||
(import ./spotifywm)
|
(import ./spotifywm)
|
||||||
(import ./squeekboard)
|
(import ./squeekboard)
|
||||||
|
|
||||||
|
|
|
@ -1,33 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
radio_status () {
|
|
||||||
radio_status=$(nmcli radio wifi)
|
|
||||||
if [[ $radio_status == "enabled" ]]; then
|
|
||||||
echo "on"
|
|
||||||
else
|
|
||||||
echo "off"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ $1 == "toggle-radio" ]]; then
|
|
||||||
stat=$(radio_status)
|
|
||||||
if [[ $stat == "on" ]]; then
|
|
||||||
nmcli radio wifi off
|
|
||||||
else
|
|
||||||
nmcli radio wifi on
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
FILE='/home/matt/.config/.bluetooth'
|
|
||||||
get_state() {
|
|
||||||
if [[ "$(rfkill list | grep -A 1 hci0 | grep -o no)" == "no" ]]; then
|
|
||||||
echo " " > "$FILE"
|
|
||||||
else
|
|
||||||
echo " " > "$FILE"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
if [[ "$1" == "blue-toggle" ]]; then
|
|
||||||
rfkill toggle bluetooth
|
|
||||||
get_state
|
|
||||||
fi
|
|
|
@ -1,10 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
## Make bluetooth status persistent between reboots
|
|
||||||
if [[ ! -f "$HOME/.config/.bluetooth" ]]; then
|
|
||||||
echo > "$FILE"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if grep -q "$HOME/.config/.bluetooth"; then
|
|
||||||
rfkill block bluetooth
|
|
||||||
fi
|
|
|
@ -1,37 +1,24 @@
|
||||||
import Battery from 'resource:///com/github/Aylur/ags/service/battery.js';
|
import Battery from 'resource:///com/github/Aylur/ags/service/battery.js';
|
||||||
|
|
||||||
import { Box, EventBox, Icon, Label, Overlay, Revealer } from 'resource:///com/github/Aylur/ags/widget.js';
|
import { Label, Icon, Box } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
|
||||||
import Separator from '../../misc/separator.js';
|
import Separator from '../../misc/separator.js';
|
||||||
|
|
||||||
const LOW_BATT = 20;
|
const LOW_BATT = 20;
|
||||||
|
|
||||||
|
|
||||||
const NumOverlay = () => Label({
|
const Indicator = () => Icon({
|
||||||
className: 'bg-text',
|
className: 'battery-indicator',
|
||||||
hpack: 'center',
|
|
||||||
vpack: 'center',
|
binds: [['icon', Battery, 'icon-name']],
|
||||||
|
|
||||||
connections: [[Battery, (self) => {
|
connections: [[Battery, (self) => {
|
||||||
self.label = `${Math.floor(Battery.percent / 10)}`;
|
self.toggleClassName('charging', Battery.charging);
|
||||||
self.visible = !Battery.charging;
|
self.toggleClassName('charged', Battery.charged);
|
||||||
|
self.toggleClassName('low', Battery.percent < LOW_BATT);
|
||||||
}]],
|
}]],
|
||||||
});
|
});
|
||||||
|
|
||||||
const Indicator = (overlay) => Overlay({
|
|
||||||
child: Icon({
|
|
||||||
className: 'battery-indicator',
|
|
||||||
|
|
||||||
binds: [['icon', Battery, 'icon-name']],
|
|
||||||
|
|
||||||
connections: [[Battery, (self) => {
|
|
||||||
self.toggleClassName('charging', Battery.charging);
|
|
||||||
self.toggleClassName('charged', Battery.charged);
|
|
||||||
self.toggleClassName('low', Battery.percent < LOW_BATT);
|
|
||||||
}]],
|
|
||||||
}),
|
|
||||||
overlays: [overlay],
|
|
||||||
});
|
|
||||||
|
|
||||||
const LevelLabel = (props) => Label({
|
const LevelLabel = (props) => Label({
|
||||||
...props,
|
...props,
|
||||||
className: 'label',
|
className: 'label',
|
||||||
|
@ -43,44 +30,12 @@ const LevelLabel = (props) => Label({
|
||||||
|
|
||||||
const SPACING = 5;
|
const SPACING = 5;
|
||||||
|
|
||||||
export default () => {
|
export default () => Box({
|
||||||
const rev1 = NumOverlay();
|
className: 'toggle-off battery',
|
||||||
const rev = Revealer({
|
|
||||||
transition: 'slide_right',
|
|
||||||
child: Box({
|
|
||||||
children: [
|
|
||||||
Separator(SPACING),
|
|
||||||
LevelLabel(),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const widget = EventBox({
|
children: [
|
||||||
onHover: () => {
|
Indicator(),
|
||||||
rev.revealChild = true;
|
Separator(SPACING),
|
||||||
|
LevelLabel(),
|
||||||
if (!Battery.charging) {
|
],
|
||||||
rev1.visible = false;
|
});
|
||||||
}
|
|
||||||
},
|
|
||||||
onHoverLost: () => {
|
|
||||||
rev.revealChild = false;
|
|
||||||
|
|
||||||
if (!Battery.charging) {
|
|
||||||
rev1.visible = true;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Box({
|
|
||||||
className: 'battery',
|
|
||||||
children: [
|
|
||||||
Indicator(rev1),
|
|
||||||
|
|
||||||
rev,
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
widget.rev = rev;
|
|
||||||
|
|
||||||
return widget;
|
|
||||||
};
|
|
||||||
|
|
64
devices/wim/config/ags/js/bar/buttons/bluetooth.js
Normal file
64
devices/wim/config/ags/js/bar/buttons/bluetooth.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
|
||||||
|
|
||||||
|
import { Label, Box, EventBox, Icon, Revealer } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
|
||||||
|
import Separator from '../../misc/separator.js';
|
||||||
|
|
||||||
|
|
||||||
|
const Indicator = (props) => Icon({
|
||||||
|
...props,
|
||||||
|
connections: [[Bluetooth, (self) => {
|
||||||
|
if (Bluetooth.enabled) {
|
||||||
|
self.icon = Bluetooth.connectedDevices[0] ?
|
||||||
|
Bluetooth.connectedDevices[0].iconName :
|
||||||
|
'bluetooth-active-symbolic';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self.icon = 'bluetooth-disabled-symbolic';
|
||||||
|
}
|
||||||
|
}]],
|
||||||
|
});
|
||||||
|
|
||||||
|
const ConnectedLabel = (props) => Label({
|
||||||
|
...props,
|
||||||
|
connections: [[Bluetooth, (self) => {
|
||||||
|
self.label = Bluetooth.connectedDevices[0] ?
|
||||||
|
`${Bluetooth.connectedDevices[0]}` :
|
||||||
|
'Disconnected';
|
||||||
|
}, 'notify::connected-devices']],
|
||||||
|
});
|
||||||
|
|
||||||
|
const SPACING = 5;
|
||||||
|
|
||||||
|
export default () => {
|
||||||
|
const rev = Revealer({
|
||||||
|
transition: 'slide_right',
|
||||||
|
child: Box({
|
||||||
|
children: [
|
||||||
|
Separator(SPACING),
|
||||||
|
ConnectedLabel(),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const widget = EventBox({
|
||||||
|
onHover: () => {
|
||||||
|
rev.revealChild = true;
|
||||||
|
},
|
||||||
|
onHoverLost: () => {
|
||||||
|
rev.revealChild = false;
|
||||||
|
},
|
||||||
|
child: Box({
|
||||||
|
className: 'bluetooth',
|
||||||
|
children: [
|
||||||
|
Indicator(),
|
||||||
|
|
||||||
|
rev,
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.rev = rev;
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
};
|
|
@ -3,7 +3,7 @@ import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js';
|
import { Box, Label } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
|
||||||
import Audio from './audio.js';
|
import Audio from './audio.js';
|
||||||
import Battery from './battery.js';
|
import Bluetooth from './bluetooth.js';
|
||||||
import KeyboardLayout from './keyboard-layout.js';
|
import KeyboardLayout from './keyboard-layout.js';
|
||||||
import Network from './network.js';
|
import Network from './network.js';
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ export default () => EventBox({
|
||||||
|
|
||||||
Audio(),
|
Audio(),
|
||||||
|
|
||||||
Battery(),
|
Bluetooth(),
|
||||||
|
|
||||||
Network(),
|
Network(),
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ import { Window, CenterBox, Box } from 'resource:///com/github/Aylur/ags/widget.
|
||||||
|
|
||||||
import Separator from '../misc/separator.js';
|
import Separator from '../misc/separator.js';
|
||||||
|
|
||||||
|
import Battery from './buttons/battery.js';
|
||||||
import Brightness from './buttons/brightness.js';
|
import Brightness from './buttons/brightness.js';
|
||||||
import Clock from './buttons/clock.js';
|
import Clock from './buttons/clock.js';
|
||||||
import CurrentWindow from './buttons/current-window.js';
|
import CurrentWindow from './buttons/current-window.js';
|
||||||
|
@ -41,11 +42,11 @@ export default () => Window({
|
||||||
|
|
||||||
SysTray(),
|
SysTray(),
|
||||||
|
|
||||||
Brightness(),
|
Workspaces(),
|
||||||
|
|
||||||
Separator(SPACING),
|
Separator(SPACING),
|
||||||
|
|
||||||
Workspaces(),
|
CurrentWindow(),
|
||||||
|
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
@ -54,7 +55,7 @@ export default () => Window({
|
||||||
children: [
|
children: [
|
||||||
Separator(SPACING),
|
Separator(SPACING),
|
||||||
|
|
||||||
CurrentWindow(),
|
Clock(),
|
||||||
|
|
||||||
Separator(SPACING),
|
Separator(SPACING),
|
||||||
],
|
],
|
||||||
|
@ -63,7 +64,11 @@ export default () => Window({
|
||||||
endWidget: Box({
|
endWidget: Box({
|
||||||
hpack: 'end',
|
hpack: 'end',
|
||||||
children: [
|
children: [
|
||||||
Clock(),
|
Brightness(),
|
||||||
|
|
||||||
|
Separator(SPACING),
|
||||||
|
|
||||||
|
Battery(),
|
||||||
|
|
||||||
Separator(SPACING),
|
Separator(SPACING),
|
||||||
|
|
||||||
|
|
|
@ -72,11 +72,10 @@ const CalendarWidget = () => Box({
|
||||||
});
|
});
|
||||||
|
|
||||||
const TOP_MARGIN = 6;
|
const TOP_MARGIN = 6;
|
||||||
const RIGHT_MARGIN = 182;
|
|
||||||
|
|
||||||
export default () => PopupWindow({
|
export default () => PopupWindow({
|
||||||
anchor: ['top', 'right'],
|
anchor: ['top'],
|
||||||
margins: [TOP_MARGIN, RIGHT_MARGIN, 0, 0],
|
margins: [TOP_MARGIN, 0, 0, 0],
|
||||||
name: 'calendar',
|
name: 'calendar',
|
||||||
child: Box({
|
child: Box({
|
||||||
className: 'date',
|
className: 'date',
|
||||||
|
|
192
devices/wim/config/ags/js/quick-settings/bluetooth.js
Normal file
192
devices/wim/config/ags/js/quick-settings/bluetooth.js
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
|
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
|
||||||
|
|
||||||
|
import { Box, Icon, Label, ListBox, Overlay, Revealer, Scrollable } from 'resource:///com/github/Aylur/ags/widget.js';
|
||||||
|
|
||||||
|
import EventBox from '../misc/cursorbox.js';
|
||||||
|
|
||||||
|
const SCROLL_THRESHOLD_H = 200;
|
||||||
|
const SCROLL_THRESHOLD_N = 7;
|
||||||
|
|
||||||
|
|
||||||
|
const BluetoothDevice = (dev) => {
|
||||||
|
const widget = Box({
|
||||||
|
className: 'menu-item',
|
||||||
|
});
|
||||||
|
|
||||||
|
const child = Box({
|
||||||
|
hexpand: true,
|
||||||
|
children: [
|
||||||
|
Icon({
|
||||||
|
binds: [['icon', dev, 'icon-name']],
|
||||||
|
}),
|
||||||
|
|
||||||
|
Label({
|
||||||
|
binds: [['label', dev, 'name']],
|
||||||
|
}),
|
||||||
|
|
||||||
|
Icon({
|
||||||
|
icon: 'object-select-symbolic',
|
||||||
|
hexpand: true,
|
||||||
|
hpack: 'end',
|
||||||
|
connections: [[dev, (self) => {
|
||||||
|
self.setCss(`opacity: ${dev.paired ? '1' : '0'};`);
|
||||||
|
}]],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
widget.dev = dev;
|
||||||
|
widget.add(Revealer({
|
||||||
|
revealChild: true,
|
||||||
|
transition: 'slide_down',
|
||||||
|
child: EventBox({
|
||||||
|
onPrimaryClickRelease: () => dev.setConnection(true),
|
||||||
|
child,
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
return widget;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const BluetoothMenu = () => {
|
||||||
|
const DevList = new Map();
|
||||||
|
const topArrow = Revealer({
|
||||||
|
transition: 'slide_down',
|
||||||
|
child: Icon({
|
||||||
|
icon: `${App.configDir }/icons/down-large.svg`,
|
||||||
|
className: 'scrolled-indicator',
|
||||||
|
size: 16,
|
||||||
|
css: '-gtk-icon-transform: rotate(180deg);',
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
const bottomArrow = Revealer({
|
||||||
|
transition: 'slide_up',
|
||||||
|
child: Icon({
|
||||||
|
icon: `${App.configDir }/icons/down-large.svg`,
|
||||||
|
className: 'scrolled-indicator',
|
||||||
|
size: 16,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
return Overlay({
|
||||||
|
pass_through: true,
|
||||||
|
overlays: [
|
||||||
|
Box({
|
||||||
|
vpack: 'start',
|
||||||
|
hpack: 'center',
|
||||||
|
css: 'margin-top: 12px',
|
||||||
|
children: [topArrow],
|
||||||
|
}),
|
||||||
|
|
||||||
|
Box({
|
||||||
|
vpack: 'end',
|
||||||
|
hpack: 'center',
|
||||||
|
css: 'margin-bottom: 12px',
|
||||||
|
children: [bottomArrow],
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
|
||||||
|
child: Box({
|
||||||
|
className: 'menu',
|
||||||
|
|
||||||
|
child: Scrollable({
|
||||||
|
hscroll: 'never',
|
||||||
|
vscroll: 'never',
|
||||||
|
|
||||||
|
connections: [['edge-reached', (_, pos) => {
|
||||||
|
// Manage scroll indicators
|
||||||
|
if (pos === 2) {
|
||||||
|
topArrow.revealChild = false;
|
||||||
|
bottomArrow.revealChild = true;
|
||||||
|
}
|
||||||
|
else if (pos === 3) {
|
||||||
|
topArrow.revealChild = true;
|
||||||
|
bottomArrow.revealChild = false;
|
||||||
|
}
|
||||||
|
}]],
|
||||||
|
|
||||||
|
child: ListBox({
|
||||||
|
setup: (self) => {
|
||||||
|
self.set_sort_func((a, b) => {
|
||||||
|
return b.get_children()[0].dev.paired -
|
||||||
|
a.get_children()[0].dev.paired;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
connections: [[Bluetooth, (box) => {
|
||||||
|
// Get all devices
|
||||||
|
const Devices = [].concat(
|
||||||
|
Bluetooth.devices,
|
||||||
|
Bluetooth.connectedDevices,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Add missing devices
|
||||||
|
Devices.forEach((dev) => {
|
||||||
|
if (!DevList.has(dev) && dev.name) {
|
||||||
|
DevList.set(dev, BluetoothDevice(dev));
|
||||||
|
|
||||||
|
box.add(DevList.get(dev));
|
||||||
|
box.show_all();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Delete ones that don't exist anymore
|
||||||
|
const difference = Array.from(DevList.keys())
|
||||||
|
.filter((dev) => !Devices
|
||||||
|
.find((d) => dev === d) &&
|
||||||
|
dev.name);
|
||||||
|
|
||||||
|
difference.forEach((dev) => {
|
||||||
|
const devWidget = DevList.get(dev);
|
||||||
|
|
||||||
|
if (devWidget) {
|
||||||
|
if (devWidget.toDestroy) {
|
||||||
|
devWidget.get_parent().destroy();
|
||||||
|
DevList.delete(dev);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
devWidget.children[0].revealChild = false;
|
||||||
|
devWidget.toDestroy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Start scrolling after a specified height
|
||||||
|
// is reached by the children
|
||||||
|
const height = Math.max(
|
||||||
|
box.get_parent().get_allocated_height(),
|
||||||
|
SCROLL_THRESHOLD_H,
|
||||||
|
);
|
||||||
|
|
||||||
|
const scroll = box.get_parent().get_parent();
|
||||||
|
|
||||||
|
if (box.get_children().length > SCROLL_THRESHOLD_N) {
|
||||||
|
scroll.vscroll = 'always';
|
||||||
|
scroll.setCss(`min-height: ${height}px;`);
|
||||||
|
|
||||||
|
// Make bottom scroll indicator appear only
|
||||||
|
// when first getting overflowing children
|
||||||
|
if (!(bottomArrow.revealChild === true ||
|
||||||
|
topArrow.revealChild === true)) {
|
||||||
|
bottomArrow.revealChild = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
scroll.vscroll = 'never';
|
||||||
|
scroll.setCss('');
|
||||||
|
topArrow.revealChild = false;
|
||||||
|
bottomArrow.revealChild = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger sort_func
|
||||||
|
box.get_children().forEach((ch) => {
|
||||||
|
ch.changed();
|
||||||
|
});
|
||||||
|
}]],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
|
@ -11,6 +11,7 @@ import EventBox from '../misc/cursorbox.js';
|
||||||
import Separator from '../misc/separator.js';
|
import Separator from '../misc/separator.js';
|
||||||
|
|
||||||
import { NetworkMenu } from './network.js';
|
import { NetworkMenu } from './network.js';
|
||||||
|
import { BluetoothMenu } from './bluetooth.js';
|
||||||
|
|
||||||
const SPACING = 28;
|
const SPACING = 28;
|
||||||
|
|
||||||
|
@ -19,6 +20,7 @@ const ButtonStates = [];
|
||||||
const GridButton = ({
|
const GridButton = ({
|
||||||
command = () => { /**/ },
|
command = () => { /**/ },
|
||||||
secondaryCommand = () => { /**/ },
|
secondaryCommand = () => { /**/ },
|
||||||
|
onOpen = () => { /**/ },
|
||||||
icon,
|
icon,
|
||||||
indicator,
|
indicator,
|
||||||
menu,
|
menu,
|
||||||
|
@ -129,6 +131,7 @@ const GridButton = ({
|
||||||
|
|
||||||
if (Activated.value) {
|
if (Activated.value) {
|
||||||
deg = menu ? 360 : 450;
|
deg = menu ? 360 : 450;
|
||||||
|
onOpen(menu);
|
||||||
}
|
}
|
||||||
self.setCss(`
|
self.setCss(`
|
||||||
-gtk-icon-transform: rotate(${deg}deg);
|
-gtk-icon-transform: rotate(${deg}deg);
|
||||||
|
@ -156,7 +159,7 @@ const Row = ({ buttons } = {}) => {
|
||||||
hpack: 'center',
|
hpack: 'center',
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Box(),
|
Box({ vertical: true }),
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -180,8 +183,7 @@ const FirstRow = () => Row({
|
||||||
command: () => Network.toggleWifi(),
|
command: () => Network.toggleWifi(),
|
||||||
|
|
||||||
secondaryCommand: () => {
|
secondaryCommand: () => {
|
||||||
execAsync(['bash', '-c', 'nm-connection-editor'])
|
// TODO: connection editor
|
||||||
.catch(print);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
icon: [Network, (icon) => {
|
icon: [Network, (icon) => {
|
||||||
|
@ -193,62 +195,52 @@ const FirstRow = () => Row({
|
||||||
}],
|
}],
|
||||||
|
|
||||||
menu: NetworkMenu(),
|
menu: NetworkMenu(),
|
||||||
|
onOpen: () => Network.wifi.scan(),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
|
// TODO: do vpn
|
||||||
GridButton({
|
GridButton({
|
||||||
command: () => {
|
command: () => {
|
||||||
execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh blue-toggle'])
|
//
|
||||||
.catch(print);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
secondaryCommand: () => {
|
secondaryCommand: () => {
|
||||||
execAsync(['bash', '-c', 'blueberry'])
|
//
|
||||||
.catch(print);
|
},
|
||||||
|
|
||||||
|
icon: 'airplane-mode-disabled-symbolic',
|
||||||
|
}),
|
||||||
|
|
||||||
|
GridButton({
|
||||||
|
command: () => Bluetooth.toggle(),
|
||||||
|
|
||||||
|
secondaryCommand: () => {
|
||||||
|
// TODO: bluetooth connection editor
|
||||||
},
|
},
|
||||||
|
|
||||||
icon: [Bluetooth, (self) => {
|
icon: [Bluetooth, (self) => {
|
||||||
if (Bluetooth.enabled) {
|
if (Bluetooth.enabled) {
|
||||||
self.icon = 'bluetooth-active-symbolic';
|
self.icon = Bluetooth.connectedDevices[0] ?
|
||||||
execAsync(['bash', '-c',
|
Bluetooth.connectedDevices[0].iconName :
|
||||||
'echo > $HOME/.config/.bluetooth']).catch(print);
|
'bluetooth-active-symbolic';
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
self.icon = 'bluetooth-disabled-symbolic';
|
self.icon = 'bluetooth-disabled-symbolic';
|
||||||
execAsync(['bash', '-c',
|
|
||||||
'echo > $HOME/.config/.bluetooth']).catch(print);
|
|
||||||
}
|
}
|
||||||
}, 'changed'],
|
}],
|
||||||
|
|
||||||
indicator: [Bluetooth, (self) => {
|
indicator: [Bluetooth, (self) => {
|
||||||
if (Bluetooth.connectedDevices[0]) {
|
self.label = Bluetooth.connectedDevices[0] ?
|
||||||
self.label = String(Bluetooth.connectedDevices[0]);
|
`${Bluetooth.connectedDevices[0]}` :
|
||||||
}
|
'Disconnected';
|
||||||
else {
|
}, 'notify::connected-devices'],
|
||||||
self.label = 'Disconnected';
|
|
||||||
}
|
|
||||||
}, 'changed'],
|
|
||||||
}),
|
|
||||||
|
|
||||||
// TODO: replace with vpn
|
menu: BluetoothMenu(),
|
||||||
GridButton({
|
onOpen: (menu) => {
|
||||||
command: () => {
|
execAsync(`bluetoothctl scan ${menu.revealChild ?
|
||||||
execAsync(['bash', '-c',
|
'on' :
|
||||||
'$AGS_PATH/qs-toggles.sh toggle-radio']).catch(print);
|
'off'}`);
|
||||||
},
|
},
|
||||||
|
|
||||||
secondaryCommand: () => {
|
|
||||||
execAsync(['notify-send', 'set this up moron'])
|
|
||||||
.catch(print);
|
|
||||||
},
|
|
||||||
|
|
||||||
icon: [Network, (self) => {
|
|
||||||
if (Network.wifi.enabled) {
|
|
||||||
self.icon = 'airplane-mode-disabled-symbolic';
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
self.icon = 'airplane-mode-symbolic';
|
|
||||||
}
|
|
||||||
}, 'changed'],
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
|
@ -13,7 +13,7 @@ const SCROLL_THRESHOLD_N = 7;
|
||||||
|
|
||||||
const AccessPoint = (ap) => {
|
const AccessPoint = (ap) => {
|
||||||
const widget = Box({
|
const widget = Box({
|
||||||
className: 'ap',
|
className: 'menu-item',
|
||||||
});
|
});
|
||||||
|
|
||||||
widget.ap = Variable(ap);
|
widget.ap = Variable(ap);
|
||||||
|
@ -38,7 +38,11 @@ const AccessPoint = (ap) => {
|
||||||
hexpand: true,
|
hexpand: true,
|
||||||
hpack: 'end',
|
hpack: 'end',
|
||||||
connections: [[Network, (self) => {
|
connections: [[Network, (self) => {
|
||||||
self.visible = widget.ap.value.ssid === Network.wifi.ssid;
|
self.setCss(`opacity: ${
|
||||||
|
widget.ap.value.ssid === Network.wifi.ssid ?
|
||||||
|
'1' :
|
||||||
|
'0'
|
||||||
|
};`);
|
||||||
}]],
|
}]],
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
|
@ -55,7 +59,6 @@ const AccessPoint = (ap) => {
|
||||||
child,
|
child,
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
widget.show_all();
|
|
||||||
|
|
||||||
return widget;
|
return widget;
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||||
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
import Hyprland from 'resource:///com/github/Aylur/ags/service/hyprland.js';
|
||||||
|
|
||||||
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
|
|
||||||
|
|
||||||
import Brightness from '../services/brightness.js';
|
import Brightness from '../services/brightness.js';
|
||||||
import Pointers from '../services/pointers.js';
|
import Pointers from '../services/pointers.js';
|
||||||
import Tablet from '../services/tablet.js';
|
import Tablet from '../services/tablet.js';
|
||||||
|
@ -16,8 +14,6 @@ export default () => {
|
||||||
globalThis.Tablet = Tablet;
|
globalThis.Tablet = Tablet;
|
||||||
globalThis.closeAll = closeAll;
|
globalThis.closeAll = closeAll;
|
||||||
|
|
||||||
execAsync(['bash', '-c', '$AGS_PATH/startup.sh']).catch(print);
|
|
||||||
|
|
||||||
TouchGestures.addGesture({
|
TouchGestures.addGesture({
|
||||||
name: 'openAppLauncher',
|
name: 'openAppLauncher',
|
||||||
gesture: 'UD',
|
gesture: 'UD',
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
background-color: $bg;
|
background-color: $bg;
|
||||||
color: $fg;
|
color: $fg;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
border-top-right-radius: 0;
|
|
||||||
border: 2px solid $contrast-bg;
|
border: 2px solid $contrast-bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ap {
|
.menu-item {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|
|
@ -53,7 +53,8 @@
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.audio {
|
.audio,
|
||||||
|
.bluetooth {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-right: -10px;
|
margin-right: -10px;
|
||||||
|
@ -72,7 +73,6 @@
|
||||||
.battery {
|
.battery {
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
margin-right: -10px;
|
|
||||||
|
|
||||||
.battery-indicator {
|
.battery-indicator {
|
||||||
&.charging {
|
&.charging {
|
||||||
|
|
|
@ -16,8 +16,7 @@ plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Autostart programs
|
# Autostart programs
|
||||||
exec-once = sleep 4; blueberry-tray
|
exec-once = sleep 3; nextcloud --background
|
||||||
exec-once = sleep 6; nextcloud --background
|
|
||||||
exec-once = squeekboard
|
exec-once = squeekboard
|
||||||
exec-once = ags
|
exec-once = ags
|
||||||
exec-once = sleep 3; ags -t applauncher
|
exec-once = sleep 3; ags -t applauncher
|
||||||
|
|
|
@ -42,7 +42,6 @@ in {
|
||||||
lisgd
|
lisgd
|
||||||
squeekboard
|
squeekboard
|
||||||
ydotool
|
ydotool
|
||||||
blueberry
|
|
||||||
]));
|
]));
|
||||||
})
|
})
|
||||||
];
|
];
|
||||||
|
|
Loading…
Reference in a new issue