mirror of
https://github.com/zoriya/flake.git
synced 2026-06-01 18:26:18 +00:00
Add osd
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Bar } from "./layouts/bar.js";
|
||||
import { Notifications } from "./layouts/notifications.js";
|
||||
// import { OSD } from "./layouts/osd.js";
|
||||
import { Quicksettings } from "./layouts/quicksettings.js";
|
||||
import { Notifications } from "./layouts/notifications.js";
|
||||
import { OSD } from "./layouts/osd.js";
|
||||
import { Quicksettings } from "./layouts/quicksettings.js";
|
||||
|
||||
import Gtk from "gi://Gtk?version=3.0";
|
||||
import Gdk from "gi://Gdk";
|
||||
@@ -17,13 +17,14 @@ export function forMonitors(widget) {
|
||||
App.config({
|
||||
closeWindowDelay: {
|
||||
quicksettings: 300,
|
||||
notifications: 300,
|
||||
notifications: 200,
|
||||
osd: 300,
|
||||
},
|
||||
style: `${App.configDir}/style.css`,
|
||||
windows: [
|
||||
...forMonitors(Bar),
|
||||
Quicksettings(),
|
||||
Notifications(),
|
||||
// OSD(),
|
||||
Quicksettings(),
|
||||
Notifications(),
|
||||
OSD(),
|
||||
],
|
||||
});
|
||||
|
||||
@@ -1,86 +1,85 @@
|
||||
import { lookUpIcon } from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import { Window, Revealer, Stack, Box, Icon } from 'resource:///com/github/Aylur/ags/widget.js'
|
||||
import { FontIcon, Progress } from "../misc.js";
|
||||
import Indicator from "../services/osd.js";
|
||||
import { getIcon } from "../modules/audio.js";
|
||||
import brightness from "../services/brightness.js";
|
||||
|
||||
export const OSD = () =>
|
||||
Window({
|
||||
name: "osd",
|
||||
popup: true,
|
||||
// Follow active monitor
|
||||
monitor: undefined,
|
||||
visible: false,
|
||||
layer: "overlay",
|
||||
anchor: ["bottom"],
|
||||
child: Revealer({
|
||||
transition: "crossfade",
|
||||
connections: [
|
||||
[
|
||||
Indicator,
|
||||
(revealer, value) => {
|
||||
revealer.revealChild = value > -1;
|
||||
},
|
||||
],
|
||||
],
|
||||
child: Box({
|
||||
className: "osd bgcont osd",
|
||||
vpack: "center",
|
||||
hpack: "center",
|
||||
children: [
|
||||
Stack({
|
||||
vpack: "center",
|
||||
hpack: "center",
|
||||
css: "padding: 20px;",
|
||||
hexpand: false,
|
||||
items: [
|
||||
[
|
||||
"true",
|
||||
Icon({
|
||||
hpack: "center",
|
||||
vpack: "center",
|
||||
size: 40,
|
||||
connections: [[Indicator, (icon, _v, name) => (icon.icon = name || "")]],
|
||||
}),
|
||||
],
|
||||
[
|
||||
"false",
|
||||
FontIcon({
|
||||
hpack: "center",
|
||||
vpack: "center",
|
||||
hexpand: true,
|
||||
css: `font-size: 40px;`,
|
||||
connections: [[Indicator, ({ label }, _v, name) => (label.label = name || "")]],
|
||||
}),
|
||||
],
|
||||
],
|
||||
connections: [
|
||||
[
|
||||
Indicator,
|
||||
(stack, _v, name) => {
|
||||
stack.shown = `${!!lookUpIcon(name)}`;
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
Progress({
|
||||
width: 200,
|
||||
height: 10,
|
||||
hpack: "center",
|
||||
vpack: "center",
|
||||
css: "margin-right: 20px;",
|
||||
hexpand: false,
|
||||
vexpand: false,
|
||||
connections: [
|
||||
[
|
||||
Indicator,
|
||||
(progress, value, icon) => {
|
||||
if (!icon) return;
|
||||
progress.setValue(value, icon.startsWith("audio") ? 1.5 : 1);
|
||||
},
|
||||
],
|
||||
],
|
||||
}),
|
||||
],
|
||||
}),
|
||||
const audio = await Service.import("audio");
|
||||
|
||||
const DELAY = 1000;
|
||||
|
||||
function OnScreenProgress() {
|
||||
const indicator = Widget.Icon({
|
||||
vpack: "start",
|
||||
hpack: "center",
|
||||
size: 30,
|
||||
css: "padding-right: 12px;",
|
||||
});
|
||||
const progress = Widget.Slider({
|
||||
drawValue: false,
|
||||
hexpand: true,
|
||||
});
|
||||
const revealer = Widget.Revealer({
|
||||
transition: "crossfade",
|
||||
css: "opacity: 0",
|
||||
revealChild: true,
|
||||
vpack: "center",
|
||||
hpack: "center",
|
||||
child: Widget.Box({
|
||||
vpack: "center",
|
||||
hpack: "center",
|
||||
className: "osd bgcount",
|
||||
css: "padding: 20px;",
|
||||
children: [indicator, progress],
|
||||
}),
|
||||
});
|
||||
// Prevent OSD to be shown when starting ags.
|
||||
Utils.timeout(DELAY * 2, () => {
|
||||
revealer.css = "opacity: 1";
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
/**
|
||||
* @param {number} value
|
||||
* @param {string} icon
|
||||
*/
|
||||
function show(value, icon) {
|
||||
revealer.reveal_child = true;
|
||||
indicator.icon = icon;
|
||||
progress.value = value;
|
||||
count++;
|
||||
Utils.timeout(DELAY, () => {
|
||||
count--;
|
||||
if (count === 0) revealer.reveal_child = false;
|
||||
});
|
||||
}
|
||||
return revealer
|
||||
.hook(
|
||||
brightness,
|
||||
() => show(brightness.screen, "display-brightness-symbolic"),
|
||||
"notify::screen",
|
||||
)
|
||||
.hook(
|
||||
audio.speaker,
|
||||
() => show(audio.speaker.volume, getIcon(audio.speaker.volume * 100)),
|
||||
"notify::volume",
|
||||
)
|
||||
.hook(
|
||||
audio.speaker,
|
||||
() =>
|
||||
show(
|
||||
audio.speaker.is_muted ? 0 : audio.speaker.volume,
|
||||
audio.speaker.is_muted
|
||||
? "audio-volume-muted-symbolic"
|
||||
: getIcon(audio.speaker.volume * 100),
|
||||
),
|
||||
"notify::is-muted",
|
||||
);
|
||||
}
|
||||
|
||||
export const OSD = () =>
|
||||
Widget.Window({
|
||||
name: "osd",
|
||||
className: "indicator",
|
||||
layer: "overlay",
|
||||
clickThrough: true,
|
||||
anchor: ["bottom"],
|
||||
child: OnScreenProgress(),
|
||||
});
|
||||
|
||||
@@ -126,6 +126,7 @@ export const Quicksettings = () =>
|
||||
exclusivity: "exclusive",
|
||||
transition: "slide_down",
|
||||
layout: "top-right",
|
||||
duration: 300,
|
||||
child: Widget.Box({
|
||||
vertical: true,
|
||||
className: "bgcont qs-container",
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import { icon } from "../misc/utils.js";
|
||||
import { Arrow, Menu, SettingsButton, SimpleToggleButton } from "../misc/menu.js";
|
||||
import {
|
||||
Arrow,
|
||||
Menu,
|
||||
SettingsButton,
|
||||
SimpleToggleButton,
|
||||
} from "../misc/menu.js";
|
||||
|
||||
const audio = await Service.import("audio");
|
||||
|
||||
@@ -11,6 +16,12 @@ const volumeIcons = /** @type {const} */ ([
|
||||
[0, "muted"],
|
||||
]);
|
||||
|
||||
/** @param {number} volume */
|
||||
export const getIcon = (volume) => {
|
||||
const icon = volumeIcons.find(([threshold]) => threshold <= volume)?.[1];
|
||||
return `audio-volume-${icon}-symbolic`;
|
||||
};
|
||||
|
||||
/** @param {{type?: "speaker" | "microphone"} & import("types/widgets/icon").IconProps} props */
|
||||
export const VolumeIndicator = ({ type = "speaker", ...props }) =>
|
||||
Widget.Icon(props).hook(audio, (self) => {
|
||||
@@ -20,8 +31,7 @@ export const VolumeIndicator = ({ type = "speaker", ...props }) =>
|
||||
return;
|
||||
}
|
||||
const vol = audio[type].volume * 100;
|
||||
const icon = volumeIcons.find(([threshold]) => threshold <= vol)?.[1];
|
||||
self.icon = `audio-volume-${icon}-symbolic`;
|
||||
self.icon = getIcon(vol);
|
||||
self.tooltip_text = `Volume: ${Math.floor(vol)}%`;
|
||||
});
|
||||
|
||||
@@ -38,7 +48,7 @@ export const MicrophoneIndicator = (props) =>
|
||||
const VolumeSlider = ({ type = "speaker", ...props }) =>
|
||||
Widget.Slider({
|
||||
hexpand: true,
|
||||
draw_value: false,
|
||||
drawValue: false,
|
||||
onChange: ({ value, dragging }) => {
|
||||
if (dragging) {
|
||||
audio[type].volume = value;
|
||||
@@ -101,9 +111,13 @@ export const MuteToggle = ({ ...props } = {}) =>
|
||||
.bind("is_muted")
|
||||
.as((x) => (x ? "Unmute" : "Mute")),
|
||||
}),
|
||||
activate: () => (audio.microphone.is_muted = true),
|
||||
deactivate: () => (audio.microphone.is_muted = false),
|
||||
connection: [audio.microphone, () => audio.microphone.is_muted],
|
||||
activate: () => {
|
||||
audio.microphone.is_muted = true;
|
||||
},
|
||||
deactivate: () => {
|
||||
audio.microphone.is_muted = false;
|
||||
},
|
||||
connection: [audio.microphone, () => audio.microphone.is_muted || false],
|
||||
...props,
|
||||
});
|
||||
|
||||
|
||||
@@ -245,7 +245,7 @@ export const Placeholder = (props) =>
|
||||
/** @param {import("types/widgets/button").ButtonProps} props */
|
||||
export const ClearButton = (props) =>
|
||||
Widget.Button({
|
||||
className: "button surface",
|
||||
className: "surface r20 p10",
|
||||
onClicked: () => notifications.clear(),
|
||||
sensitive: notifications.bind("notifications").as((x) => x.length > 0),
|
||||
child: Widget.Box({
|
||||
|
||||
@@ -6,7 +6,7 @@ const systemtray = await Service.import("systemtray");
|
||||
export const Toggle = (props) =>
|
||||
ArrowToggleButton({
|
||||
name: "systray",
|
||||
icon: Widget.Icon({ className: "qs-icon" }),
|
||||
icon: Widget.Icon({ icon: "open-menu-symbolic", className: "qs-icon" }),
|
||||
label: Widget.Label("Systray"),
|
||||
activate: () => {},
|
||||
deactivate: () => {},
|
||||
@@ -18,7 +18,7 @@ export const Toggle = (props) =>
|
||||
export const Selection = (props) =>
|
||||
Menu({
|
||||
name: "systray",
|
||||
icon: Widget.Icon(),
|
||||
icon: Widget.Icon("open-menu-symbolic"),
|
||||
title: "Systray",
|
||||
content: [
|
||||
Widget.Box({
|
||||
|
||||
@@ -16,7 +16,6 @@ class Brightness extends Service {
|
||||
|
||||
set screen(percent) {
|
||||
if (percent < 0) percent = 0;
|
||||
|
||||
if (percent > 1) percent = 1;
|
||||
|
||||
Utils.execAsync(`brightnessctl s ${percent * 100}% -q`)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
import App from 'resource:///com/github/Aylur/ags/app.js';
|
||||
import Service from 'resource:///com/github/Aylur/ags/service.js';
|
||||
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
|
||||
import Brightness from '../services/brightness.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
|
||||
class Indicator extends Service {
|
||||
static {
|
||||
Service.register(this, {
|
||||
'popup': ['double', 'string'],
|
||||
});
|
||||
}
|
||||
|
||||
#openned = false
|
||||
#delay = 1500;
|
||||
#count = 0;
|
||||
|
||||
/**
|
||||
* @param {number} value - 0 < v < 1
|
||||
* @param {string} icon
|
||||
*/
|
||||
popup(value, icon) {
|
||||
if (!this.#openned) {
|
||||
this.#openned = true;
|
||||
App.openWindow("osd");
|
||||
}
|
||||
this.emit('popup', value, icon);
|
||||
this.#count++;
|
||||
Utils.timeout(this.#delay, () => {
|
||||
this.#count--;
|
||||
|
||||
if (this.#count === 0) {
|
||||
this.emit('popup', -1, icon);
|
||||
App.closeWindow("osd");
|
||||
this.#openned = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
speaker() {
|
||||
const icon = (value) => {
|
||||
const icons = [];
|
||||
icons[0] = "audio-volume-muted-symbolic";
|
||||
icons[1] = "audio-volume-low-symbolic";
|
||||
icons[34] = "audio-volume-medium-symbolic";
|
||||
icons[67] = "audio-volume-high-symbolic";
|
||||
icons[101] = "audio-volume-overamplified-symbolic";
|
||||
if (Audio.speaker.isMuted) return icons[0];
|
||||
for (const i of [101, 67, 34, 1, 0]) {
|
||||
if (i <= value * 100) return icons[i];
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
this.popup(
|
||||
Audio.speaker.volume,
|
||||
icon(Audio.speaker.volume),
|
||||
);
|
||||
}
|
||||
|
||||
display() {
|
||||
// brightness is async, so lets wait a bit
|
||||
Utils.timeout(10, () => this.popup(
|
||||
Brightness.screen,
|
||||
"display-brightness-symbolic"));
|
||||
}
|
||||
|
||||
kbd() {
|
||||
// brightness is async, so lets wait a bit
|
||||
Utils.timeout(10, () => this.popup(
|
||||
(Brightness.kbd * 33 + 1) / 100,
|
||||
"keyboard-brightness-symbolic"));
|
||||
}
|
||||
|
||||
connect(event = 'popup', callback) {
|
||||
return super.connect(event, callback);
|
||||
}
|
||||
}
|
||||
|
||||
const indicator = new Indicator();
|
||||
globalThis.indicator = indicator;
|
||||
export default indicator;
|
||||
@@ -61,20 +61,6 @@ separator {
|
||||
min-width: 1px;
|
||||
}
|
||||
|
||||
/* Progress bar */
|
||||
.progress {
|
||||
border-radius: 10px;
|
||||
}
|
||||
.max-indicator {
|
||||
min-width: 1px;
|
||||
min-height: 1px;
|
||||
}
|
||||
|
||||
.button {
|
||||
border-radius: 20px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
/* Slider */
|
||||
slider {
|
||||
box-shadow: none;
|
||||
@@ -93,6 +79,7 @@ trough {
|
||||
highlight, fill {
|
||||
background-color: #94e2d5;
|
||||
border-radius: 100px;
|
||||
transition: 200ms;
|
||||
}
|
||||
mark {
|
||||
background-color: #F38BA8;
|
||||
@@ -133,10 +120,10 @@ switch image {
|
||||
|
||||
/* On Screen Display */
|
||||
.osd {
|
||||
border-radius: 50px;
|
||||
border-radius: 20px;
|
||||
margin-bottom: 150px;
|
||||
min-width: 300px;
|
||||
min-height: 80px;
|
||||
min-width: 175px;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
/* Quick settings */
|
||||
|
||||
Reference in New Issue
Block a user