feat(ags): start working on bluetooth
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-12-04 00:18:11 -05:00
parent 5c94aeb86a
commit d02d82c7e1
11 changed files with 256 additions and 14 deletions

View file

@ -6,6 +6,7 @@ import style from '../style/main.scss';
import AppLauncher from '../widgets/applauncher/main';
import Bar from '../widgets/bar/wim';
import BgLayer from '../widgets/bg-layer/main';
import BluetoothWindow from '../widgets/bluetooth/wim';
import Calendar from '../widgets/date/wim';
import Clipboard from '../widgets/clipboard/main';
import Corners from '../widgets/corners/main';
@ -55,6 +56,7 @@ export default () => {
AppLauncher();
Bar();
BluetoothWindow();
Calendar();
Clipboard();
Corners();

View file

@ -2,6 +2,7 @@
@use '../widgets/applauncher';
@use '../widgets/bar';
@use '../widgets/bluetooth';
@use '../widgets/clipboard';
@use '../widgets/date';
@use '../widgets/icon-browser';

View file

@ -19,7 +19,8 @@
background-color: color.adjust(colors.$window_bg_color, $lightness: 3%);
}
&.network icon {
&.network icon,
&.bluetooth icon {
min-width: 30px;
}

View file

@ -0,0 +1,67 @@
import { bind, Variable } from 'astal';
import { App, Gtk } from 'astal/gtk3';
import AstalBluetooth from 'gi://AstalBluetooth';
import PopupWindow from '../../misc/popup-window';
export default () => {
const bluetooth = AstalBluetooth.get_default();
const Hovered = Variable(false);
return (
<button
className="bar-item bluetooth"
cursor="pointer"
onHover={() => Hovered.set(true)}
onHoverLost={() => Hovered.set(false)}
onButtonReleaseEvent={(self) => {
const win = App.get_window('win-bluetooth') as PopupWindow;
win.set_x_pos(
self.get_allocation(),
'right',
);
win.visible = !win.visible;
}}
>
{bind(bluetooth, 'isPowered').as((isPowered) => {
if (!isPowered) {
return (<icon icon="bluetooth-disabled-symbolic" />);
}
else {
return (
<box>
{bind(bluetooth, 'isConnected').as((isConnected) => {
const device = bluetooth.get_devices().find((dev) => dev.connected);
if (!isConnected || !device) {
return (<icon icon="bluetooth-active-symbolic" />);
}
else {
return (
<>
<icon icon={bind(device, 'icon')} />
<revealer
revealChild={bind(Hovered)}
transitionType={Gtk.RevealerTransitionType.SLIDE_LEFT}
>
<label label={bind(device, 'name')} />
</revealer>
</>
);
}
})}
</box>
);
}
})}
</button>
);
};

View file

@ -2,6 +2,7 @@ import { Astal, Gtk } from 'astal/gtk3';
import Audio from './items/audio';
import Battery from './items/battery';
import Bluetooth from './items/bluetooth';
import Brightness from './items/brightness';
import Clock from './items/clock';
import CurrentClient from './items/current-client';
@ -48,6 +49,10 @@ export default () => (
<Separator size={8} />
<Bluetooth />
<Separator size={8} />
<NotifButton />
<Separator size={8} />

View file

@ -0,0 +1,24 @@
@use 'sass:color';
@use '../../style/colors';
.bluetooth {
margin-top: 0;
.toggle-button {
background-color: colors.$window_bg_color;
transition: background-color 0.2s ease-in-out, border-color 0.2s ease-in-out;
box-shadow: 2px 1px 2px colors.$accent-color;
padding: 4px;
margin: 4px 4px 4px 4px;
&.active {
box-shadow: 0 0 0 white;
margin: 6px 4px 2px 4px;
background-color: color.adjust(colors.$window_bg_color, $lightness: -3%);
}
}
}

View file

@ -0,0 +1,57 @@
import { bind } from 'astal';
import { Gtk, Widget } from 'astal/gtk3';
import AstalBluetooth from 'gi://AstalBluetooth';
import Separator from '../misc/separator';
export default (dev: AstalBluetooth.Device) => {
const rev = (
<revealer
transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}
>
<box>
TODO: add buttons here
</box>
</revealer>
) as Widget.Revealer;
const button = (
<button
onButtonReleaseEvent={() => {
rev.revealChild = !rev.revealChild;
}}
>
<box>
<icon
icon={bind(dev, 'connected').as((isConnected) => isConnected ?
'check-active-symbolic' :
'check-mixed-symbolic')}
css={bind(dev, 'paired').as((isPaired) => isPaired ?
'' :
'opacity: 0;')}
/>
<Separator size={8} />
<icon
icon={bind(dev, 'icon').as((iconName) =>
iconName ? `${iconName}-symbolic` : 'help-browser-symbolic')}
/>
<Separator size={8} />
<label label={bind(dev, 'name')} />
</box>
</button>
);
return (
<box vertical>
{button}
{rev}
</box>
);
};

View file

@ -0,0 +1,67 @@
import { bind } from 'astal';
import { Gtk } from 'astal/gtk3';
import AstalBluetooth from 'gi://AstalBluetooth';
import { ToggleButton } from '../misc/subclasses';
import Separator from '../misc/separator';
import DeviceWidget from './device';
export default () => {
const bluetooth = AstalBluetooth.get_default();
return (
<box
className="bluetooth widget"
vertical
>
<centerbox homogeneous>
<switch
cursor="pointer"
valign={Gtk.Align.CENTER}
halign={Gtk.Align.START}
active={bind(bluetooth, 'isPowered')}
setup={(self) => {
self.connect('notify::active', () => {
bluetooth.adapter?.set_powered(self.active);
});
}}
/>
<box />
<ToggleButton
cursor="pointer"
halign={Gtk.Align.END}
className="toggle-button"
sensitive={bind(bluetooth, 'isPowered')}
onToggled={(self) => {
self.toggleClassName('active', self.active);
if (self.active) {
bluetooth.adapter?.start_discovery();
}
else {
bluetooth.adapter?.stop_discovery();
}
}}
>
<icon icon="emblem-synchronizing-symbolic" css="font-size: 20px;" />
</ToggleButton>
</centerbox>
<Separator size={8} vertical />
{bind(bluetooth, 'devices').as((devices) => devices
.filter((dev) => dev.name)
.map((dev) => DeviceWidget(dev)))}
</box>
);
};

View file

@ -0,0 +1,15 @@
import { Astal } from 'astal/gtk3';
import PopupWindow from '../misc/popup-window';
import BluetoothWidget from './main';
export default () => (
<PopupWindow
name="bluetooth"
anchor={Astal.WindowAnchor.RIGHT | Astal.WindowAnchor.TOP}
>
<BluetoothWidget />
</PopupWindow>
);

View file

@ -0,0 +1,14 @@
import { astalify, Gtk, type ConstructProps } from 'astal/gtk3';
import { register } from 'astal/gobject';
@register()
export class ToggleButton extends astalify(Gtk.ToggleButton) {
constructor(props: ConstructProps<
ToggleButton,
Gtk.ToggleButton.ConstructorProps
>) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
super(props as any);
}
}

View file

@ -1,7 +1,7 @@
import { bind, idle, Variable } from 'astal';
import { Astal, astalify, Gtk, type ConstructProps, Widget } from 'astal/gtk3';
import { register } from 'astal/gobject';
import { Astal, Gtk, Widget } from 'astal/gtk3';
import { ToggleButton } from '../misc/subclasses';
import Separator from '../misc/separator';
import Arc from './arcs';
@ -13,17 +13,6 @@ import { defaultOskLayout, oskLayouts } from './keyboard-layouts';
const keyboardLayout = defaultOskLayout;
const keyboardJson = oskLayouts[keyboardLayout];
@register()
class ToggleButton extends astalify(Gtk.ToggleButton) {
constructor(props: ConstructProps<
ToggleButton,
Gtk.ToggleButton.ConstructorProps
>) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
super(props as any);
}
}
const L_KEY_PER_ROW = [8, 7, 6, 6, 6, 4];
const SPACING = 4;
const COLOR = 'rgba(0, 0, 0, 0.5)';