From 4f91bb8b8f8419006a96e5842e9ece2cb6673ca4 Mon Sep 17 00:00:00 2001 From: Jas Singh Date: Sun, 8 Sep 2024 02:01:13 -0700 Subject: [PATCH] Added filters for notifications and system tray items. (#234) * Added filters for notifications and systray. closes #233 * Add links to documentation. --- customModules/module.ts | 1 + globals.d.ts | 9 + globals/mousePos.ts | 4 +- lib/shared/media.ts | 10 +- lib/shared/notifications.ts | 15 + lib/types/volume.d.ts | 3 + modules/bar/battery/index.ts | 1 + modules/bar/bluetooth/index.ts | 1 + modules/bar/clock/index.ts | 1 + modules/bar/media/index.ts | 1 + modules/bar/menu/index.ts | 1 + modules/bar/network/index.ts | 1 + modules/bar/notifications/index.ts | 37 +- modules/bar/systray/index.ts | 2 + modules/bar/volume/index.ts | 11 +- modules/bar/window_title/index.ts | 1 + .../menus/notifications/notification/index.ts | 93 ++-- modules/notifications/index.ts | 12 +- options.ts | 3 +- tsconfig.json | 2 +- widget/settings/pages/config/bar/index.ts | 494 ++++++++++++++---- .../pages/config/notifications/index.ts | 101 +++- 22 files changed, 630 insertions(+), 174 deletions(-) create mode 100644 globals.d.ts create mode 100644 lib/shared/notifications.ts create mode 100644 lib/types/volume.d.ts diff --git a/customModules/module.ts b/customModules/module.ts index 1578334..6e38ffa 100644 --- a/customModules/module.ts +++ b/customModules/module.ts @@ -46,6 +46,7 @@ export const module = ({ default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `${boxClass} ${styleMap[style]} ${!shouldShowLabel ? "no-label" : ""}`; }), diff --git a/globals.d.ts b/globals.d.ts new file mode 100644 index 0000000..9c92638 --- /dev/null +++ b/globals.d.ts @@ -0,0 +1,9 @@ +// globals.d.ts + +import { Variable as VariableType } from "types/variable"; + +declare global { + var globalMousePos: VariableType; +} + +export { }; diff --git a/globals/mousePos.ts b/globals/mousePos.ts index 7e127a3..fe37eae 100644 --- a/globals/mousePos.ts +++ b/globals/mousePos.ts @@ -1,3 +1,5 @@ -const globalMousePosVar = Variable([0, 0]); +import { Variable as VariableType } from "types/variable"; + +const globalMousePosVar: VariableType = Variable([0, 0]); globalThis["globalMousePos"] = globalMousePosVar; diff --git a/lib/shared/media.ts b/lib/shared/media.ts index 733fdcf..be7e6ba 100644 --- a/lib/shared/media.ts +++ b/lib/shared/media.ts @@ -13,17 +13,17 @@ export const getCurrentPlayer = (activePlayer: MprisPlayer = mpris.players[0]): } const isPlaying = mpris.players.some( - (p) => p["play-back-status"] === "Playing", + (p: MprisPlayer) => p.play_back_status === "Playing", ); const playerStillExists = mpris.players.some( - (p) => activePlayer["bus-name"] === p["bus-name"], + (p) => activePlayer.bus_name === p.bus_name ); const nextPlayerUp = mpris.players.sort( - (a, b) => - statusOrder[a["play-back-status"]] - - statusOrder[b["play-back-status"]], + (a: MprisPlayer, b: MprisPlayer) => + statusOrder[a.play_back_status] - + statusOrder[b.play_back_status], )[0]; if (isPlaying || !playerStillExists) { diff --git a/lib/shared/notifications.ts b/lib/shared/notifications.ts new file mode 100644 index 0000000..8cb0535 --- /dev/null +++ b/lib/shared/notifications.ts @@ -0,0 +1,15 @@ +import { Notification } from "types/service/notifications"; + +export const filterNotifications = (notifications: Notification[], filter: string[]): Notification[] => { + + const notifFilter = new Set( + filter.map((name: string) => name.toLowerCase().replace(/\s+/g, '_')) + ); + + const filteredNotifications = notifications.filter((notif: Notification) => { + const normalizedAppName = notif.app_name.toLowerCase().replace(/\s+/g, '_'); + return !notifFilter.has(normalizedAppName); + }); + + return filteredNotifications; +} diff --git a/lib/types/volume.d.ts b/lib/types/volume.d.ts new file mode 100644 index 0000000..dd5ec22 --- /dev/null +++ b/lib/types/volume.d.ts @@ -0,0 +1,3 @@ +export type VolumeIcons = { + [index: number]: string +} diff --git a/modules/bar/battery/index.ts b/modules/bar/battery/index.ts index e35c511..49128ae 100644 --- a/modules/bar/battery/index.ts +++ b/modules/bar/battery/index.ts @@ -46,6 +46,7 @@ const BatteryLabel = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `battery ${styleMap[style]} ${!showLabel ? "no-label" : ""}`; }), diff --git a/modules/bar/bluetooth/index.ts b/modules/bar/bluetooth/index.ts index 8d1662b..c204b7a 100644 --- a/modules/bar/bluetooth/index.ts +++ b/modules/bar/bluetooth/index.ts @@ -32,6 +32,7 @@ const Bluetooth = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `bluetooth ${styleMap[style]} ${!showLabel ? "no-label" : ""}`; }), diff --git a/modules/bar/clock/index.ts b/modules/bar/clock/index.ts index fb99e3f..bcc48d9 100644 --- a/modules/bar/clock/index.ts +++ b/modules/bar/clock/index.ts @@ -33,6 +33,7 @@ const Clock = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `bluetooth ${styleMap[btnStyle]} ${!shwLbl ? "no-label" : ""} ${!shwIcn ? "no-icon" : ""}`; diff --git a/modules/bar/media/index.ts b/modules/bar/media/index.ts index e7f5237..a33dcd4 100644 --- a/modules/bar/media/index.ts +++ b/modules/bar/media/index.ts @@ -70,6 +70,7 @@ const Media = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `media ${styleMap[style]}`; }), diff --git a/modules/bar/menu/index.ts b/modules/bar/menu/index.ts index a258dc5..095c478 100644 --- a/modules/bar/menu/index.ts +++ b/modules/bar/menu/index.ts @@ -10,6 +10,7 @@ const Menu = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `dashboard ${styleMap[style]}`; }), diff --git a/modules/bar/network/index.ts b/modules/bar/network/index.ts index da944fa..7b3cc15 100644 --- a/modules/bar/network/index.ts +++ b/modules/bar/network/index.ts @@ -15,6 +15,7 @@ const Network = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `network ${styleMap[style]}${!showLabel ? " no-label" : ""}`; }), diff --git a/modules/bar/notifications/index.ts b/modules/bar/notifications/index.ts index f168a4e..dc8d4dc 100644 --- a/modules/bar/notifications/index.ts +++ b/modules/bar/notifications/index.ts @@ -1,8 +1,10 @@ import Gdk from 'gi://Gdk?version=3.0'; import { openMenu } from "../utils.js"; import options from "options"; +import { filterNotifications } from 'lib/shared/notifications.js'; const { show_total } = options.bar.notifications; +const { ignore } = options.notifications; const notifs = await Service.import("notifications"); @@ -10,30 +12,41 @@ export const Notifications = () => { return { component: Widget.Box({ hpack: "start", - className: Utils.merge([options.theme.bar.buttons.style.bind("value"), show_total.bind("value")], (style, showTotal) => { - const styleMap = { - default: "style1", - split: "style2", - wave: "style3", - }; - return `notifications ${styleMap[style]} ${!showTotal ? "no-label" : ""}`; - }), + className: Utils.merge( + [ + options.theme.bar.buttons.style.bind("value"), + show_total.bind("value") + ], + ( + style, + showTotal + ) => { + const styleMap = { + default: "style1", + split: "style2", + wave: "style3", + wave2: "style3", + }; + return `notifications ${styleMap[style]} ${!showTotal ? "no-label" : ""}`; + }), child: Widget.Box({ hpack: "start", class_name: "bar-notifications", children: Utils.merge( - [notifs.bind("notifications"), notifs.bind("dnd"), show_total.bind("value")], - (notif, dnd, showTotal) => { + [notifs.bind("notifications"), notifs.bind("dnd"), show_total.bind("value"), ignore.bind("value")], + (notif, dnd, showTotal, ignoredNotifs) => { + const filteredNotifications = filterNotifications(notif, ignoredNotifs); + const notifIcon = Widget.Label({ hpack: "center", class_name: "bar-button-icon notifications txt-icon bar", - label: dnd ? "󰂛" : notif.length > 0 ? "󱅫" : "󰂚", + label: dnd ? "󰂛" : filteredNotifications.length > 0 ? "󱅫" : "󰂚", }); const notifLabel = Widget.Label({ hpack: "center", class_name: "bar-button-label notifications", - label: notif.length.toString(), + label: filteredNotifications.length.toString(), }); if (showTotal) { diff --git a/modules/bar/systray/index.ts b/modules/bar/systray/index.ts index 1d4cc0e..c8de649 100644 --- a/modules/bar/systray/index.ts +++ b/modules/bar/systray/index.ts @@ -1,4 +1,5 @@ import Gdk from 'gi://Gdk?version=3.0'; +import { Notify } from 'lib/utils'; const systemtray = await Service.import("systemtray"); import options from "options"; @@ -27,6 +28,7 @@ const SysTray = () => { }), on_primary_click: (_: any, event: Gdk.Event) => item.activate(event), on_secondary_click: (_, event) => item.openMenu(event), + onMiddleClick: () => Notify({ summary: "App Name", body: item.id }), tooltip_markup: item.bind("tooltip_markup"), }); }); diff --git a/modules/bar/volume/index.ts b/modules/bar/volume/index.ts index 4c62062..937cac9 100644 --- a/modules/bar/volume/index.ts +++ b/modules/bar/volume/index.ts @@ -2,9 +2,11 @@ import Gdk from 'gi://Gdk?version=3.0'; const audio = await Service.import("audio"); import { openMenu } from "../utils.js"; import options from "options"; +import { Binding } from 'lib/utils.js'; +import { VolumeIcons } from 'lib/types/volume.js'; const Volume = () => { - const icons = { + const icons: VolumeIcons = { 101: "󰕾", 66: "󰕾", 34: "󰖀", @@ -13,16 +15,16 @@ const Volume = () => { }; const getIcon = () => { - const icon = Utils.merge( + const icon: Binding = Utils.merge( [audio.speaker.bind("is_muted"), audio.speaker.bind("volume")], (isMuted, vol) => { return isMuted ? 0 - : [101, 66, 34, 1, 0].find((threshold) => threshold <= vol * 100); + : [101, 66, 34, 1, 0].find((threshold) => threshold <= vol * 100) || 101; }, ); - return icon.as((i) => i !== undefined ? icons[i] : 101); + return icon.as((i: number) => i !== undefined ? icons[i] : icons[101]); }; const volIcn = Widget.Label({ @@ -46,6 +48,7 @@ const Volume = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `volume ${styleMap[style]} ${!showLabel ? "no-label" : ""}`; diff --git a/modules/bar/window_title/index.ts b/modules/bar/window_title/index.ts index 58a887c..0b0818e 100644 --- a/modules/bar/window_title/index.ts +++ b/modules/bar/window_title/index.ts @@ -140,6 +140,7 @@ const ClientTitle = () => { default: "style1", split: "style2", wave: "style3", + wave2: "style3", }; return `windowtitle ${styleMap[style]} ${!showLabel ? "no-label" : ""}`; }), diff --git a/modules/menus/notifications/notification/index.ts b/modules/menus/notifications/notification/index.ts index 74cdfa1..62a1749 100644 --- a/modules/menus/notifications/notification/index.ts +++ b/modules/menus/notifications/notification/index.ts @@ -8,8 +8,9 @@ import { Body } from "./body/index.js"; import { CloseButton } from "./close/index.js"; import options from "options.js"; import { Variable } from "types/variable.js"; +import { filterNotifications } from "lib/shared/notifications.js"; -const { displayedTotal } = options.notifications; +const { displayedTotal, ignore } = options.notifications; const NotificationCard = (notifs: Notifications, curPage: Variable) => { return Widget.Scrollable({ @@ -21,46 +22,60 @@ const NotificationCard = (notifs: Notifications, curPage: Variable) => { spacing: 0, vertical: true, setup: (self) => { - Utils.merge([notifs.bind("notifications"), curPage.bind("value"), displayedTotal.bind("value")], (notifications, currentPage, dispTotal) => { - const sortedNotifications = notifications.sort( - (a, b) => b.time - a.time, - ); + Utils.merge( + [ + notifs.bind("notifications"), + curPage.bind("value"), + displayedTotal.bind("value"), + ignore.bind("value") + ], + ( + notifications, + currentPage, + dispTotal, + ignoredNotifs + ) => { + const filteredNotifications = filterNotifications(notifications, ignoredNotifs); - if (notifications.length <= 0) { - return (self.children = [Placeholder(notifs)]); - } + const sortedNotifications = filteredNotifications.sort( + (a, b) => b.time - a.time, + ); - const pageStart = (currentPage - 1) * dispTotal; - const pageEnd = currentPage * dispTotal; - return (self.children = sortedNotifications.slice(pageStart, pageEnd).map((notif: Notification) => { - return Widget.Box({ - class_name: "notification-card-content-container", - children: [ - Widget.Box({ - class_name: "notification-card menu", - vpack: "start", - hexpand: true, - vexpand: false, - children: [ - Image(notif), - Widget.Box({ - vpack: "center", - vertical: true, - hexpand: true, - class_name: `notification-card-content ${!notifHasImg(notif) ? "noimg" : " menu"}`, - children: [ - Header(notif), - Body(notif), - Actions(notif, notifs), - ], - }), - ], - }), - CloseButton(notif, notifs), - ], - }); - })); - }); + if (filteredNotifications.length <= 0) { + return (self.children = [Placeholder(notifs)]); + } + + const pageStart = (currentPage - 1) * dispTotal; + const pageEnd = currentPage * dispTotal; + return (self.children = sortedNotifications.slice(pageStart, pageEnd).map((notif: Notification) => { + return Widget.Box({ + class_name: "notification-card-content-container", + children: [ + Widget.Box({ + class_name: "notification-card menu", + vpack: "start", + hexpand: true, + vexpand: false, + children: [ + Image(notif), + Widget.Box({ + vpack: "center", + vertical: true, + hexpand: true, + class_name: `notification-card-content ${!notifHasImg(notif) ? "noimg" : " menu"}`, + children: [ + Header(notif), + Body(notif), + Actions(notif, notifs), + ], + }), + ], + }), + CloseButton(notif, notifs), + ], + }); + })); + }); }, }) }); diff --git a/modules/notifications/index.ts b/modules/notifications/index.ts index 4e742d9..54eb2ca 100644 --- a/modules/notifications/index.ts +++ b/modules/notifications/index.ts @@ -7,9 +7,11 @@ import { Header } from "./header/index.js"; import { Body } from "./body/index.js"; import { CloseButton } from "./close/index.js"; import { getPosition } from "lib/utils.js"; +import { filterNotifications } from "lib/shared/notifications.js"; +import { Notification } from "types/service/notifications.js"; const hyprland = await Service.import("hyprland"); -const { position, timeout, cache_actions, monitor, active_monitor, displayedTotal } = options.notifications; +const { position, timeout, cache_actions, monitor, active_monitor, displayedTotal, ignore } = options.notifications; const curMonitor = Variable(monitor.value); @@ -46,8 +48,10 @@ export default () => { vertical: true, hexpand: true, setup: (self) => { - self.hook(notifs, () => { - return (self.children = notifs.popups.slice(0, displayedTotal.value).map((notif) => { + Utils.merge([notifs.bind("popups"), ignore.bind("value")], (notifications: Notification[], ignoredNotifs: string[]) => { + const filteredNotifications = filterNotifications(notifications, ignoredNotifs); + + return (self.children = filteredNotifications.slice(0, displayedTotal.value).map((notif) => { return Widget.Box({ class_name: "notification-card", vpack: "start", @@ -65,7 +69,7 @@ export default () => { ], }); })); - }); + }) }, }), }); diff --git a/options.ts b/options.ts index 1681ab7..529c987 100644 --- a/options.ts +++ b/options.ts @@ -849,7 +849,7 @@ const options = mkOptions(OPTIONS, { label: opt(true), }, systray: { - ignore: opt([]), + ignore: opt([]), }, clock: { icon: opt("󰸗"), @@ -1068,6 +1068,7 @@ const options = mkOptions(OPTIONS, { notifications: { position: opt("top right"), + ignore: opt([]), displayedTotal: opt(10), monitor: opt(0), active_monitor: opt(true), diff --git a/tsconfig.json b/tsconfig.json index ff8d4be..288c831 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,7 +9,7 @@ "allowJs": true, "checkJs": true, "strict": true, - "noImplicitAny": false, + "noImplicitAny": true, "baseUrl": ".", "typeRoots": [ "types", diff --git a/widget/settings/pages/config/bar/index.ts b/widget/settings/pages/config/bar/index.ts index 8a0cc0c..85cc2d2 100644 --- a/widget/settings/pages/config/bar/index.ts +++ b/widget/settings/pages/config/bar/index.ts @@ -2,8 +2,10 @@ import { Option } from "widget/settings/shared/Option"; import { Header } from "widget/settings/shared/Header"; import options from "options"; +import Scrollable from "types/widgets/scrollable"; +import Gtk from "types/@girs/gtk-3.0/gtk-3.0"; -export const BarSettings = () => { +export const BarSettings = (): Scrollable => { return Widget.Scrollable({ vscroll: "always", hscroll: "automatic", @@ -11,109 +13,423 @@ export const BarSettings = () => { child: Widget.Box({ vertical: true, children: [ - Header('Layouts'), + /* + ****************************** + * LAYOUTS * + ****************************** + */ + Header("Layouts"), + Option( + { + opt: options.bar.layouts, + title: "Bar Layouts for Monitors", + subtitle: "Wiki Link: https://hyprpanel.com/configuration/panel.html#layouts", + type: "object", + subtitleLink: "https://hyprpanel.com/configuration/panel.html#layouts", + }, + "bar-layout-input" + ), + + /* + ****************************** + * SPACING * + ****************************** + */ + Header("Spacing"), Option({ - opt: options.bar.layouts, - title: 'Bar Layouts for Monitors', - subtitle: 'Wiki Link: https://hyprpanel.com/configuration/panel.html#layouts', - type: 'object', - subtitleLink: 'https://hyprpanel.com/configuration/panel.html#layouts' - }, - 'bar-layout-input'), + opt: options.theme.bar.outer_spacing, + title: "Outer Spacing", + subtitle: "Spacing on the outer left and right edges of the bar.", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.y_margins, + title: "Vertical Margins", + subtitle: "Spacing above/below the buttons in the bar.", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.spacing, + title: "Button Spacing", + subtitle: "Spacing between the buttons in the bar.", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.padding_x, + title: "Button Horizontal Padding", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.padding_y, + title: "Button Vertical Padding", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.radius, + title: "Button Radius", + type: "string", + }), + Option({ + opt: options.theme.bar.floating, + title: "Floating Bar", + type: "boolean", + }), + Option({ + opt: options.theme.bar.layer, + title: "Layer", + type: "enum", + subtitle: "Layer determines the Z index of your bar.", + enums: ["top", "bottom", "overlay", "background"], + }), + Option({ + opt: options.theme.bar.margin_top, + title: "Margin Top", + subtitle: "Only applies if floating is enabled", + type: "string", + }), + Option({ + opt: options.theme.bar.margin_bottom, + title: "Margin Bottom", + subtitle: "Only applies if floating is enabled", + type: "string", + }), + Option({ + opt: options.theme.bar.margin_sides, + title: "Margin Sides", + subtitle: "Only applies if floating is enabled", + type: "string", + }), + Option({ + opt: options.theme.bar.border_radius, + title: "Border Radius", + subtitle: "Only applies if floating is enabled", + type: "string", + }), - Header('Spacing'), - Option({ opt: options.theme.bar.outer_spacing, title: 'Outer Spacing', subtitle: 'Spacing on the outer left and right edges of the bar.', type: 'string' }), - Option({ opt: options.theme.bar.buttons.y_margins, title: 'Vertical Margins', subtitle: 'Spacing above/below the buttons in the bar.', type: 'string' }), - Option({ opt: options.theme.bar.buttons.spacing, title: 'Button Spacing', subtitle: 'Spacing between the buttons in the bar.', type: 'string' }), - Option({ opt: options.theme.bar.buttons.padding_x, title: 'Button Horizontal Padding', type: 'string' }), - Option({ opt: options.theme.bar.buttons.padding_y, title: 'Button Vertical Padding', type: 'string' }), - Option({ opt: options.theme.bar.buttons.radius, title: 'Button Radius', type: 'string' }), - Option({ opt: options.theme.bar.floating, title: 'Floating Bar', type: 'boolean' }), - Option({ opt: options.theme.bar.layer, title: 'Layer', type: 'enum', subtitle: 'Layer determines the Z index of your bar.', enums: ["top", "bottom", "overlay", "background"] }), - Option({ opt: options.theme.bar.margin_top, title: 'Margin Top', subtitle: 'Only applies if floating is enabled', type: 'string' }), - Option({ opt: options.theme.bar.margin_bottom, title: 'Margin Bottom', subtitle: 'Only applies if floating is enabled', type: 'string' }), - Option({ opt: options.theme.bar.margin_sides, title: 'Margin Sides', subtitle: 'Only applies if floating is enabled', type: 'string' }), - Option({ opt: options.theme.bar.border_radius, title: 'Border Radius', subtitle: 'Only applies if floating is enabled', type: 'string' }), + /* + ****************************** + * DASHBOARD * + ****************************** + */ + Header("Dashboard"), + Option({ + opt: options.bar.launcher.icon, + title: "Dashboard Menu Icon", + type: "string", + }), - Header('Dashboard'), - Option({ opt: options.bar.launcher.icon, title: 'Dashboard Menu Icon', type: 'string' }), - - Header('Workspaces'), - Option({ opt: options.bar.workspaces.show_icons, title: 'Show Workspace Icons', type: 'boolean' }), - Option({ opt: options.bar.workspaces.icons.available, title: 'Workspace Available', type: 'string' }), - Option({ opt: options.bar.workspaces.icons.active, title: 'Workspace Active', type: 'string' }), - Option({ opt: options.bar.workspaces.icons.occupied, title: 'Workspace Occupied', type: 'string' }), - Option({ opt: options.bar.workspaces.show_numbered, title: 'Show Workspace Numbers', type: 'boolean' }), - Option({ opt: options.bar.workspaces.numbered_active_indicator, title: 'Numbered Workspace Identifier', subtitle: 'Only applicable if Workspace Numbers are enabled', type: 'enum', enums: ["underline", "highlight", "color"] }), - Option({ opt: options.theme.bar.buttons.workspaces.numbered_active_highlight_border, title: 'Highlight Radius', subtitle: 'Only applicable if Workspace Numbers are enabled', type: 'string' }), - Option({ opt: options.theme.bar.buttons.workspaces.numbered_active_highlight_padding, title: 'Highlight Padding', subtitle: 'Only applicable if Workspace Numbers are enabled', type: 'string' }), - Option({ opt: options.bar.workspaces.spacing, title: 'Spacing', subtitle: 'Spacing between workspace icons', type: 'float' }), - Option({ opt: options.bar.workspaces.workspaces, title: 'Total Workspaces', subtitle: 'The least amount of workspaces to always show.', type: 'number' }), - Option({ opt: options.bar.workspaces.monitorSpecific, title: 'Monitor Specific', subtitle: 'Only workspaces applicable to the monitor will be displayed.\nWorks in conjuction with \'Total Workspaces\'.', type: 'boolean' }), - Option({ opt: options.bar.workspaces.hideUnoccupied, title: 'Hide Unoccupied', subtitle: 'Only show workspaces that are occupied or active', type: 'boolean' }), + /* + ****************************** + * WORKSPACES * + ****************************** + */ + Header("Workspaces"), + Option({ + opt: options.bar.workspaces.show_icons, + title: "Show Workspace Icons", + type: "boolean", + }), + Option({ + opt: options.bar.workspaces.icons.available, + title: "Workspace Available", + type: "string", + }), + Option({ + opt: options.bar.workspaces.icons.active, + title: "Workspace Active", + type: "string", + }), + Option({ + opt: options.bar.workspaces.icons.occupied, + title: "Workspace Occupied", + type: "string", + }), + Option({ + opt: options.bar.workspaces.show_numbered, + title: "Show Workspace Numbers", + type: "boolean", + }), + Option({ + opt: options.bar.workspaces.numbered_active_indicator, + title: "Numbered Workspace Identifier", + subtitle: "Only applicable if Workspace Numbers are enabled", + type: "enum", + enums: ["underline", "highlight", "color"], + }), + Option({ + opt: options.theme.bar.buttons.workspaces.numbered_active_highlight_border, + title: "Highlight Radius", + subtitle: "Only applicable if Workspace Numbers are enabled", + type: "string", + }), + Option({ + opt: options.theme.bar.buttons.workspaces.numbered_active_highlight_padding, + title: "Highlight Padding", + subtitle: "Only applicable if Workspace Numbers are enabled", + type: "string", + }), + Option({ + opt: options.bar.workspaces.spacing, + title: "Spacing", + subtitle: "Spacing between workspace icons", + type: "float", + }), + Option({ + opt: options.bar.workspaces.workspaces, + title: "Total Workspaces", + subtitle: "The least amount of workspaces to always show.", + type: "number", + }), + Option({ + opt: options.bar.workspaces.monitorSpecific, + title: "Monitor Specific", + subtitle: + "Only workspaces applicable to the monitor will be displayed.\n" + + "Works in conjuction with 'Total Workspaces'.", + type: "boolean", + }), + Option({ + opt: options.bar.workspaces.hideUnoccupied, + title: "Hide Unoccupied", + subtitle: "Only show workspaces that are occupied or active", + type: "boolean", + }), Option({ opt: options.bar.workspaces.workspaceMask, - title: 'Mask Workspace Numbers On Monitors', - - subtitle: `Only applicable if Workspace Numbers and Monitor Specific are enabled. -Forces each Monitor's Workspace labels to start from 1.`, - type: 'boolean' + title: "Mask Workspace Numbers On Monitors", + subtitle: "Only applicable if Workspace Numbers and Monitor Specific are enabled.\n" + + "Forces each Monitor's Workspace labels to start from 1.", + type: "boolean", + }), + Option({ + opt: options.bar.workspaces.reverse_scroll, + title: "Invert Scroll", + subtitle: "Scrolling up will go to the previous workspace rather than the next.", + type: "boolean", + }), + Option({ + opt: options.bar.workspaces.scroll_speed, + title: "Scrolling Speed", + type: "number", }), - Option({ opt: options.bar.workspaces.reverse_scroll, title: 'Invert Scroll', subtitle: 'Scrolling up will go to the previous workspace rather than the next.', type: 'boolean' }), - Option({ opt: options.bar.workspaces.scroll_speed, title: 'Scrolling Speed', type: 'number' }), - Header('Window Titles'), - Option({ opt: options.bar.windowtitle.label, title: 'Show Window Title Label', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.windowtitle.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * WINDOW TITLES * + ****************************** + */ + Header("Window Titles"), + Option({ + opt: options.bar.windowtitle.label, + title: "Show Window Title Label", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.windowtitle.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), Option({ opt: options.bar.windowtitle.title_map, - title: 'Window Title Mappings', - subtitle: 'Wiki Link: https://hyprpanel.com/configuration/panel.html#window-title-mappings', - type: 'object', - subtitleLink: 'https://hyprpanel.com/configuration/panel.html#window-title-mappings' + title: "Window Title Mappings", + subtitle: "Wiki Link: https://hyprpanel.com/configuration/panel.html#window-title-mappings", + type: "object", + subtitleLink: "https://hyprpanel.com/configuration/panel.html#window-title-mappings", }), - Header('Volume'), - Option({ opt: options.bar.volume.label, title: 'Show Volume Percentage', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.volume.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * VOLUME * + ****************************** + */ + Header("Volume"), + Option({ + opt: options.bar.volume.label, + title: "Show Volume Percentage", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.volume.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), - Header('Network'), - Option({ opt: options.bar.network.label, title: 'Show Network Name', type: 'boolean' }), - Option({ opt: options.bar.network.truncation, title: 'Truncate Network Name', subtitle: 'Will truncate the network name to the specified size below.', type: 'boolean' }), - Option({ opt: options.bar.network.truncation_size, title: 'Truncation Size', type: 'number' }), - Option({ opt: options.theme.bar.buttons.network.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * NETWORK * + ****************************** + */ + Header("Network"), + Option({ + opt: options.bar.network.label, + title: "Show Network Name", + type: "boolean", + }), + Option({ + opt: options.bar.network.truncation, + title: "Truncate Network Name", + subtitle: "Will truncate the network name to the specified size below.", + type: "boolean", + }), + Option({ + opt: options.bar.network.truncation_size, + title: "Truncation Size", + type: "number", + }), + Option({ + opt: options.theme.bar.buttons.network.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), - Header('Bluetooth'), - Option({ opt: options.bar.bluetooth.label, title: 'Show Bluetooth Label', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.bluetooth.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * BLUETOOTH * + ****************************** + */ + Header("Bluetooth"), + Option({ + opt: options.bar.bluetooth.label, + title: "Show Bluetooth Label", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.bluetooth.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), - Header('Battery'), - Option({ opt: options.bar.battery.label, title: 'Show Battery Percentage', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.battery.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * BATTERY * + ****************************** + */ + Header("Battery"), + Option({ + opt: options.bar.battery.label, + title: "Show Battery Percentage", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.battery.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), - // Header('System Tray'), - // TODO: Figure out how to handle arrays - // Option({ opt: options.bar.systray.ignore, title: 'Ignore', subtitle: 'Comma separated string of apps to ignore in the tray', type: 'string' }), + /* + ****************************** + * SYSTEM TRAY * + ****************************** + */ + Header("System Tray"), + Option({ + opt: options.bar.systray.ignore, + title: "Ignore List", + subtitle: + "An array of applications to prevent from showing in the system tray.\n" + + "Wiki: https://hyprpanel.com/configuration/panel.html#system-tray", + subtitleLink: "https://hyprpanel.com/configuration/panel.html#system-tray", + type: "object", + }), - Header('Clock'), - Option({ opt: options.bar.clock.format, title: 'Clock Format', type: 'string' }), - Option({ opt: options.bar.clock.icon, title: 'Icon', type: 'string' }), - Option({ opt: options.bar.clock.showIcon, title: 'Show Icon', type: 'boolean' }), - Option({ opt: options.bar.clock.showTime, title: 'Show Time', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.clock.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), + /* + ****************************** + * CLOCK * + ****************************** + */ + Header("Clock"), + Option({ + opt: options.bar.clock.format, + title: "Clock Format", + type: "string", + }), + Option({ + opt: options.bar.clock.icon, + title: "Icon", + type: "string", + }), + Option({ + opt: options.bar.clock.showIcon, + title: "Show Icon", + type: "boolean", + }), + Option({ + opt: options.bar.clock.showTime, + title: "Show Time", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.clock.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), - Header('Media'), - Option({ opt: options.theme.bar.buttons.media.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), - Option({ opt: options.bar.media.show_artist, title: 'Show Track Artist', type: 'boolean' }), - Option({ opt: options.bar.media.show_label, title: 'Toggle Media Label', type: 'boolean' }), - Option({ opt: options.bar.media.truncation, title: 'Truncate Media Label', subtitle: 'Only applicable if Toggle Media Label is enabled', type: 'boolean' }), - Option({ opt: options.bar.media.truncation_size, title: 'Truncation Size', subtitle: 'Only applicable if Toggle Media Label is enabled', type: 'number', min: 10 }), - Option({ opt: options.bar.media.show_active_only, title: 'Auto Hide', subtitle: 'Button will automatically hide if no media is detected.', type: 'boolean' }), + /* + ****************************** + * MEDIA * + ****************************** + */ + Header("Media"), + Option({ + opt: options.theme.bar.buttons.media.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), + Option({ + opt: options.bar.media.show_artist, + title: "Show Track Artist", + type: "boolean", + }), + Option({ + opt: options.bar.media.show_label, + title: "Toggle Media Label", + type: "boolean", + }), + Option({ + opt: options.bar.media.truncation, + title: "Truncate Media Label", + subtitle: "Only applicable if Toggle Media Label is enabled", + type: "boolean", + }), + Option({ + opt: options.bar.media.truncation_size, + title: "Truncation Size", + subtitle: "Only applicable if Toggle Media Label is enabled", + type: "number", + min: 10, + }), + Option({ + opt: options.bar.media.show_active_only, + title: "Auto Hide", + subtitle: "Button will automatically hide if no media is detected.", + type: "boolean", + }), - Header('Notifications'), - Option({ opt: options.bar.notifications.show_total, title: 'Show Total # of notifications', type: 'boolean' }), - Option({ opt: options.theme.bar.buttons.notifications.spacing, title: 'Inner Spacing', subtitle: 'Spacing between the icon and the label inside the buttons.', type: 'string' }), - ] - }) - }) -} + /* + ****************************** + * NOTIFICATIONS * + ****************************** + */ + Header("Notifications"), + Option({ + opt: options.bar.notifications.show_total, + title: "Show Total # of notifications", + type: "boolean", + }), + Option({ + opt: options.theme.bar.buttons.notifications.spacing, + title: "Inner Spacing", + subtitle: "Spacing between the icon and the label inside the buttons.", + type: "string", + }), + ], + }), + }); +}; diff --git a/widget/settings/pages/config/notifications/index.ts b/widget/settings/pages/config/notifications/index.ts index 7660e72..a5ca185 100644 --- a/widget/settings/pages/config/notifications/index.ts +++ b/widget/settings/pages/config/notifications/index.ts @@ -2,29 +2,94 @@ import { Option } from "widget/settings/shared/Option"; import { Header } from "widget/settings/shared/Header"; import options from "options"; +import Scrollable from "types/widgets/scrollable"; +import Gtk from "types/@girs/gtk-3.0/gtk-3.0"; -export const NotificationSettings = () => { +export const NotificationSettings = (): Scrollable => { return Widget.Scrollable({ vscroll: "automatic", child: Widget.Box({ class_name: "bar-theme-page paged-container", vertical: true, children: [ - Header('Notification Settings'), - Option({ opt: options.notifications.position, title: 'Notification Location', type: 'enum', enums: ['top left', 'top', 'top right', 'right', 'bottom right', 'bottom', 'bottom left', 'left'] }), - Option({ opt: options.theme.notification.border_radius, title: 'Border Radius', type: 'string' }), - Option({ opt: options.notifications.monitor, title: 'Monitor', subtitle: 'The ID of the monitor on which to display the notification', type: 'number' }), - Option({ opt: options.notifications.active_monitor, title: 'Follow Cursor', subtitle: 'The notification will follow the monitor of your cursor', type: 'boolean' }), - Option({ opt: options.notifications.timeout, title: 'Notification Timeout', subtitle: 'How long notification popups will last (in milliseconds).', type: 'number' }), - Option({ opt: options.notifications.cache_actions, title: 'Preserve Actions', subtitle: 'This will persist the action buttons of a notification after rebooting.', type: 'boolean' }), + Header("Notification Settings"), + Option({ + opt: options.notifications.ignore, + title: "Ignored Applications", + subtitle: "Applications to ignore.\n" + + "Wiki: https://hyprpanel.com/configuration/notifications.html#ignored-applications", + subtitleLink: "https://hyprpanel.com/configuration/notifications.html#ignored-applications", + type: "object", + enums: ["top left", "top", "top right", "right", "bottom right", "bottom", "bottom left", "left"], + }), + Option({ + opt: options.notifications.position, + title: "Notification Location", + type: "enum", + enums: ["top left", "top", "top right", "right", "bottom right", "bottom", "bottom left", "left"], + }), + Option({ + opt: options.theme.notification.border_radius, + title: "Border Radius", + type: "string", + }), + Option({ + opt: options.notifications.monitor, + title: "Monitor", + subtitle: "The ID of the monitor on which to display the notification", + type: "number", + }), + Option({ + opt: options.notifications.active_monitor, + title: "Follow Cursor", + subtitle: "The notification will follow the monitor of your cursor", + type: "boolean", + }), + Option({ + opt: options.notifications.timeout, + title: "Notification Timeout", + subtitle: "How long notification popups will last (in milliseconds).", + type: "number", + }), + Option({ + opt: options.notifications.cache_actions, + title: "Preserve Actions", + subtitle: "This will persist the action buttons of a notification after rebooting.", + type: "boolean", + }), + + Header("Notification Menu Settings"), + Option({ + opt: options.theme.bar.menus.menu.notifications.height, + title: "Notification Menu Height", + type: "string", + }), + Option({ + opt: options.notifications.displayedTotal, + title: "Displayed Total", + subtitle: "How many notifications to show in the menu at once.\n" + + "Newer notifications will display towards the top.", + type: "number", + min: 1, + }), + Option({ + opt: options.theme.bar.menus.menu.notifications.pager.show, + title: "Show Pager", + subtitle: "Shows the pagination footer at the bottom of the menu.", + type: "boolean", + }), + Option({ + opt: options.theme.bar.menus.menu.notifications.scrollbar.width, + title: "Scrollbar Width", + type: "string", + }), + Option({ + opt: options.theme.bar.menus.menu.notifications.scrollbar.radius, + title: "Scrollbar Radius", + type: "string", + }), + ], + }), + }); +}; - Header('Notification Menu Settings'), - Option({ opt: options.theme.bar.menus.menu.notifications.height, title: 'Notification Menu Height', type: 'string' }), - Option({ opt: options.notifications.displayedTotal, title: 'Displayed Total', subtitle: 'How many notifications to show in the menu at once.\nNewer notifications will display towards the top.', type: 'number', min: 1 }), - Option({ opt: options.theme.bar.menus.menu.notifications.pager.show, title: 'Show Pager', subtitle: "Shows the pagination footer at the bottom of the menu.", type: 'boolean' }), - Option({ opt: options.theme.bar.menus.menu.notifications.scrollbar.width, title: 'Scrollbar Width', type: 'string' }), - Option({ opt: options.theme.bar.menus.menu.notifications.scrollbar.radius, title: 'Scrollbar Radius', type: 'string' }), - ] - }) - }) -}