diff --git a/modules/common/ags/config.js b/modules/common/ags/config.js index ff29fc4..64bacd5 100644 --- a/modules/common/ags/config.js +++ b/modules/common/ags/config.js @@ -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(), ], }); diff --git a/modules/common/ags/layouts/osd.js b/modules/common/ags/layouts/osd.js index fd54068..ac98a1a 100644 --- a/modules/common/ags/layouts/osd.js +++ b/modules/common/ags/layouts/osd.js @@ -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(), + }); diff --git a/modules/common/ags/layouts/quicksettings.js b/modules/common/ags/layouts/quicksettings.js index 3550b62..9d80243 100644 --- a/modules/common/ags/layouts/quicksettings.js +++ b/modules/common/ags/layouts/quicksettings.js @@ -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", diff --git a/modules/common/ags/modules/audio.js b/modules/common/ags/modules/audio.js index b8675b0..1428da5 100644 --- a/modules/common/ags/modules/audio.js +++ b/modules/common/ags/modules/audio.js @@ -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, }); diff --git a/modules/common/ags/modules/notifications.js b/modules/common/ags/modules/notifications.js index 4c4db6d..9f1b3ca 100644 --- a/modules/common/ags/modules/notifications.js +++ b/modules/common/ags/modules/notifications.js @@ -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({ diff --git a/modules/common/ags/modules/systray.js b/modules/common/ags/modules/systray.js index 98cbd5b..8c412d6 100644 --- a/modules/common/ags/modules/systray.js +++ b/modules/common/ags/modules/systray.js @@ -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({ diff --git a/modules/common/ags/services/brightness.js b/modules/common/ags/services/brightness.js index f30c337..e5e554d 100644 --- a/modules/common/ags/services/brightness.js +++ b/modules/common/ags/services/brightness.js @@ -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`) diff --git a/modules/common/ags/services/osd.js b/modules/common/ags/services/osd.js deleted file mode 100644 index e2f4cec..0000000 --- a/modules/common/ags/services/osd.js +++ /dev/null @@ -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; diff --git a/modules/common/ags/style.css b/modules/common/ags/style.css index de6a30a..fcce45c 100644 --- a/modules/common/ags/style.css +++ b/modules/common/ags/style.css @@ -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 */