From 5b01d3e60e6fb5c30aba1129d9001323ef2ff1e2 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 01:52:29 +0545 Subject: [PATCH 01/10] feat: add option to hide seconds on calendar (#343) --- modules/menus/calendar/time/index.ts | 61 +++++++++++---------- options.ts | 1 + widget/settings/pages/config/menus/clock.ts | 1 + 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/modules/menus/calendar/time/index.ts b/modules/menus/calendar/time/index.ts index 0812a61..2cbb279 100644 --- a/modules/menus/calendar/time/index.ts +++ b/modules/menus/calendar/time/index.ts @@ -1,7 +1,7 @@ import { BoxWidget } from 'lib/types/widget'; import options from 'options'; -const { military } = options.menus.clock.time; +const { military, hideSeconds } = options.menus.clock.time; const time = Variable('', { poll: [1000, 'date "+%I:%M:%S"'], @@ -26,43 +26,48 @@ const TimeWidget = (): BoxWidget => { vpack: 'center', hpack: 'center', class_name: 'clock-content-items', - children: military.bind('value').as((is24hr) => { - if (!is24hr) { + children: Utils.merge( + [military.bind('value'), hideSeconds.bind('value')], + (is24hr: boolean, hideSeconds: boolean) => { + if (!is24hr) { + return [ + Widget.Box({ + hpack: 'center', + children: [ + Widget.Label({ + class_name: 'clock-content-time', + label: hideSeconds ? time.bind().as((str) => str.slice(0, -3)) : time.bind(), + }), + ], + }), + Widget.Box({ + hpack: 'center', + children: [ + Widget.Label({ + vpack: 'end', + class_name: 'clock-content-period', + label: period.bind(), + }), + ], + }), + ]; + } + return [ Widget.Box({ hpack: 'center', children: [ Widget.Label({ class_name: 'clock-content-time', - label: time.bind(), - }), - ], - }), - Widget.Box({ - hpack: 'center', - children: [ - Widget.Label({ - vpack: 'end', - class_name: 'clock-content-period', - label: period.bind(), + label: hideSeconds + ? militaryTime.bind().as((str) => str.slice(0, -3)) + : militaryTime.bind(), }), ], }), ]; - } - - return [ - Widget.Box({ - hpack: 'center', - children: [ - Widget.Label({ - class_name: 'clock-content-time', - label: militaryTime.bind(), - }), - ], - }), - ]; - }), + }, + ), }), }); }; diff --git a/options.ts b/options.ts index 805a180..98b202a 100644 --- a/options.ts +++ b/options.ts @@ -1137,6 +1137,7 @@ const options = mkOptions(OPTIONS, { clock: { time: { military: opt(false), + hideSeconds: opt(false), }, weather: { enabled: opt(true), diff --git a/widget/settings/pages/config/menus/clock.ts b/widget/settings/pages/config/menus/clock.ts index 7f71120..71d8e18 100644 --- a/widget/settings/pages/config/menus/clock.ts +++ b/widget/settings/pages/config/menus/clock.ts @@ -14,6 +14,7 @@ export const ClockMenuSettings = (): Scrollable => { children: [ Header('Time'), Option({ opt: options.menus.clock.time.military, title: 'Use 24hr time', type: 'boolean' }), + Option({ opt: options.menus.clock.time.hideSeconds, title: 'Hide seconds', type: 'boolean' }), Header('Weather'), Option({ opt: options.menus.clock.weather.enabled, title: 'Enabled', type: 'boolean' }), From 7a2d91744fd4ff9e06075a9ef988b73e56277ea1 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 02:24:16 +0545 Subject: [PATCH 02/10] fix: hide pager when only first page (#335) * fix: hide pager when only first page * fix: lints and formatting --------- Co-authored-by: Jas Singh --- modules/menus/notifications/pager/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/menus/notifications/pager/index.ts b/modules/menus/notifications/pager/index.ts index 62dd1bf..1a4571b 100644 --- a/modules/menus/notifications/pager/index.ts +++ b/modules/menus/notifications/pager/index.ts @@ -21,7 +21,7 @@ export const NotificationPager = (curPage: Variable): BoxWidget => { showPager.bind('value'), ], (currentPage: number, dispTotal: number, _: Notification[], showPgr: boolean) => { - if (showPgr === false) { + if (showPgr === false || (currentPage === 1 && notifs.notifications.length <= dispTotal)) { return []; } return [ From 27d2652e8e66f17dffbac6fb09bf953bc5389012 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 04:04:30 +0545 Subject: [PATCH 03/10] feat: add option to toggle each section on dashboard (#344) Co-authored-by: Jas Singh --- modules/menus/dashboard/index.ts | 40 +++++++++++-------- options.ts | 5 +++ .../settings/pages/config/menus/dashboard.ts | 6 ++- 3 files changed, 33 insertions(+), 18 deletions(-) diff --git a/modules/menus/dashboard/index.ts b/modules/menus/dashboard/index.ts index 0569109..9bac607 100644 --- a/modules/menus/dashboard/index.ts +++ b/modules/menus/dashboard/index.ts @@ -8,7 +8,7 @@ import Window from 'types/widgets/window.js'; import { Attribute, Child } from 'lib/types/widget.js'; import options from 'options.js'; -const { enabled: directoriesEnabled } = options.menus.dashboard.directories; +const { controls, shortcuts, stats, directories } = options.menus.dashboard; export default (): Window => { return DropdownMenu({ @@ -22,21 +22,29 @@ export default (): Window => { Widget.Box({ class_name: 'dashboard-content-container', vertical: true, - children: directoriesEnabled.bind('value').as((isDirectoriesEnabled) => { - return [ - Widget.Box({ - class_name: 'dashboard-content-items', - vertical: true, - children: [ - Profile(), - Shortcuts(), - Controls(), - ...(isDirectoriesEnabled ? [Directories()] : []), - Stats(), - ], - }), - ]; - }), + children: Utils.merge( + [ + controls.enabled.bind('value'), + shortcuts.enabled.bind('value'), + stats.enabled.bind('value'), + directories.enabled.bind('value'), + ], + (isControlsEnabled, isShortcutsEnabled, isStatsEnabled, isDirectoriesEnabled) => { + return [ + Widget.Box({ + class_name: 'dashboard-content-items', + vertical: true, + children: [ + Profile(), + ...(isShortcutsEnabled ? [Shortcuts()] : []), + ...(isControlsEnabled ? [Controls()] : []), + ...(isDirectoriesEnabled ? [Directories()] : []), + ...(isStatsEnabled ? [Stats()] : []), + ], + }), + ]; + }, + ), }), ], }), diff --git a/options.ts b/options.ts index 98b202a..e6a1cfd 100644 --- a/options.ts +++ b/options.ts @@ -1064,9 +1064,14 @@ const options = mkOptions(OPTIONS, { }, }, stats: { + enabled: opt(true), enable_gpu: opt(false), }, + controls: { + enabled: opt(true), + }, shortcuts: { + enabled: opt(true), left: { shortcut1: { icon: opt('󰇩'), diff --git a/widget/settings/pages/config/menus/dashboard.ts b/widget/settings/pages/config/menus/dashboard.ts index e6ef528..fbb7128 100644 --- a/widget/settings/pages/config/menus/dashboard.ts +++ b/widget/settings/pages/config/menus/dashboard.ts @@ -43,16 +43,18 @@ export const DashboardMenuSettings = (): Scrollable => { Option({ opt: options.menus.dashboard.powermenu.reboot, title: 'Reboot Command', type: 'string' }), Option({ opt: options.menus.dashboard.powermenu.logout, title: 'Logout Command', type: 'string' }), Option({ opt: options.menus.dashboard.powermenu.sleep, title: 'Sleep Command', type: 'string' }), - + Header('Controls'), + Option({ opt: options.menus.dashboard.controls.enabled, title: 'Enabled', type: 'boolean' }), Header('Resource Usage Metrics'), + Option({ opt: options.menus.dashboard.stats.enabled, title: 'Enabled', type: 'boolean' }), Option({ opt: options.menus.dashboard.stats.enable_gpu, title: 'Track GPU', subtitle: "NOTE: This is currently only available for NVidia GPUs and requires 'python-gpustat'.", type: 'boolean', }), - Header('Shortcuts'), + Option({ opt: options.menus.dashboard.shortcuts.enabled, title: 'Enabled', type: 'boolean' }), Option({ opt: options.menus.dashboard.shortcuts.left.shortcut1.icon, title: 'Left - Shortcut 1 (Icon)', From 3cae0e1fae24b47e644bf8e3e099220eb3ba5b8f Mon Sep 17 00:00:00 2001 From: Jas Singh Date: Sun, 20 Oct 2024 17:13:53 -0700 Subject: [PATCH 04/10] Added support for special characters in path for images. (#347) --- widget/settings/shared/components/image.ts | 34 +++++++++++++++++----- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/widget/settings/shared/components/image.ts b/widget/settings/shared/components/image.ts index 94f838a..1906004 100644 --- a/widget/settings/shared/components/image.ts +++ b/widget/settings/shared/components/image.ts @@ -1,11 +1,31 @@ import { Opt } from 'lib/option'; -import { Attribute, BoxWidget } from 'lib/types/widget'; +import { Attribute, BoxWidget, Child } from 'lib/types/widget'; +import FileChooserButton from 'types/widgets/filechooserbutton'; export const imageInputter = (self: BoxWidget, opt: Opt): Attribute => { - return (self.child = Widget.FileChooserButton({ - class_name: 'image-chooser', - on_file_set: ({ uri }) => { - opt.value = uri!.replace('file://', '') as T; - }, - })); + self.child = createFileChooserButton(opt); + return self.child; }; + +const createFileChooserButton = (opt: Opt): FileChooserButton => { + return Widget.FileChooserButton({ + class_name: 'image-chooser', + on_file_set: handleFileSet(opt), + }); +}; + +const handleFileSet = + (opt: Opt) => + ({ uri }: { uri: string | null }): void => { + if (!uri) { + console.warn('No URI selected'); + return; + } + + try { + const decodedPath = decodeURIComponent(uri.replace('file://', '')); + opt.value = decodedPath as T; + } catch (error) { + console.error('Failed to decode URI:', error); + } + }; From 2126cf0657fe61371d0a2cdeedd44b89a0460737 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 14:15:53 +0545 Subject: [PATCH 05/10] feat: add wifi toggle slider (#348) * feat: add wifi toggle slider * Added styling options for the network switch --------- Co-authored-by: Jas Singh --- modules/menus/network/wifi/index.ts | 9 + options.ts | 5 + scss/style/menus/network.scss | 271 +++++++++++-------- widget/settings/pages/theme/menus/network.ts | 13 + 4 files changed, 181 insertions(+), 117 deletions(-) diff --git a/modules/menus/network/wifi/index.ts b/modules/menus/network/wifi/index.ts index dc583fc..57948f6 100644 --- a/modules/menus/network/wifi/index.ts +++ b/modules/menus/network/wifi/index.ts @@ -31,6 +31,15 @@ const Wifi = (): BoxWidget => { hpack: 'start', label: 'Wi-Fi', }), + Widget.Switch({ + class_name: 'menu-switch network', + vpack: 'center', + tooltip_text: 'Toggle Wifi', + active: network.wifi.enabled, + on_activate: () => { + network.toggleWifi(); + }, + }), Widget.Button({ vpack: 'center', hpack: 'end', diff --git a/options.ts b/options.ts index e6a1cfd..a79f7cc 100644 --- a/options.ts +++ b/options.ts @@ -528,6 +528,11 @@ const options = mkOptions(OPTIONS, { passive: opt(colors.text), active: opt(colors.mauve), }, + switch: { + enabled: opt(colors.mauve), + disabled: opt(tertiary_colors.surface0), + puck: opt(secondary_colors.surface1), + }, }, bluetooth: { scaling: opt(100), diff --git a/scss/style/menus/network.scss b/scss/style/menus/network.scss index 0fc10d7..b76bee1 100644 --- a/scss/style/menus/network.scss +++ b/scss/style/menus/network.scss @@ -1,147 +1,184 @@ .menu-items-container.network * { - font-size: $font-size * $bar-menus-menu-network-scaling * 0.01; + font-size: $font-size * $bar-menus-menu-network-scaling * 0.01; } -@import "./menu.scss"; +@import './menu.scss'; .menu-items.network { - background: if($bar-menus-monochrome, $bar-menus-background, $bar-menus-menu-network-background-color); - border-color: if($bar-menus-monochrome, $bar-menus-border-color, $bar-menus-menu-network-border-color); - opacity: $bar-menus-opacity * 0.01; - font-size: $font-size * $bar-menus-menu-network-scaling * 0.01; + background: if($bar-menus-monochrome, $bar-menus-background, $bar-menus-menu-network-background-color); + border-color: if($bar-menus-monochrome, $bar-menus-border-color, $bar-menus-menu-network-border-color); + opacity: $bar-menus-opacity * 0.01; + font-size: $font-size * $bar-menus-menu-network-scaling * 0.01; } .menu-items-container.network { - min-width: 18em * $bar-menus-menu-network-scaling * 0.01; - font-size: 1.3em; - - .menu-items-section { - padding-bottom: 1.5em; - } - - .menu-label { - color: if($bar-menus-monochrome, $bar-menus-label, $bar-menus-menu-network-label-color); - } - - .network-icon { + min-width: 18em * $bar-menus-menu-network-scaling * 0.01; font-size: 1.3em; - min-width: 1em; - min-height: 1em; - color: if($bar-menus-monochrome, $bar-menus-icons-passive, $bar-menus-menu-network-icons-passive); - - &.active { - color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-network-icons-active); - } - } - - .menu-icon-button.network { - margin: 1em; - } - - .connection-container { - margin-left: 1em; - } - - .connection-status.dim { - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); - opacity: 0.5; - font-size: 0.9em; - } - - .menu-section-container.wifi { - margin-top: 0.65em; .menu-items-section { - min-height: 12em; - } - } - - .network-element-item { - &:not(:last-child) { - margin-bottom: 0.5em; + padding-bottom: 1.5em; } - &.staging { - margin-bottom: 0.5em; + .menu-label { + color: if($bar-menus-monochrome, $bar-menus-label, $bar-menus-menu-network-label-color); } - &:hover { - .network-icon { - color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-network-icons-active); - opacity: 1; - } + .network-icon { + font-size: 1.3em; + min-width: 1em; + min-height: 1em; + color: if($bar-menus-monochrome, $bar-menus-icons-passive, $bar-menus-menu-network-icons-passive); - .active-connection { + &.active { + color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-network-icons-active); + } + } + + .menu-icon-button.network { + margin: 1em; + } + + .connection-container { + margin-left: 1em; + } + + .connection-status.dim { + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + opacity: 0.5; + font-size: 0.9em; + } + + .menu-section-container.wifi { + margin-top: 0.65em; + + .menu-items-section { + min-height: 12em; + } + } + + .network-element-item { + &:not(:last-child) { + margin-bottom: 0.5em; + } + + &.staging { + margin-bottom: 0.5em; + } + + &:hover { + .network-icon { + color: if($bar-menus-monochrome, $bar-menus-icons-active, $bar-menus-menu-network-icons-active); + opacity: 1; + } + + .active-connection { + color: if( + $bar-menus-monochrome, + $bar-menus-iconbuttons-active, + $bar-menus-menu-network-iconbuttons-active + ); + } + } + + .active-connection { + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + } + + .active-connection.dim { + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + opacity: 0.5; + } + } + + .spinner.wap { color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); - } } - .active-connection { - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + .network-password-input-container { + background: darken(if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color), 5%); + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + border-radius: 0.4em; + margin: 0em 2em; + margin-top: 0.75em; + padding: 0.5em; } - .active-connection.dim { - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); - opacity: 0.5; - } - } + .close-network-password-input-button { + padding: 0em 0.5em; - .spinner.wap { - color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); - } - - .network-password-input-container { - background: darken(if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color), 5%); - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); - border-radius: 0.4em; - margin: 0em 2em; - margin-top: 0.75em; - padding: 0.5em; - } - - .close-network-password-input-button { - padding: 0em 0.5em; - - &:hover image { - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); - opacity: 0.5; - } - } - - .menu-icon-button.network.search { - color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-network-iconbuttons-passive); - - &:hover { - color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); - } - } - - .menu-icon-button.network.disconnect { - color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-network-iconbuttons-passive); - margin: 0em; - margin-top: -0.2em; - margin-left: 1em; - - label { - font-size: 1.4em; + &:hover image { + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + opacity: 0.5; + } } - &:hover { - color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); + .menu-icon-button.network.search { + color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-network-iconbuttons-passive); + + &:hover { + color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); + } } - } - .waps-not-found.dim { - color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); - opacity: 0.5; - } + .menu-icon-button.network.disconnect { + color: if($bar-menus-monochrome, $bar-menus-iconbuttons-passive, $bar-menus-menu-network-iconbuttons-passive); + margin: 0em; + margin-top: -0.2em; + margin-left: 1em; - .menu-label-container { - background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color); - } + label { + font-size: 1.4em; + } + &:hover { + color: if($bar-menus-monochrome, $bar-menus-iconbuttons-active, $bar-menus-menu-network-iconbuttons-active); + } + } - .menu-items-section { - background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color); - } + .waps-not-found.dim { + color: if($bar-menus-monochrome, $bar-menus-text, $bar-menus-menu-network-text); + opacity: 0.5; + } + + .menu-label-container { + background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color); + } + + .menu-items-section { + background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-network-card-color); + } + + .menu-switch.network { + background-color: if( + $bar-menus-monochrome, + $bar-menus-switch-disabled, + $bar-menus-menu-network-switch-disabled + ); + + &:checked { + background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-network-switch-enabled); + } + + slider { + background-color: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-network-switch-puck); + } + + &:hover { + trough { + background: if( + $bar-menus-monochrome, + $bar-menus-switch-disabled, + $bar-menus-menu-network-switch-disabled + ); + } + + slider { + background: if($bar-menus-monochrome, $bar-menus-switch-puck, $bar-menus-menu-network-switch-puck); + } + } + + &:active { + background: if($bar-menus-monochrome, $bar-menus-switch-enabled, $bar-menus-menu-network-switch-enabled); + } + } } diff --git a/widget/settings/pages/theme/menus/network.ts b/widget/settings/pages/theme/menus/network.ts index da52e8c..b06dfc5 100644 --- a/widget/settings/pages/theme/menus/network.ts +++ b/widget/settings/pages/theme/menus/network.ts @@ -40,6 +40,19 @@ export const NetworkMenuTheme = (): Scrollable => { type: 'color', }), + Header('Switch'), + Option({ + opt: options.theme.bar.menus.menu.network.switch.enabled, + title: 'Enabled', + type: 'color', + }), + Option({ + opt: options.theme.bar.menus.menu.network.switch.disabled, + title: 'Disabled', + type: 'color', + }), + Option({ opt: options.theme.bar.menus.menu.network.switch.puck, title: 'Puck', type: 'color' }), + Header('List Items'), Option({ opt: options.theme.bar.menus.menu.network.listitems.active, From ca664e3e7899226575484f7e873194434c7066fc Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 14:29:36 +0545 Subject: [PATCH 06/10] feat: add uptime on power profile (#349) * feat: add uptime on power profile * feat: add uptime on power profile * feat: add uptime on power profile * feat: add uptime on power profile * Update modules/menus/energy/profiles/index.ts Co-authored-by: Jas Singh * Update modules/menus/energy/profiles/index.ts Co-authored-by: Jas Singh * Update modules/menus/energy/profiles/index.ts * Update modules/menus/energy/profiles/index.ts --------- Co-authored-by: Jas Singh --- modules/menus/energy/profiles/index.ts | 29 +++++++++++++++++++------- scss/style/menus/energy.scss | 3 +++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/modules/menus/energy/profiles/index.ts b/modules/menus/energy/profiles/index.ts index f06dd73..72b2824 100644 --- a/modules/menus/energy/profiles/index.ts +++ b/modules/menus/energy/profiles/index.ts @@ -1,12 +1,20 @@ const powerProfiles = await Service.import('powerprofiles'); import { PowerProfile, PowerProfileObject, PowerProfiles } from 'lib/types/powerprofiles.js'; -import icons from '../../../icons/index.js'; import { BoxWidget } from 'lib/types/widget.js'; +import icons from '../../../icons/index.js'; +import { uptime } from 'lib/variables.js'; const EnergyProfiles = (): BoxWidget => { const isValidProfile = (profile: string): profile is PowerProfile => profile === 'power-saver' || profile === 'balanced' || profile === 'performance'; + function renderUptime(curUptime: number): string { + const days = Math.floor(curUptime / (60 * 24)); + const hours = Math.floor((curUptime % (60 * 24)) / 60); + const minutes = Math.floor(curUptime % 60); + return ` : ${days}d ${hours}h ${minutes}m`; + } + return Widget.Box({ class_name: 'menu-section-container energy', vertical: true, @@ -14,12 +22,19 @@ const EnergyProfiles = (): BoxWidget => { Widget.Box({ class_name: 'menu-label-container', hpack: 'fill', - child: Widget.Label({ - class_name: 'menu-label', - hexpand: true, - hpack: 'start', - label: 'Power Profile', - }), + children: [ + Widget.Label({ + class_name: 'menu-label', + hexpand: true, + hpack: 'start', + label: 'Power Profile', + }), + Widget.Label({ + class_name: 'menu-label uptime', + label: uptime.bind().as(renderUptime), + tooltipText: 'Uptime', + }), + ], }), Widget.Box({ class_name: 'menu-items-section', diff --git a/scss/style/menus/energy.scss b/scss/style/menus/energy.scss index a798b2a..45648f3 100644 --- a/scss/style/menus/energy.scss +++ b/scss/style/menus/energy.scss @@ -22,6 +22,9 @@ background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-battery-card-color); } + .uptime { + font-size: 0.92em; + } .menu-items-section { background: if($bar-menus-monochrome, $bar-menus-cards, $bar-menus-menu-battery-card-color); From c265697adc1a812dcf4cbb5abc34fcb4554021c1 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 14:31:47 +0545 Subject: [PATCH 07/10] feat: add option to hide label when battery is full (#350) * feat: add option to hide label when battery is full * feat: add option to hide label when battery is full * feat: add option to hide label when battery is full * Update modules/bar/battery/index.ts Co-authored-by: Jas Singh * fix: battery css --------- Co-authored-by: Jas Singh --- modules/bar/battery/index.ts | 60 ++++++++++++++--------- options.ts | 1 + scss/style/bar/battery.scss | 5 ++ widget/settings/pages/config/bar/index.ts | 5 ++ 4 files changed, 47 insertions(+), 24 deletions(-) diff --git a/modules/bar/battery/index.ts b/modules/bar/battery/index.ts index 42e9980..8d22ef7 100644 --- a/modules/bar/battery/index.ts +++ b/modules/bar/battery/index.ts @@ -7,7 +7,7 @@ import Button from 'types/widgets/button.js'; import { Attribute, Child } from 'lib/types/widget.js'; import { runAsyncCommand, throttledScrollHandler } from 'customModules/utils.js'; -const { label: show_label, rightClick, middleClick, scrollUp, scrollDown } = options.bar.battery; +const { label: show_label, rightClick, middleClick, scrollUp, scrollDown, hideLabelWhenFull } = options.bar.battery; const BatteryLabel = (): BarBoxChild => { const isVis = Variable(battery.available); @@ -59,29 +59,41 @@ const BatteryLabel = (): BarBoxChild => { ), visible: battery.bind('available'), tooltip_text: battery.bind('time_remaining').as((t) => t.toString()), - children: Utils.merge([battery.bind('available'), show_label.bind('value')], (batAvail, showLabel) => { - if (batAvail && showLabel) { - return [ - Widget.Icon({ - class_name: 'bar-button-icon battery', - icon: batIcon, - }), - Widget.Label({ - class_name: 'bar-button-label battery', - label: battery.bind('percent').as((p) => `${Math.floor(p)}%`), - }), - ]; - } else if (batAvail && !showLabel) { - return [ - Widget.Icon({ - class_name: 'bar-button-icon battery', - icon: batIcon, - }), - ]; - } else { - return []; - } - }), + children: Utils.merge( + [ + battery.bind('available'), + show_label.bind('value'), + battery.bind('charged'), + hideLabelWhenFull.bind('value'), + ], + (batAvail, showLabel, isCharged, hideWhenFull) => { + if (batAvail && showLabel) { + return [ + Widget.Icon({ + class_name: 'bar-button-icon battery', + icon: batIcon, + }), + ...(hideWhenFull && isCharged + ? [] + : [ + Widget.Label({ + class_name: 'bar-button-label battery', + label: battery.bind('percent').as((p) => `${Math.floor(p)}%`), + }), + ]), + ]; + } else if (batAvail && !showLabel) { + return [ + Widget.Icon({ + class_name: 'bar-button-icon battery', + icon: batIcon, + }), + ]; + } else { + return []; + } + }, + ), setup: (self) => { self.hook(battery, () => { if (battery.available) { diff --git a/options.ts b/options.ts index a79f7cc..d763510 100644 --- a/options.ts +++ b/options.ts @@ -912,6 +912,7 @@ const options = mkOptions(OPTIONS, { }, battery: { label: opt(true), + hideLabelWhenFull: opt(false), rightClick: opt(''), middleClick: opt(''), scrollUp: opt(''), diff --git a/scss/style/bar/battery.scss b/scss/style/bar/battery.scss index 7f1df89..f1b449a 100644 --- a/scss/style/bar/battery.scss +++ b/scss/style/bar/battery.scss @@ -25,6 +25,10 @@ $bar-buttons-radius * 0.4, $bar-buttons-radius ); + + &:last-child { + border-radius: $bar-buttons-radius; + } } .bar-button-label.battery { @@ -56,3 +60,4 @@ 0em ); } + diff --git a/widget/settings/pages/config/bar/index.ts b/widget/settings/pages/config/bar/index.ts index 713679d..00a2408 100644 --- a/widget/settings/pages/config/bar/index.ts +++ b/widget/settings/pages/config/bar/index.ts @@ -559,6 +559,11 @@ export const BarSettings = (): Scrollable => { title: 'Show Battery Percentage', type: 'boolean', }), + Option({ + opt: options.bar.battery.hideLabelWhenFull, + title: 'Hide Battery Percentage When Full', + type: 'boolean', + }), Option({ opt: options.theme.bar.buttons.battery.spacing, title: 'Inner Spacing', From 604f73718220f83db8a00215267a578610042e07 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 14:34:25 +0545 Subject: [PATCH 08/10] feature: hide notifications count when 0 (#338) * fix: hide notifications count when 0 * feat: add settings to control earlier behavious * fix: lints and formatting * Update widget/settings/pages/config/bar/index.ts Co-authored-by: Jas Singh * fix: notifications css * Update modules/bar/notifications/index.ts --------- Co-authored-by: Jas Singh --- modules/bar/notifications/index.ts | 15 ++++++++++++--- options.ts | 1 + scss/style/bar/notifications.scss | 4 ++++ widget/settings/pages/config/bar/index.ts | 6 ++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/modules/bar/notifications/index.ts b/modules/bar/notifications/index.ts index 818f4ed..f0e721d 100644 --- a/modules/bar/notifications/index.ts +++ b/modules/bar/notifications/index.ts @@ -7,7 +7,7 @@ import Button from 'types/widgets/button.js'; import { Attribute, Child } from 'lib/types/widget.js'; import { runAsyncCommand, throttledScrollHandler } from 'customModules/utils.js'; -const { show_total, rightClick, middleClick, scrollUp, scrollDown } = options.bar.notifications; +const { show_total, rightClick, middleClick, scrollUp, scrollDown, hideCountWhenZero } = options.bar.notifications; const { ignore } = options.notifications; const notifs = await Service.import('notifications'); @@ -32,8 +32,14 @@ export const Notifications = (): BarBoxChild => { hpack: 'start', class_name: 'bar-notifications', children: Utils.merge( - [notifs.bind('notifications'), notifs.bind('dnd'), show_total.bind('value'), ignore.bind('value')], - (notif, dnd, showTotal, ignoredNotifs) => { + [ + notifs.bind('notifications'), + notifs.bind('dnd'), + show_total.bind('value'), + ignore.bind('value'), + hideCountWhenZero.bind('value'), + ], + (notif, dnd, showTotal, ignoredNotifs, hideCountForZero) => { const filteredNotifications = filterNotifications(notif, ignoredNotifs); const notifIcon = Widget.Label({ @@ -49,6 +55,9 @@ export const Notifications = (): BarBoxChild => { }); if (showTotal) { + if (hideCountForZero && filteredNotifications.length === 0) { + return [notifIcon]; + } return [notifIcon, notifLabel]; } return [notifIcon]; diff --git a/options.ts b/options.ts index d763510..33142b6 100644 --- a/options.ts +++ b/options.ts @@ -942,6 +942,7 @@ const options = mkOptions(OPTIONS, { }, notifications: { show_total: opt(false), + hideCountWhenZero: opt(false), rightClick: opt(''), middleClick: opt(''), scrollUp: opt(''), diff --git a/scss/style/bar/notifications.scss b/scss/style/bar/notifications.scss index edf9147..5818a26 100644 --- a/scss/style/bar/notifications.scss +++ b/scss/style/bar/notifications.scss @@ -28,6 +28,10 @@ $bar-buttons-radius ); color: if($bar-buttons-monochrome, $bar-buttons-icon, $bar-buttons-notifications-icon); + + &:last-child { + border-radius: $bar-buttons-radius; + } } .bar-button-label.notifications { diff --git a/widget/settings/pages/config/bar/index.ts b/widget/settings/pages/config/bar/index.ts index 00a2408..f713739 100644 --- a/widget/settings/pages/config/bar/index.ts +++ b/widget/settings/pages/config/bar/index.ts @@ -743,6 +743,12 @@ export const BarSettings = (): Scrollable => { title: 'Show Total # of notifications', type: 'boolean', }), + Option({ + opt: options.bar.notifications.hideCountWhenZero, + title: 'Auto Hide Label', + subtitle: 'Hide Total # of notifications when zero', + type: 'boolean', + }), Option({ opt: options.theme.bar.buttons.notifications.spacing, title: 'Inner Spacing', From 3bc8c0d2e117c1ed010f521d2c3431fe5892ea29 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Mon, 21 Oct 2024 14:35:49 +0545 Subject: [PATCH 09/10] feature: remove delay when clearing all notifications (#342) * feat: add setting option to control delay * Update widget/settings/pages/config/notifications/index.ts * Update widget/settings/pages/config/notifications/index.ts * Update widget/settings/pages/config/notifications/index.ts --------- Co-authored-by: Jas Singh --- globals/notification.ts | 4 ++-- modules/menus/notifications/controls/index.ts | 17 +++++++++++------ options.ts | 1 + .../pages/config/notifications/index.ts | 9 +++++++++ 4 files changed, 23 insertions(+), 8 deletions(-) diff --git a/globals/notification.ts b/globals/notification.ts index 1564029..f382bc4 100644 --- a/globals/notification.ts +++ b/globals/notification.ts @@ -25,11 +25,11 @@ export const getNotificationIcon = (app_name: string, app_icon: string, app_entr return icon; }; -export const closeNotifications = async (notifications: Notification[]): Promise => { +export const closeNotifications = async (notifications: Notification[], delay: number): Promise => { removingNotifications.value = true; for (const notif of notifications) { notif.close(); - await new Promise((resolve) => setTimeout(resolve, 100)); + await new Promise((resolve) => setTimeout(resolve, delay)); } removingNotifications.value = false; }; diff --git a/modules/menus/notifications/controls/index.ts b/modules/menus/notifications/controls/index.ts index 467bf00..a2964fd 100644 --- a/modules/menus/notifications/controls/index.ts +++ b/modules/menus/notifications/controls/index.ts @@ -1,6 +1,9 @@ import { closeNotifications } from 'globals/notification'; import { BoxWidget } from 'lib/types/widget'; import { Notifications } from 'types/service/notifications'; +import options from 'options'; + +const { clearDelay } = options.notifications; const Controls = (notifs: Notifications): BoxWidget => { return Widget.Box({ @@ -44,13 +47,15 @@ const Controls = (notifs: Notifications): BoxWidget => { Widget.Button({ className: 'clear-notifications-button', tooltip_text: 'Clear Notifications', - on_primary_click: () => { - if (removingNotifications.value) { - return; - } + on_primary_click: clearDelay.bind('value').as((delay) => { + return () => { + if (removingNotifications.value) { + return; + } - closeNotifications(notifs.notifications); - }, + return closeNotifications(notifs.notifications, delay); + }; + }), child: Widget.Label({ class_name: removingNotifications.bind('value').as((removing: boolean) => { return removing diff --git a/options.ts b/options.ts index 33142b6..8902241 100644 --- a/options.ts +++ b/options.ts @@ -1183,6 +1183,7 @@ const options = mkOptions(OPTIONS, { active_monitor: opt(true), timeout: opt(7000), cache_actions: opt(true), + clearDelay: opt(100), }, dummy: opt(true), diff --git a/widget/settings/pages/config/notifications/index.ts b/widget/settings/pages/config/notifications/index.ts index 3d7925e..4191d4f 100644 --- a/widget/settings/pages/config/notifications/index.ts +++ b/widget/settings/pages/config/notifications/index.ts @@ -45,6 +45,15 @@ export const NotificationSettings = (): Scrollable => { subtitle: 'The notification will follow the monitor of your cursor', type: 'boolean', }), + Option({ + opt: options.notifications.clearDelay, + title: 'Clear Delay', + subtitle: + 'The delay in milliseconds before a notification is cleared' + + '\nWARNING: Setting this value too low may crash AGS depending on your system.', + type: 'number', + increment: 20, + }), Option({ opt: options.notifications.timeout, title: 'Notification Timeout', From 7c06b3e0f086f06b0e49f84d54c3e27247ac9b91 Mon Sep 17 00:00:00 2001 From: Rubin Bhandari Date: Tue, 22 Oct 2024 13:39:15 +0545 Subject: [PATCH 10/10] feat: allow custom icons on custom modules (#351) * feat: allow custom icons on custom modules * Update options.ts * Update customModules/config.ts --------- Co-authored-by: Jas Singh --- customModules/config.ts | 27 ++++++++++++++++----------- customModules/cpu/index.ts | 4 ++-- customModules/ram/index.ts | 5 +++-- lib/types/bar.d.ts | 5 ----- lib/types/customModules/kbLayout.d.ts | 1 - options.ts | 24 +++++++++--------------- 6 files changed, 30 insertions(+), 36 deletions(-) diff --git a/customModules/config.ts b/customModules/config.ts index 71edca8..36e2c4c 100644 --- a/customModules/config.ts +++ b/customModules/config.ts @@ -37,6 +37,11 @@ export const CustomModuleSettings = (): Scrollable => title: 'Button Border', type: 'boolean', }), + Option({ + opt: options.bar.customModules.ram.icon, + title: 'Ram Icon', + type: 'string', + }), Option({ opt: options.bar.customModules.ram.label, title: 'Show Label', @@ -93,6 +98,11 @@ export const CustomModuleSettings = (): Scrollable => title: 'Button Border', type: 'boolean', }), + Option({ + opt: options.bar.customModules.cpu.icon, + title: 'Cpu Icon', + type: 'string', + }), Option({ opt: options.bar.customModules.cpu.label, title: 'Show Label', @@ -156,8 +166,7 @@ export const CustomModuleSettings = (): Scrollable => Option({ opt: options.bar.customModules.storage.icon, title: 'Storage Icon', - type: 'enum', - enums: ['󰋊', '', '󱛟', '', '', ''], + type: 'string', }), Option({ opt: options.bar.customModules.storage.label, @@ -225,8 +234,7 @@ export const CustomModuleSettings = (): Scrollable => Option({ opt: options.bar.customModules.netstat.icon, title: 'Netstat Icon', - type: 'enum', - enums: ['󰖟', '󰇚', '󰕒', '󰛳', '', '󰣺', '󰖩', '', '󰈀'], + type: 'string', }), Option({ opt: options.bar.customModules.netstat.label, @@ -292,9 +300,8 @@ export const CustomModuleSettings = (): Scrollable => }), Option({ opt: options.bar.customModules.kbLayout.icon, - title: 'kbLayout Icon', - type: 'enum', - enums: ['', '󰌌', '', '󰬴', '󰗊'], + title: 'Keyboard Layout Icon', + type: 'string', }), Option({ opt: options.bar.customModules.kbLayout.label, @@ -357,8 +364,7 @@ export const CustomModuleSettings = (): Scrollable => Option({ opt: options.bar.customModules.updates.icon, title: 'Updates Icon', - type: 'enum', - enums: ['󰚰', '󰇚', '', '󱑢', '󱑣', '󰏖', '', '󰏔', '󰏗'], + type: 'string', }), Option({ opt: options.bar.customModules.updates.label, @@ -557,8 +563,7 @@ export const CustomModuleSettings = (): Scrollable => Option({ opt: options.bar.customModules.power.icon, title: 'Power Button Icon', - type: 'enum', - enums: ['', '', '󰍃', '󰿅', '󰒲', '󰤄'], + type: 'string', }), Option({ opt: options.bar.customModules.power.leftClick, diff --git a/customModules/cpu/index.ts b/customModules/cpu/index.ts index 73f96ed..a3848e4 100644 --- a/customModules/cpu/index.ts +++ b/customModules/cpu/index.ts @@ -13,7 +13,7 @@ import { BarBoxChild } from 'lib/types/bar'; import { Attribute, Child } from 'lib/types/widget'; // All the user configurable options for the cpu module that are needed -const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval } = +const { label, round, leftClick, rightClick, middleClick, scrollUp, scrollDown, pollingInterval, icon } = options.bar.customModules.cpu; export const cpuUsage = Variable(0); @@ -35,7 +35,7 @@ export const Cpu = (): BarBoxChild => { }; const cpuModule = module({ - textIcon: '', + textIcon: icon.bind('value'), label: Utils.merge([cpuUsage.bind('value'), round.bind('value')], (cpuUsg, rnd) => { return renderLabel(cpuUsg, rnd); }), diff --git a/customModules/ram/index.ts b/customModules/ram/index.ts index c78d8f5..b651aaa 100644 --- a/customModules/ram/index.ts +++ b/customModules/ram/index.ts @@ -20,7 +20,8 @@ import { pollVariable } from 'customModules/PollVar'; import { Attribute, Child } from 'lib/types/widget'; // All the user configurable options for the ram module that are needed -const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval } = options.bar.customModules.ram; +const { label, labelType, round, leftClick, rightClick, middleClick, pollingInterval, icon } = + options.bar.customModules.ram; const defaultRamData: GenericResourceData = { total: 0, used: 0, percentage: 0, free: 0 }; const ramUsage = Variable(defaultRamData); @@ -29,7 +30,7 @@ pollVariable(ramUsage, [round.bind('value')], pollingInterval.bind('value'), cal export const Ram = (): BarBoxChild => { const ramModule = module({ - textIcon: '', + textIcon: icon.bind('value'), label: Utils.merge( [ramUsage.bind('value'), labelType.bind('value'), round.bind('value')], (rmUsg: GenericResourceData, lblTyp: ResourceLabelType, round: boolean) => { diff --git a/lib/types/bar.d.ts b/lib/types/bar.d.ts index 13033d4..99066d8 100644 --- a/lib/types/bar.d.ts +++ b/lib/types/bar.d.ts @@ -36,12 +36,7 @@ export type Module = { export type ResourceLabelType = 'used/total' | 'used' | 'percentage' | 'free'; -export type StorageIcon = '󰋊' | '' | '󱛟' | '' | '' | ''; - -export type NetstatIcon = '󰖟' | '󰇚' | '󰕒' | '󰛳' | '' | '󰣺' | '󰖩' | '' | '󰈀'; export type NetstatLabelType = 'full' | 'in' | 'out'; export type RateUnit = 'GiB' | 'MiB' | 'KiB' | 'auto'; -export type UpdatesIcon = '󰚰' | '󰇚' | '' | '󱑢' | '󱑣' | '󰏖' | '' | '󰏔' | '󰏗'; -export type PowerIcon = '' | '' | '󰍃' | '󰿅' | '󰒲' | '󰤄'; diff --git a/lib/types/customModules/kbLayout.d.ts b/lib/types/customModules/kbLayout.d.ts index 93ecea4..b287e06 100644 --- a/lib/types/customModules/kbLayout.d.ts +++ b/lib/types/customModules/kbLayout.d.ts @@ -1,7 +1,6 @@ import { layoutMap } from 'customModules/kblayout/layouts'; export type KbLabelType = 'layout' | 'code'; -export type KbIcon = '' | '󰌌' | '' | '󰬴' | '󰗊'; export type HyprctlKeyboard = { address: string; diff --git a/options.ts b/options.ts index 8902241..24c854c 100644 --- a/options.ts +++ b/options.ts @@ -1,14 +1,6 @@ import { opt, mkOptions } from 'lib/option'; -import { - NetstatIcon, - NetstatLabelType, - PowerIcon, - RateUnit, - ResourceLabelType, - StorageIcon, - UpdatesIcon, -} from 'lib/types/bar'; -import { KbIcon, KbLabelType } from 'lib/types/customModules/kbLayout'; +import { NetstatLabelType, RateUnit, ResourceLabelType } from 'lib/types/bar'; +import { KbLabelType } from 'lib/types/customModules/kbLayout'; import { ActiveWsIndicator, BarButtonStyles, @@ -951,6 +943,7 @@ const options = mkOptions(OPTIONS, { customModules: { scrollSpeed: opt(5), ram: { + icon: opt(''), label: opt(true), labelType: opt('percentage'), round: opt(true), @@ -960,6 +953,7 @@ const options = mkOptions(OPTIONS, { middleClick: opt(''), }, cpu: { + icon: opt(''), label: opt(true), round: opt(true), pollingInterval: opt(2000), @@ -971,7 +965,7 @@ const options = mkOptions(OPTIONS, { }, storage: { label: opt(true), - icon: opt('󰋊'), + icon: opt('󰋊'), round: opt(false), labelType: opt('percentage'), pollingInterval: opt(2000), @@ -982,7 +976,7 @@ const options = mkOptions(OPTIONS, { netstat: { label: opt(true), networkInterface: opt(''), - icon: opt('󰖟'), + icon: opt('󰖟'), round: opt(true), labelType: opt('full'), rateUnit: opt('auto'), @@ -994,7 +988,7 @@ const options = mkOptions(OPTIONS, { kbLayout: { label: opt(true), labelType: opt('code'), - icon: opt('󰌌'), + icon: opt('󰌌'), leftClick: opt(''), rightClick: opt(''), middleClick: opt(''), @@ -1005,7 +999,7 @@ const options = mkOptions(OPTIONS, { updateCommand: opt('$HOME/.config/ags/scripts/checkUpdates.sh -arch'), label: opt(true), padZero: opt(true), - icon: opt('󰏖'), + icon: opt('󰏖'), pollingInterval: opt(1000 * 60 * 60 * 6), leftClick: opt(''), rightClick: opt(''), @@ -1036,7 +1030,7 @@ const options = mkOptions(OPTIONS, { scrollDown: opt(''), }, power: { - icon: opt(''), + icon: opt(''), showLabel: opt(true), leftClick: opt('menu:powerdropdown'), rightClick: opt(''),