summaryrefslogtreecommitdiff
path: root/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js
diff options
context:
space:
mode:
authorAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
committerAlexanderCurl <alexc@alexc.hu>2026-04-18 17:46:06 +0100
commit70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch)
treeab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js
parent5d94c0a7d44a2255b81815a52a7056a94a39842d (diff)
downloadRaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.tar.gz
RaveOS-PKGBUILD-70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69.zip
Replaced file structures for themes in the correct format
Diffstat (limited to 'raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js')
-rw-r--r--raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js573
1 files changed, 0 insertions, 573 deletions
diff --git a/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js b/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js
deleted file mode 100644
index 3a80198..0000000
--- a/raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js
+++ /dev/null
@@ -1,573 +0,0 @@
-// SPDX-FileCopyrightText: 2023 Deminder <tremminder@gmail.com>
-// SPDX-License-Identifier: GPL-3.0-or-later
-
-import GObject from 'gi://GObject';
-import St from 'gi://St';
-import Gio from 'gi://Gio';
-import Clutter from 'gi://Clutter';
-import * as Main from 'resource:///org/gnome/shell/ui/main.js';
-import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js';
-import * as Slider from 'resource:///org/gnome/shell/ui/slider.js';
-import * as QuickSettings from 'resource:///org/gnome/shell/ui/quickSettings.js';
-
-import { InfoFetcher } from './info-fetcher.js';
-import { Textbox } from './text-box.js';
-import { gettext as _, ngettext as _n, pgettext as C_ } from './translation.js';
-import * as SessionModeAware from './session-mode-aware.js';
-import { getShutdownScheduleFromSettings } from './schedule-info.js';
-import {
- ShutdownTimerName,
- ShutdownTimerObjectPath,
-} from '../dbus-service/shutdown-timer-dbus.js';
-
-import {
- foregroundActive,
- observeForegroundActive,
- unobserveForegroundActive,
-} from './session-mode-aware.js';
-import {
- durationString,
- longDurationString,
- absoluteTimeString,
- getSliderMinutesFromSettings,
- ScheduleInfo,
-} from './schedule-info.js';
-
-import { logDebug, proxyPromise } from './util.js';
-import {
- WAKE_ACTIONS,
- actionLabel,
- ACTIONS,
- mapLegacyAction,
-} from '../dbus-service/action.js';
-
-/**
- * The ShutdownTimerItem controls wake/shutdown action time and mode.
- * Additionally, it shows wake and external/internal shutdown schedules.
- *
- * The external schedule of the `shutdown` command is fetched by the InfoFetcher.
- * Note that there is no external schedule for `suspend`.
- */
-const ShutdownTimerItem = GObject.registerClass(
- {
- Properties: {
- 'shutdown-text': GObject.ParamSpec.string(
- 'shutdown-text',
- '',
- '',
- GObject.ParamFlags.READWRITE,
- ''
- ),
- 'indicator-icon-name': GObject.ParamSpec.string(
- 'indicator-icon-name',
- '',
- '',
- GObject.ParamFlags.READWRITE,
- 'go-down-symbolic'
- ),
- },
- Signals: {
- 'open-preferences': {},
- shutdown: {
- param_types: [GObject.TYPE_BOOLEAN, GObject.TYPE_STRING],
- },
- wake: {
- param_types: [GObject.TYPE_BOOLEAN],
- },
- },
- },
- class ShutdownTimerItem extends QuickSettings.QuickMenuToggle {
- _init({ path, settings }) {
- const gicon = Gio.icon_new_for_string(
- `${path}/icons/shutdown-timer-symbolic.svg`
- );
- super._init({ gicon, accessible_name: _('Shutdown Timer') });
- this.info = {
- internalShutdown: getShutdownScheduleFromSettings(settings),
- externalShutdown: new ScheduleInfo({ external: true }),
- externalWake: new ScheduleInfo({ mode: 'wake' }),
- state: 'inactive',
- };
- this._settings = settings;
- this.shutdownTimerIcon = gicon;
- this._updatingSwitcherState = false;
-
- // submenu in status area menu with slider and toggle button
- this.sliderItems = {};
- this.sliders = {};
- ['shutdown', 'wake'].forEach(prefix => {
- const [item, slider] = this._createSliderItem(prefix);
- this.sliderItems[prefix] = item;
- this.sliders[prefix] = slider;
- this._onShowSliderChanged(prefix);
- });
- this.switcher = new PopupMenu.PopupSwitchMenuItem('', false);
- // start/stop shutdown timer
- this.switcher.connect('toggled', () => {
- if (!this._updatingSwitcherState) {
- this.emit(
- 'shutdown',
- this.switcher.state,
- this.info.internalShutdown.mode
- );
- }
- });
- this.switcherSettingsButton = new St.Button({
- reactive: true,
- can_focus: true,
- track_hover: true,
- accessible_name: _('Settings'),
- style_class: 'icon-button settings-button',
- });
- this.switcherSettingsButton.child = new St.Icon({
- icon_name: 'applications-system-symbolic',
- });
- this.switcherSettingsButton.connect('clicked', () =>
- this.emit('open-preferences')
- );
- this.switcher.add_child(this.switcherSettingsButton);
-
- this.menu.addMenuItem(this.switcher);
- // make switcher toggle without popup menu closing
- this.switcher.activate = __ => {
- if (this.switcher._switch.mapped) {
- this.switcher.toggle();
- }
- };
- this.menu.addMenuItem(this.sliderItems['shutdown']);
-
- this.modeItems = Object.keys(ACTIONS).map(action => {
- const modeItem = new PopupMenu.PopupMenuItem(actionLabel(action));
- modeItem.connect('activate', () => {
- this.emit('shutdown', true, action);
- });
- this.menu.addMenuItem(modeItem);
- return [action, modeItem];
- });
-
- this.wakeItems = [
- new PopupMenu.PopupSeparatorMenuItem(),
- this.sliderItems['wake'],
- ...Object.keys(WAKE_ACTIONS).map(action => {
- const modeItem = new PopupMenu.PopupMenuItem(actionLabel(action));
- if (action === 'wake') {
- this.wakeModeItem = modeItem;
- }
- modeItem.connect('activate', () =>
- this.emit('wake', action === 'wake')
- );
- return modeItem;
- }),
- ];
- this.wakeItems.forEach(item => {
- this.menu.addMenuItem(item);
- });
- this._updateWakeModeItem();
- this._updateSwitchLabel();
-
- // handlers for changed values in settings
- const settingsHandlerIds = [
- [
- [
- 'shutdown-max-timer-value',
- 'nonlinear-shutdown-slider-value',
- 'shutdown-ref-timer-value',
- 'show-shutdown-absolute-timer-value',
- 'root-mode-value',
- 'shutdown-slider-value',
- ],
- () => this._updateSwitchLabel(),
- ],
- [
- [
- 'wake-max-timer-value',
- 'wake-ref-timer-value',
- 'show-wake-absolute-timer-value',
- 'nonlinear-wake-slider-value',
- 'wake-slider-value',
- ],
- () => this._updateWakeModeItem(),
- ],
- [['shutdown-slider-value'], () => this._updateSlider('shutdown')],
- [['wake-slider-value'], () => this._updateSlider('wake')],
- [
- [
- 'show-wake-items-value',
- 'show-shutdown-mode-value',
- 'show-shutdown-slider-value',
- 'show-wake-slider-value',
- 'show-shutdown-indicator-value',
- 'show-settings-value',
- ],
- () => this._sync(),
- ],
- ]
- .flatMap(([names, func]) => names.map(n => [n, func]))
- .map(([name, func]) =>
- this._settings.connect(`changed::${name}`, func)
- );
-
- this.connect('clicked', () => this.switcher.toggle());
- observeForegroundActive(this, () => this._sync());
- const tickHandlerId = setInterval(() => this.updateShutdownInfo(), 1000);
- this.connect('destroy', () => {
- unobserveForegroundActive(this);
- clearInterval(tickHandlerId);
- settingsHandlerIds.forEach(handlerId => {
- this._settings.disconnect(handlerId);
- });
- });
- }
-
- _sync() {
- // Update wake mode items
- this.wakeItems.forEach(item => {
- item.visible = this._settings.get_boolean('show-wake-items-value');
- });
- this._onShowSliderChanged('wake');
-
- // Update shutdown mode items
- const activeActions = this._settings
- .get_string('show-shutdown-mode-value')
- .split(',')
- .map(s => mapLegacyAction(s.trim()))
- .filter(action => action in ACTIONS);
- logDebug('[menu-item]', activeActions);
- this.modeItems.forEach(([action, item]) => {
- const position = activeActions.indexOf(action);
- if (position > -1) {
- this.menu.moveMenuItem(item, position + 2);
- }
- item.visible = position > -1;
- });
-
- this._onShowSliderChanged('shutdown');
-
- this.switcherSettingsButton.visible =
- foregroundActive() && this._settings.get_boolean('show-settings-value');
-
- this.updateShutdownInfo();
- }
-
- updateShutdownInfo() {
- const schedule = this.info.internalShutdown;
- const externalSchedule = this.info.externalShutdown;
- const externalWake = this.info.externalWake;
- const urgendSchedule = externalSchedule.isMoreUrgendThan(schedule)
- ? externalSchedule
- : schedule;
- const active = schedule.scheduled || this.info.state !== 'inactive';
- const showIndicator = this._settings.get_boolean(
- 'show-shutdown-indicator-value'
- );
-
- // Update Indicator
- this.set({
- checked: active,
- shutdownText:
- urgendSchedule.scheduled && showIndicator
- ? urgendSchedule.secondsLeft > 0
- ? durationString(urgendSchedule.secondsLeft)
- : _('now')
- : '',
- indicatorIconName:
- showIndicator &&
- (this.info.internalShutdown.scheduled ||
- this.info.externalShutdown.scheduled)
- ? 'go-down-symbolic'
- : '',
- });
-
- // Update selected shutdown mode
- this.modeItems.forEach(([mode, item]) => {
- item.setOrnament(
- mode === schedule.mode
- ? PopupMenu.Ornament.DOT
- : PopupMenu.Ornament.NONE
- );
- });
-
- // Update title with scheduled action
- this.title = actionLabel(schedule.mode);
-
- // Update toggle state of switcher
- this._updatingSwitcherState = true;
- this.switcher.setToggleState(active);
- this._updatingSwitcherState = false;
-
- // Update long status description in menu
- this.menu.setHeader(
- this.shutdownTimerIcon,
- _('Shutdown Timer'),
- [schedule.label, externalWake.label].filter(v => !!v).join('\n')
- );
- if (this._settings.get_boolean('show-shutdown-absolute-timer-value')) {
- this._updateSwitchLabel();
- }
- if (this._settings.get_boolean('show-wake-absolute-timer-value')) {
- this._updateWakeModeItem();
- }
- this._updateSubtitle();
- }
-
- // update timer value if slider has changed
- _updateSlider(prefix) {
- this.sliders[prefix].value =
- this._settings.get_double(`${prefix}-slider-value`) / 100.0;
- }
-
- _createSliderItem(settingsPrefix) {
- const valueName = `${settingsPrefix}-slider-value`;
- const sliderValue = this._settings.get_double(valueName) / 100.0;
- const item = new PopupMenu.PopupBaseMenuItem({ activate: false });
- const sliderIcon = new St.Icon({
- icon_name:
- settingsPrefix === 'wake'
- ? 'alarm-symbolic'
- : 'system-shutdown-symbolic',
- style_class: 'popup-menu-icon',
- });
- item.add_child(sliderIcon);
- const slider = new Slider.Slider(sliderValue);
- slider.connect('notify::value', () => {
- const v = slider.value * 100;
- if (v !== this._settings.get_double(valueName))
- this._settings.set_double(valueName, v);
- });
- item.add_child(slider);
- return [item, slider];
- }
-
- get shutdownTimeStr() {
- const minutes = Math.abs(
- getSliderMinutesFromSettings(this._settings, 'shutdown')
- );
- return this._settings.get_boolean('show-shutdown-absolute-timer-value')
- ? absoluteTimeString(minutes, C_('absolute time notation', '%a, %R'))
- : longDurationString(
- minutes,
- h => _n('%s hr', '%s hrs', h),
- m => _n('%s min', '%s mins', m)
- );
- }
-
- _updateSwitchLabel() {
- this.switcher.label.text = this._settings.get_boolean('root-mode-value')
- ? _('%s (protect)').format(this.shutdownTimeStr)
- : this.shutdownTimeStr;
-
- if (this._settings.get_string('wake-ref-timer-value') === 'shutdown') {
- this._updateWakeModeItem();
- }
- if (!this.info.internalShutdown.scheduled) {
- this._updateSubtitle();
- }
- }
-
- _updateSubtitle() {
- this.subtitle = this.info.internalShutdown.scheduled
- ? this._settings.get_boolean('show-shutdown-absolute-timer-value')
- ? this.info.internalShutdown.absoluteTimeString
- : durationString(this.info.internalShutdown.secondsLeft)
- : this.shutdownTimeStr;
- }
-
- _updateWakeModeItem() {
- const minutes = getSliderMinutesFromSettings(this._settings, 'wake');
- const abs = this._settings.get_boolean('show-wake-absolute-timer-value');
- this.wakeModeItem.label.text = (
- abs
- ? C_('WakeButtonText', '%s at %s')
- : C_('WakeButtonText', '%s after %s')
- ).format(
- actionLabel('wake'),
- abs
- ? absoluteTimeString(minutes, C_('absolute time notation', '%a, %R'))
- : longDurationString(
- minutes,
- h => _n('%s hour', '%s hours', h),
- m => _n('%s minute', '%s minutes', m)
- )
- );
- }
-
- _onShowSliderChanged(settingsPrefix) {
- this.sliderItems[settingsPrefix].visible =
- (settingsPrefix !== 'wake' ||
- this._settings.get_boolean('show-wake-items-value')) &&
- this._settings.get_boolean(`show-${settingsPrefix}-slider-value`);
- }
- }
-);
-
-export const ShutdownTimerIndicator = GObject.registerClass(
- {
- Properties: {
- 'wake-minutes': GObject.ParamSpec.int(
- 'wake-minutes',
- '',
- '',
- GObject.ParamFlags.READABLE,
- 0
- ),
- 'shutdown-minutes': GObject.ParamSpec.int(
- 'shutdown-minutes',
- '',
- '',
- GObject.ParamFlags.READABLE,
- 0
- ),
- },
- Signals: {
- 'open-preferences': {},
- shutdown: {
- param_types: [GObject.TYPE_BOOLEAN, GObject.TYPE_STRING],
- },
- wake: {
- param_types: [GObject.TYPE_BOOLEAN],
- },
- },
- },
- class ShutdownTimerIndicator extends QuickSettings.SystemIndicator {
- _init({ path, settings }) {
- super._init();
- this._state = 'inactive';
- this._settings = settings;
- this._textbox = new Textbox({ settings });
- const item = new ShutdownTimerItem({ path, settings });
- const infoFetcher = new InfoFetcher();
- const proxyCancel = new Gio.Cancellable();
- this._sdtProxy = null;
- this._initProxy(item, this._textbox, infoFetcher, proxyCancel).catch(
- err => {
- if (!proxyCancel.is_cancelled()) console.error('[sdt-proxy]', err);
- }
- );
- // React to changes in external shutdown and wake schedule
- infoFetcher.connect('changed', () => this._syncShutdownInfo());
- this._infoFetcher = infoFetcher;
- this._shutdownTimerItem = item;
-
- item.connect('open-preferences', () => this.emit('open-preferences'));
-
- const icon = new St.Icon({ style_class: 'system-status-icon' });
- const updateIcon = () => {
- const name = item.indicatorIconName;
- icon.visible = !!name;
- if (icon.visible) icon.iconName = name;
- this._syncIndicatorsVisible();
- };
-
- const scheduleLabel = new St.Label({
- y_expand: true,
- y_align: Clutter.ActorAlign.CENTER,
- });
- const updateLabel = () => {
- const text = item.shutdownText;
- scheduleLabel.text = text;
- scheduleLabel.visible = !!text;
- this._syncIndicatorsVisible();
- };
-
- this.add_child(icon);
- this.add_child(scheduleLabel);
-
- item.connect('notify::indicator-icon-name', () => updateIcon());
- item.connect('notify::shutdown-text', () => updateLabel());
-
- updateLabel();
- updateIcon();
-
- this.quickSettingsItems.push(item);
- this.connect('destroy', () => {
- proxyCancel.cancel();
- infoFetcher.destroy();
- this._infoFetcher = null;
- this._textbox.destroy();
- this.quickSettingsItems.forEach(i => i.destroy());
- this.quickSettingsItems = [];
- this._shutdownTimerItem = null;
- if (this._sdtProxy !== null) {
- this._sdtProxy.destroy();
- this._sdtProxy = null;
- }
- this._settings = null;
- });
- item.connect('destroy', () => {
- // Mitigate already destroyed error when logging out
- // Does js/ui/layout.js:256 destroy quickSettingsItems?
- this.quickSettingsItems = [];
- });
- }
-
- async _initProxy(item, textbox, infoFetcher, cancellable) {
- const proxy = await proxyPromise(
- ShutdownTimerName,
- Gio.DBus.session,
- 'org.gnome.Shell',
- ShutdownTimerObjectPath,
- cancellable
- );
- if (cancellable?.is_cancelled()) return;
- item.connect('shutdown', (__, shutdown, action) => {
- logDebug(
- '[menu-item] [shutdown-signal] shutdown: ',
- shutdown,
- 'action:',
- action
- );
- proxy
- .ScheduleShutdownAsync(shutdown, action)
- .catch(err => console.error('[shutdown]', err));
- });
- item.connect('wake', (__, wake) => {
- proxy
- .ScheduleWakeAsync(wake)
- .catch(err => console.error('[wake]', err));
- });
-
- const signalIds = [
- proxy.connectSignal('OnMessage', (__, ___, [msg]) => {
- textbox.showTextbox(msg);
- }),
- proxy.connectSignal('OnStateChange', (__, ___, [state]) => {
- logDebug('[menu-item] [OnStateChange-signal] state:', state);
- this._state = state;
- this._syncShutdownInfo();
- }),
- proxy.connectSignal('OnExternalChange', () => {
- infoFetcher.refresh();
- }),
- ];
- proxy.destroy = function () {
- signalIds.forEach(signalId => this.disconnectSignal(signalId));
- };
-
- this._sdtProxy = proxy;
- [this._state] = await this._sdtProxy.GetStateAsync();
- if (cancellable?.is_cancelled()) return;
- logDebug('[sdt-proxy] state', this._state);
- this._syncShutdownInfo();
- infoFetcher.refresh();
- }
-
- _syncShutdownInfo() {
- const item = this._shutdownTimerItem;
- if (this._state === 'action') {
- if (SessionModeAware.foregroundActive()) Main.overview.hide();
- this._textbox.hideAll();
- }
- item.info = {
- internalShutdown: getShutdownScheduleFromSettings(this._settings),
- externalShutdown: item.info.externalShutdown.copy({
- ...this._infoFetcher.shutdownInfo,
- }),
- externalWake: item.info.externalWake.copy({
- ...this._infoFetcher.wakeInfo,
- }),
- state: this._state,
- };
- item.updateShutdownInfo();
- }
- }
-);