diff options
| author | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
|---|---|---|
| committer | AlexanderCurl <alexc@alexc.hu> | 2026-04-18 17:46:06 +0100 |
| commit | 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 (patch) | |
| tree | ab1123d4067c1b086dd6faa7ee4ea643236b565a /raveos-theme/gnome/theme-data/extensions/installed/ShutdownTimer@deminder/modules/menu-item.js | |
| parent | 5d94c0a7d44a2255b81815a52a7056a94a39842d (diff) | |
| download | RaveOS-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.js | 573 |
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(); - } - } -); |