mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-01-07 08:12:49 +00:00
refactor: make the whole thing more generic
This commit is contained in:
@@ -0,0 +1,158 @@
|
||||
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().hook(Audio[type], (icon) => {
|
||||
icon.icon =
|
||||
type === "speaker"
|
||||
? getAudioTypeIcon(Audio[type].icon_name || "")
|
||||
: icons.audio.mic.high;
|
||||
|
||||
icon.tooltip_text = `Volume ${Math.floor(Audio[type].volume * 100)}%`;
|
||||
}),
|
||||
});
|
||||
|
||||
/** @param {'speaker' | 'microphone'=} type */
|
||||
const VolumeSlider = (type = "speaker") =>
|
||||
Widget.Slider({
|
||||
hexpand: true,
|
||||
draw_value: false,
|
||||
on_change: ({ value }) => (Audio[type].volume = value),
|
||||
setup: (self) =>
|
||||
self.hook(Audio[type], () => {
|
||||
self.value = Audio[type].volume || 0;
|
||||
}),
|
||||
});
|
||||
|
||||
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"),
|
||||
visible: Audio.bind("apps").transform((a) => a.length > 0),
|
||||
}),
|
||||
],
|
||||
});
|
||||
|
||||
export const Microhone = () =>
|
||||
Widget.Box({
|
||||
class_name: "slider horizontal",
|
||||
visible: Audio.bind("recorders").transform((a) => a.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({
|
||||
tooltip_text: stream.bind("name").transform((n) => n || ""),
|
||||
icon: stream.bind("name").transform((n) => {
|
||||
return Utils.lookUpIcon(n || "") ? n || "" : icons.mpris.fallback;
|
||||
}),
|
||||
}),
|
||||
Widget.Box({
|
||||
vertical: true,
|
||||
children: [
|
||||
Widget.Label({
|
||||
xalign: 0,
|
||||
truncate: "end",
|
||||
label: stream.bind("description").transform((d) => d || ""),
|
||||
}),
|
||||
Widget.Slider({
|
||||
hexpand: true,
|
||||
draw_value: false,
|
||||
value: stream.bind("volume"),
|
||||
on_change: ({ value }) => (stream.volume = value),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
Widget.Label({
|
||||
xalign: 1,
|
||||
label: stream.bind("volume").transform((v) => `${Math.floor(v * 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",
|
||||
visible: Audio.speaker
|
||||
.bind("stream")
|
||||
.transform((s) => s === stream.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,
|
||||
children: Audio.bind("apps").transform((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,
|
||||
children: Audio.bind("speakers").transform((a) => a.map(SinkItem)),
|
||||
}),
|
||||
Widget.Separator(),
|
||||
SettingsButton(),
|
||||
],
|
||||
});
|
||||
Reference in New Issue
Block a user