mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-01-04 23:02:48 +00:00
feat: update ags
This commit is contained in:
73
home/desktops/hyprland/ags/js/quicksettings/QuickSettings.js
Normal file
73
home/desktops/hyprland/ags/js/quicksettings/QuickSettings.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Header from "./widgets/Header.js";
|
||||
import PopupWindow from "../misc/PopupWindow.js";
|
||||
import { Volume, Microhone, SinkSelector, AppMixer } from "./widgets/Volume.js";
|
||||
import { NetworkToggle, WifiSelection } from "./widgets/Network.js";
|
||||
import { BluetoothToggle, BluetoothDevices } from "./widgets/Bluetooth.js";
|
||||
import { ThemeToggle, ThemeSelector } from "./widgets/Theme.js";
|
||||
import { ProfileToggle, ProfileSelector } from "./widgets/AsusProfile.js";
|
||||
import Media from "./widgets/Media.js";
|
||||
import Brightness from "./widgets/Brightness.js";
|
||||
import DND from "./widgets/DND.js";
|
||||
import MicMute from "./widgets/MicMute.js";
|
||||
import options from "../options.js";
|
||||
|
||||
const Row = (toggles = [], menus = []) =>
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: "row horizontal",
|
||||
children: toggles,
|
||||
}),
|
||||
...menus,
|
||||
],
|
||||
});
|
||||
|
||||
const Homogeneous = (toggles) =>
|
||||
Widget.Box({
|
||||
homogeneous: true,
|
||||
children: toggles,
|
||||
});
|
||||
|
||||
export default () =>
|
||||
PopupWindow({
|
||||
name: "quicksettings",
|
||||
connections: [
|
||||
[
|
||||
options.bar.position,
|
||||
(self) => {
|
||||
self.anchor = ["right", options.bar.position.value];
|
||||
if (options.bar.position.value === "top")
|
||||
self.transition = "slide_down";
|
||||
|
||||
if (options.bar.position.value === "bottom")
|
||||
self.transition = "slide_up";
|
||||
},
|
||||
],
|
||||
],
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Header(),
|
||||
Widget.Box({
|
||||
class_name: "sliders-box vertical",
|
||||
vertical: true,
|
||||
children: [
|
||||
Row([Volume()], [SinkSelector(), AppMixer()]),
|
||||
Microhone(),
|
||||
Brightness(),
|
||||
],
|
||||
}),
|
||||
Row(
|
||||
[Homogeneous([NetworkToggle(), BluetoothToggle()]), DND()],
|
||||
[WifiSelection(), BluetoothDevices()],
|
||||
),
|
||||
Row(
|
||||
[Homogeneous([ProfileToggle(), ThemeToggle()]), MicMute()],
|
||||
[ProfileSelector(), ThemeSelector()],
|
||||
),
|
||||
Media(),
|
||||
],
|
||||
}),
|
||||
});
|
||||
149
home/desktops/hyprland/ags/js/quicksettings/ToggleButton.js
Normal file
149
home/desktops/hyprland/ags/js/quicksettings/ToggleButton.js
Normal file
@@ -0,0 +1,149 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import App from "resource:///com/github/Aylur/ags/app.js";
|
||||
import Variable from "resource:///com/github/Aylur/ags/variable.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import icons from "../icons.js";
|
||||
|
||||
/** name of the currently opened menu */
|
||||
export const opened = Variable("");
|
||||
App.connect("window-toggled", (_, name, visible) => {
|
||||
if (name === "quicksettings" && !visible)
|
||||
Utils.timeout(500, () => (opened.value = ""));
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {string} name - menu name
|
||||
* @param {(() => void) | false=} activate
|
||||
*/
|
||||
export const Arrow = (name, activate) => {
|
||||
let deg = 0;
|
||||
let iconOpened = false;
|
||||
return Widget.Button({
|
||||
child: Widget.Icon({
|
||||
icon: icons.ui.arrow.right,
|
||||
connections: [
|
||||
[
|
||||
opened,
|
||||
(icon) => {
|
||||
if (
|
||||
(opened.value === name && !iconOpened) ||
|
||||
(opened.value !== name && iconOpened)
|
||||
) {
|
||||
const step = opened.value === name ? 10 : -10;
|
||||
iconOpened = !iconOpened;
|
||||
for (let i = 0; i < 9; ++i) {
|
||||
Utils.timeout(15 * i, () => {
|
||||
deg += step;
|
||||
icon.setCss(`-gtk-icon-transform: rotate(${deg}deg);`);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
on_clicked: () => {
|
||||
opened.value = opened.value === name ? "" : name;
|
||||
if (typeof activate === "function") activate();
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {string} o.name - menu name
|
||||
* @param {import('gi://Gtk').Gtk.Widget} o.icon
|
||||
* @param {import('gi://Gtk').Gtk.Widget} o.label
|
||||
* @param {() => void} o.activate
|
||||
* @param {() => void} o.deactivate
|
||||
* @param {boolean=} o.activateOnArrow
|
||||
* @param {[import('gi://GObject').GObject.Object, () => boolean]} o.connection
|
||||
*/
|
||||
export const ArrowToggleButton = ({
|
||||
name,
|
||||
icon,
|
||||
label,
|
||||
activate,
|
||||
deactivate,
|
||||
activateOnArrow = true,
|
||||
connection: [service, condition],
|
||||
}) =>
|
||||
Widget.Box({
|
||||
class_name: "toggle-button",
|
||||
connections: [
|
||||
[
|
||||
service,
|
||||
(box) => {
|
||||
box.toggleClassName("active", condition());
|
||||
},
|
||||
],
|
||||
],
|
||||
children: [
|
||||
Widget.Button({
|
||||
child: Widget.Box({
|
||||
hexpand: true,
|
||||
class_name: "label-box horizontal",
|
||||
children: [icon, label],
|
||||
}),
|
||||
on_clicked: () => {
|
||||
if (condition()) {
|
||||
deactivate();
|
||||
if (opened.value === name) opened.value = "";
|
||||
} else {
|
||||
activate();
|
||||
}
|
||||
},
|
||||
}),
|
||||
Arrow(name, activateOnArrow && activate),
|
||||
],
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {string} o.name - menu name
|
||||
* @param {import('gi://Gtk').Gtk.Widget} o.icon
|
||||
* @param {import('gi://Gtk').Gtk.Widget} o.title
|
||||
* @param {import('gi://Gtk').Gtk.Widget[]} o.content
|
||||
*/
|
||||
export const Menu = ({ name, icon, title, content }) =>
|
||||
Widget.Revealer({
|
||||
transition: "slide_down",
|
||||
binds: [["reveal-child", opened, "value", (v) => v === name]],
|
||||
child: Widget.Box({
|
||||
class_names: ["menu", name],
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: "title horizontal",
|
||||
children: [icon, title],
|
||||
}),
|
||||
Widget.Separator(),
|
||||
...content,
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
/**
|
||||
* @param {Object} o
|
||||
* @param {import('gi://Gtk').Gtk.Widget} o.icon
|
||||
* @param {() => void} o.toggle
|
||||
* @param {[import('gi://GObject').GObject.Object, () => boolean]} o.connection
|
||||
*/
|
||||
export const SimpleToggleButton = ({
|
||||
icon,
|
||||
toggle,
|
||||
connection: [service, condition],
|
||||
}) =>
|
||||
Widget.Button({
|
||||
class_name: "simple-toggle",
|
||||
connections: [
|
||||
[
|
||||
service,
|
||||
(box) => {
|
||||
box.toggleClassName("active", condition());
|
||||
},
|
||||
],
|
||||
],
|
||||
child: icon,
|
||||
on_clicked: toggle,
|
||||
});
|
||||
@@ -0,0 +1,61 @@
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import icons from "../../icons.js";
|
||||
import Asusctl from "../../services/asusctl.js";
|
||||
import { ArrowToggleButton, Menu } from "../ToggleButton.js";
|
||||
|
||||
export const ProfileToggle = () =>
|
||||
ArrowToggleButton({
|
||||
name: "asusctl-profile",
|
||||
icon: Widget.Icon({
|
||||
binds: [["icon", Asusctl, "profile", (p) => icons.asusctl.profile[p]]],
|
||||
}),
|
||||
label: Widget.Label({
|
||||
binds: [["label", Asusctl, "profile"]],
|
||||
}),
|
||||
connection: [Asusctl, () => Asusctl.profile !== "Balanced"],
|
||||
activate: () => Asusctl.setProfile("Quiet"),
|
||||
deactivate: () => Asusctl.setProfile("Balanced"),
|
||||
activateOnArrow: false,
|
||||
});
|
||||
|
||||
export const ProfileSelector = () =>
|
||||
Menu({
|
||||
name: "asusctl-profile",
|
||||
icon: Widget.Icon({
|
||||
binds: [["icon", Asusctl, "profile", (p) => icons.asusctl.profile[p]]],
|
||||
}),
|
||||
title: Widget.Label("Profile Selector"),
|
||||
content: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: Asusctl.profiles.map((prof) =>
|
||||
Widget.Button({
|
||||
on_clicked: () => Asusctl.setProfile(prof),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(icons.asusctl.profile[prof]),
|
||||
Widget.Label(prof),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Widget.Separator(),
|
||||
Widget.Button({
|
||||
on_clicked: () => Utils.execAsync("rog-control-center"),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(icons.ui.settings),
|
||||
Widget.Label("Rog Control Center"),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
import Bluetooth from "resource:///com/github/Aylur/ags/service/bluetooth.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import icons from "../../icons.js";
|
||||
import { Menu, ArrowToggleButton } from "../ToggleButton.js";
|
||||
|
||||
export const BluetoothToggle = () =>
|
||||
ArrowToggleButton({
|
||||
name: "bluetooth",
|
||||
icon: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Bluetooth,
|
||||
(icon) => {
|
||||
icon.icon = Bluetooth.enabled
|
||||
? icons.bluetooth.enabled
|
||||
: icons.bluetooth.disabled;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
label: Widget.Label({
|
||||
truncate: "end",
|
||||
connections: [
|
||||
[
|
||||
Bluetooth,
|
||||
(label) => {
|
||||
if (!Bluetooth.enabled) return (label.label = "Disabled");
|
||||
|
||||
if (Bluetooth.connectedDevices.length === 0)
|
||||
return (label.label = "Not Connected");
|
||||
|
||||
if (Bluetooth.connectedDevices.length === 1)
|
||||
return (label.label = Bluetooth.connectedDevices[0].alias);
|
||||
|
||||
label.label = `${Bluetooth.connectedDevices.length} Connected`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
connection: [Bluetooth, () => Bluetooth.enabled],
|
||||
deactivate: () => (Bluetooth.enabled = false),
|
||||
activate: () => (Bluetooth.enabled = true),
|
||||
});
|
||||
|
||||
const DeviceItem = (device) =>
|
||||
Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(device.icon_name + "-symbolic"),
|
||||
Widget.Label(device.name),
|
||||
Widget.Label({
|
||||
label: `${device.battery_percentage}%`,
|
||||
binds: [["visible", device, "battery-percentage", (p) => p > 0]],
|
||||
}),
|
||||
Widget.Box({ hexpand: true }),
|
||||
Widget.Spinner({
|
||||
binds: [
|
||||
["active", device, "connecting"],
|
||||
["visible", device, "connecting"],
|
||||
],
|
||||
}),
|
||||
Widget.Switch({
|
||||
active: device.connected,
|
||||
binds: [["visible", device, "connecting", (c) => !c]],
|
||||
connections: [
|
||||
[
|
||||
"notify::active",
|
||||
({ active }) => {
|
||||
device.setConnection(active);
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const BluetoothDevices = () =>
|
||||
Menu({
|
||||
name: "bluetooth",
|
||||
icon: Widget.Icon(icons.bluetooth.disabled),
|
||||
title: Widget.Label("Bluetooth"),
|
||||
content: [
|
||||
Widget.Box({
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
binds: [
|
||||
[
|
||||
"children",
|
||||
Bluetooth,
|
||||
"devices",
|
||||
(ds) => ds.filter((d) => d.name).map(DeviceItem),
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import icons from "../../icons.js";
|
||||
import Brightness from "../../services/brightness.js";
|
||||
|
||||
const BrightnessSlider = () =>
|
||||
Widget.Slider({
|
||||
draw_value: false,
|
||||
hexpand: true,
|
||||
binds: [["value", Brightness, "screen"]],
|
||||
on_change: ({ value }) => (Brightness.screen = value),
|
||||
});
|
||||
|
||||
export default () =>
|
||||
Widget.Box({
|
||||
children: [
|
||||
Widget.Button({
|
||||
child: Widget.Icon(icons.brightness.indicator),
|
||||
binds: [
|
||||
[
|
||||
"tooltip-text",
|
||||
Brightness,
|
||||
"screen",
|
||||
(v) => `Screen Brightness: ${Math.floor(v * 100)}%`,
|
||||
],
|
||||
],
|
||||
}),
|
||||
BrightnessSlider(),
|
||||
],
|
||||
});
|
||||
23
home/desktops/hyprland/ags/js/quicksettings/widgets/DND.js
Normal file
23
home/desktops/hyprland/ags/js/quicksettings/widgets/DND.js
Normal file
@@ -0,0 +1,23 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Notifications from "resource:///com/github/Aylur/ags/service/notifications.js";
|
||||
import icons from "../../icons.js";
|
||||
import { SimpleToggleButton } from "../ToggleButton.js";
|
||||
|
||||
export default () =>
|
||||
SimpleToggleButton({
|
||||
icon: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Notifications,
|
||||
(icon) => {
|
||||
icon.icon = Notifications.dnd
|
||||
? icons.notifications.silent
|
||||
: icons.notifications.noisy;
|
||||
},
|
||||
"notify::dnd",
|
||||
],
|
||||
],
|
||||
}),
|
||||
toggle: () => (Notifications.dnd = !Notifications.dnd),
|
||||
connection: [Notifications, () => Notifications.dnd],
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Battery from "resource:///com/github/Aylur/ags/service/battery.js";
|
||||
import PowerMenu from "../../services/powermenu.js";
|
||||
import Lockscreen from "../../services/lockscreen.js";
|
||||
import Avatar from "../../misc/Avatar.js";
|
||||
import icons from "../../icons.js";
|
||||
import { openSettings } from "../../settings/theme.js";
|
||||
import { uptime } from "../../variables.js";
|
||||
|
||||
export default () =>
|
||||
Widget.Box({
|
||||
class_name: "header horizontal",
|
||||
children: [
|
||||
Avatar(),
|
||||
Widget.Box({
|
||||
hpack: "end",
|
||||
vpack: "center",
|
||||
hexpand: true,
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: "battery horizontal",
|
||||
children: [
|
||||
Widget.Icon({ binds: [["icon", Battery, "icon-name"]] }),
|
||||
Widget.Label({
|
||||
binds: [["label", Battery, "percent", (p) => `${p}%`]],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Widget.Label({
|
||||
class_name: "uptime",
|
||||
binds: [["label", uptime, "value", (v) => `up: ${v}`]],
|
||||
}),
|
||||
Widget.Button({
|
||||
on_clicked: openSettings,
|
||||
child: Widget.Icon(icons.ui.settings),
|
||||
}),
|
||||
Widget.Button({
|
||||
on_clicked: () => Lockscreen.lockscreen(),
|
||||
child: Widget.Icon(icons.lock),
|
||||
}),
|
||||
Widget.Button({
|
||||
on_clicked: () => PowerMenu.action("shutdown"),
|
||||
child: Widget.Icon(icons.powermenu.shutdown),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
106
home/desktops/hyprland/ags/js/quicksettings/widgets/Media.js
Normal file
106
home/desktops/hyprland/ags/js/quicksettings/widgets/Media.js
Normal file
@@ -0,0 +1,106 @@
|
||||
import Mpris from "resource:///com/github/Aylur/ags/service/mpris.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import * as mpris from "../../misc/mpris.js";
|
||||
import options from "../../options.js";
|
||||
|
||||
/** @param {import('types/service/mpris').MprisPlayer} player */
|
||||
const Footer = (player) =>
|
||||
Widget.CenterBox({
|
||||
class_name: "footer-box",
|
||||
children: [
|
||||
Widget.Box({
|
||||
class_name: "position",
|
||||
children: [
|
||||
mpris.PositionLabel(player),
|
||||
mpris.Slash(player),
|
||||
mpris.LengthLabel(player),
|
||||
],
|
||||
}),
|
||||
Widget.Box({
|
||||
class_name: "controls",
|
||||
children: [
|
||||
mpris.ShuffleButton(player),
|
||||
mpris.PreviousButton(player),
|
||||
mpris.PlayPauseButton(player),
|
||||
mpris.NextButton(player),
|
||||
mpris.LoopButton(player),
|
||||
],
|
||||
}),
|
||||
mpris.PlayerIcon(player, {
|
||||
symbolic: false,
|
||||
hexpand: true,
|
||||
hpack: "end",
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {import('types/service/mpris').MprisPlayer} player */
|
||||
const TextBox = (player) =>
|
||||
Widget.Box({
|
||||
children: [
|
||||
mpris.CoverArt(player, {
|
||||
hpack: "end",
|
||||
hexpand: false,
|
||||
}),
|
||||
Widget.Box({
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
class_name: "labels",
|
||||
children: [
|
||||
mpris.TitleLabel(player, {
|
||||
xalign: 0,
|
||||
justification: "left",
|
||||
wrap: true,
|
||||
}),
|
||||
mpris.ArtistLabel(player, {
|
||||
xalign: 0,
|
||||
justification: "left",
|
||||
wrap: true,
|
||||
}),
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {import('types/service/mpris').MprisPlayer} player */
|
||||
const PlayerBox = (player) =>
|
||||
Widget.Box({
|
||||
class_name: `player ${player.name}`,
|
||||
child: mpris.BlurredCoverArt(player, {
|
||||
hexpand: true,
|
||||
child: Widget.Box({
|
||||
hexpand: true,
|
||||
vertical: true,
|
||||
children: [
|
||||
TextBox(player),
|
||||
mpris.PositionSlider(player),
|
||||
Footer(player),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
});
|
||||
|
||||
export default () =>
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
class_name: "media vertical",
|
||||
connections: [
|
||||
[
|
||||
"draw",
|
||||
(self) => {
|
||||
self.visible = Mpris.players.length > 0;
|
||||
},
|
||||
],
|
||||
],
|
||||
binds: [
|
||||
[
|
||||
"children",
|
||||
Mpris,
|
||||
"players",
|
||||
(ps) =>
|
||||
ps
|
||||
.filter((p) => !options.mpris.black_list.value.includes(p.identity))
|
||||
.map(PlayerBox),
|
||||
],
|
||||
],
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
import Audio from "resource:///com/github/Aylur/ags/service/audio.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import icons from "../../icons.js";
|
||||
import { SimpleToggleButton } from "../ToggleButton.js";
|
||||
|
||||
export default () =>
|
||||
SimpleToggleButton({
|
||||
icon: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Audio,
|
||||
(icon) => {
|
||||
icon.icon = Audio.microphone?.is_muted
|
||||
? icons.audio.mic.muted
|
||||
: icons.audio.mic.high;
|
||||
},
|
||||
"microphone-changed",
|
||||
],
|
||||
],
|
||||
}),
|
||||
toggle: () => (Audio.microphone.is_muted = !Audio.microphone.is_muted),
|
||||
connection: [Audio, () => Audio.microphone?.is_muted],
|
||||
});
|
||||
@@ -0,0 +1,91 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import Network from "resource:///com/github/Aylur/ags/service/network.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import icons from "../../icons.js";
|
||||
import { Menu, ArrowToggleButton } from "../ToggleButton.js";
|
||||
import Applications from "resource:///com/github/Aylur/ags/service/applications.js";
|
||||
|
||||
export const NetworkToggle = () =>
|
||||
ArrowToggleButton({
|
||||
name: "network",
|
||||
icon: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Network,
|
||||
(icon) => {
|
||||
icon.icon = Network.wifi.icon_name || "";
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
label: Widget.Label({
|
||||
truncate: "end",
|
||||
connections: [
|
||||
[
|
||||
Network,
|
||||
(label) => {
|
||||
label.label = Network.wifi.ssid || "Not Connected";
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
connection: [Network, () => Network.wifi.enabled],
|
||||
deactivate: () => (Network.wifi.enabled = false),
|
||||
activate: () => {
|
||||
Network.wifi.enabled = true;
|
||||
Network.wifi.scan();
|
||||
},
|
||||
});
|
||||
|
||||
export const WifiSelection = () =>
|
||||
Menu({
|
||||
name: "network",
|
||||
icon: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Network,
|
||||
(icon) => {
|
||||
icon.icon = Network.wifi.icon_name;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
title: Widget.Label("Wifi Selection"),
|
||||
content: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
connections: [
|
||||
[
|
||||
Network,
|
||||
(box) =>
|
||||
(box.children = Network.wifi?.access_points.map((ap) =>
|
||||
Widget.Button({
|
||||
on_clicked: () =>
|
||||
Utils.execAsync(`nmcli device wifi connect ${ap.bssid}`),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(ap.iconName),
|
||||
Widget.Label(ap.ssid || ""),
|
||||
ap.active &&
|
||||
Widget.Icon({
|
||||
icon: icons.ui.tick,
|
||||
hexpand: true,
|
||||
hpack: "end",
|
||||
}),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
)),
|
||||
],
|
||||
],
|
||||
}),
|
||||
Widget.Separator(),
|
||||
Widget.Button({
|
||||
on_clicked: () =>
|
||||
Applications.query("gnome-control-center")?.[0].launch(),
|
||||
child: Widget.Box({
|
||||
children: [Widget.Icon(icons.ui.settings), Widget.Label("Network")],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
57
home/desktops/hyprland/ags/js/quicksettings/widgets/Theme.js
Normal file
57
home/desktops/hyprland/ags/js/quicksettings/widgets/Theme.js
Normal file
@@ -0,0 +1,57 @@
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import { ArrowToggleButton, Menu, opened } from "../ToggleButton.js";
|
||||
import themes from "../../themes.js";
|
||||
import icons from "../../icons.js";
|
||||
import options from "../../options.js";
|
||||
import { setTheme, openSettings } from "../../settings/theme.js";
|
||||
|
||||
export const ThemeToggle = () =>
|
||||
ArrowToggleButton({
|
||||
name: "theme",
|
||||
icon: Widget.Label({ binds: [["label", options.theme.icon]] }),
|
||||
label: Widget.Label({ binds: [["label", options.theme.name]] }),
|
||||
connection: [opened, () => opened.value === "theme"],
|
||||
activate: () => opened.setValue("theme"),
|
||||
activateOnArrow: false,
|
||||
deactivate: () => {},
|
||||
});
|
||||
|
||||
export const ThemeSelector = () =>
|
||||
Menu({
|
||||
name: "theme",
|
||||
icon: Widget.Label({
|
||||
binds: [["label", options.theme.icon]],
|
||||
}),
|
||||
title: Widget.Label("Theme Selector"),
|
||||
content: [
|
||||
...themes.map(({ name, icon }) =>
|
||||
Widget.Button({
|
||||
on_clicked: () => setTheme(name),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Label(icon),
|
||||
Widget.Label(name),
|
||||
Widget.Icon({
|
||||
icon: icons.ui.tick,
|
||||
hexpand: true,
|
||||
hpack: "end",
|
||||
binds: [
|
||||
["visible", options.theme.name, "value", (v) => v === name],
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
),
|
||||
Widget.Separator(),
|
||||
Widget.Button({
|
||||
on_clicked: openSettings,
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon(icons.ui.settings),
|
||||
Widget.Label("Theme Settings"),
|
||||
],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
194
home/desktops/hyprland/ags/js/quicksettings/widgets/Volume.js
Normal file
194
home/desktops/hyprland/ags/js/quicksettings/widgets/Volume.js
Normal file
@@ -0,0 +1,194 @@
|
||||
import Audio from "resource:///com/github/Aylur/ags/service/audio.js";
|
||||
import Widget from "resource:///com/github/Aylur/ags/widget.js";
|
||||
import * as Utils from "resource:///com/github/Aylur/ags/utils.js";
|
||||
import icons from "../../icons.js";
|
||||
import FontIcon from "../../misc/FontIcon.js";
|
||||
import { getAudioTypeIcon } from "../../utils.js";
|
||||
import { Arrow } from "../ToggleButton.js";
|
||||
import { Menu } from "../ToggleButton.js";
|
||||
|
||||
/** @param {'speaker' | 'microphone'=} type */
|
||||
const VolumeIndicator = (type = "speaker") =>
|
||||
Widget.Button({
|
||||
on_clicked: () => (Audio[type].is_muted = !Audio[type].is_muted),
|
||||
child: Widget.Icon({
|
||||
connections: [
|
||||
[
|
||||
Audio,
|
||||
(icon) => {
|
||||
if (!Audio[type]) return;
|
||||
|
||||
icon.icon =
|
||||
type === "speaker"
|
||||
? getAudioTypeIcon(Audio[type].icon_name || "")
|
||||
: icons.audio.mic.high;
|
||||
|
||||
icon.tooltip_text = `Volume ${Math.floor(
|
||||
Audio[type].volume * 100,
|
||||
)}%`;
|
||||
},
|
||||
`${type}-changed`,
|
||||
],
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
/** @param {'speaker' | 'microphone'=} type */
|
||||
const VolumeSlider = (type = "speaker") =>
|
||||
Widget.Slider({
|
||||
hexpand: true,
|
||||
draw_value: false,
|
||||
on_change: ({ value }) => (Audio[type].volume = value),
|
||||
connections: [
|
||||
[
|
||||
Audio,
|
||||
(slider) => {
|
||||
slider.value = Audio[type]?.volume;
|
||||
},
|
||||
`${type}-changed`,
|
||||
],
|
||||
],
|
||||
});
|
||||
|
||||
export const Volume = () =>
|
||||
Widget.Box({
|
||||
children: [
|
||||
VolumeIndicator("speaker"),
|
||||
VolumeSlider("speaker"),
|
||||
Widget.Box({
|
||||
vpack: "center",
|
||||
child: Arrow("sink-selector"),
|
||||
}),
|
||||
Widget.Box({
|
||||
vpack: "center",
|
||||
child: Arrow("app-mixer"),
|
||||
connections: [
|
||||
[
|
||||
Audio,
|
||||
(box) => {
|
||||
box.visible = Audio.apps.length > 0;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const Microhone = () =>
|
||||
Widget.Box({
|
||||
class_name: "slider horizontal",
|
||||
binds: [["visible", Audio, "recorders", (r) => r.length > 0]],
|
||||
children: [VolumeIndicator("microphone"), VolumeSlider("microphone")],
|
||||
});
|
||||
|
||||
/** @param {import('types/service/audio').Stream} stream */
|
||||
const MixerItem = (stream) =>
|
||||
Widget.Box({
|
||||
hexpand: true,
|
||||
class_name: "mixer-item horizontal",
|
||||
children: [
|
||||
Widget.Icon({
|
||||
binds: [["tooltipText", stream, "name"]],
|
||||
connections: [
|
||||
[
|
||||
stream,
|
||||
(icon) => {
|
||||
icon.icon = Utils.lookUpIcon(stream.name || "")
|
||||
? stream.name || ""
|
||||
: icons.mpris.fallback;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
truncate: "end",
|
||||
binds: [["label", stream, "description"]],
|
||||
}),
|
||||
Widget.Slider({
|
||||
hexpand: true,
|
||||
draw_value: false,
|
||||
binds: [["value", stream, "volume"]],
|
||||
on_change: ({ value }) => (stream.volume = value),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Widget.Label({
|
||||
xalign: 1,
|
||||
connections: [
|
||||
[
|
||||
stream,
|
||||
(l) => {
|
||||
l.label = `${Math.floor(stream.volume * 100)}%`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
/** @param {import('types/service/audio').Stream} stream */
|
||||
const SinkItem = (stream) =>
|
||||
Widget.Button({
|
||||
hexpand: true,
|
||||
on_clicked: () => (Audio.speaker = stream),
|
||||
child: Widget.Box({
|
||||
children: [
|
||||
Widget.Icon({
|
||||
icon: getAudioTypeIcon(stream.icon_name || ""),
|
||||
tooltip_text: stream.icon_name,
|
||||
}),
|
||||
Widget.Label(
|
||||
(stream.description || "").split(" ").slice(0, 4).join(" "),
|
||||
),
|
||||
Widget.Icon({
|
||||
icon: icons.ui.tick,
|
||||
hexpand: true,
|
||||
hpack: "end",
|
||||
binds: [["visible", Audio, "speaker", (s) => s === stream]],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
|
||||
const SettingsButton = () =>
|
||||
Widget.Button({
|
||||
on_clicked: () => Utils.execAsync("pavucontrol"),
|
||||
hexpand: true,
|
||||
child: Widget.Box({
|
||||
children: [Widget.Icon(icons.ui.settings), Widget.Label("Settings")],
|
||||
}),
|
||||
});
|
||||
|
||||
export const AppMixer = () =>
|
||||
Menu({
|
||||
name: "app-mixer",
|
||||
icon: FontIcon(icons.audio.mixer),
|
||||
title: Widget.Label("App Mixer"),
|
||||
content: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
binds: [["children", Audio, "apps", (a) => a.map(MixerItem)]],
|
||||
}),
|
||||
Widget.Separator(),
|
||||
SettingsButton(),
|
||||
],
|
||||
});
|
||||
|
||||
export const SinkSelector = () =>
|
||||
Menu({
|
||||
name: "sink-selector",
|
||||
icon: Widget.Icon(icons.audio.type.headset),
|
||||
title: Widget.Label("Sink Selector"),
|
||||
content: [
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
binds: [["children", Audio, "speakers", (s) => s.map(SinkItem)]],
|
||||
}),
|
||||
Widget.Separator(),
|
||||
SettingsButton(),
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user