import Gtk from 'gi://Gtk'; import Adw from 'gi://Adw'; import Gio from 'gi://Gio'; import Gdk from 'gi://Gdk'; import GLib from 'gi://GLib'; import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; function color_to_hex(rgba) { const red = Math.round(rgba.red * 255); const green = Math.round(rgba.green * 255); const blue = Math.round(rgba.blue * 255); const alpha = Math.round(rgba.alpha * 255); return `#${red.toString(16).padStart(2, '0')}${green.toString(16).padStart(2, '0')}${blue.toString(16).padStart(2, '0')}${alpha.toString(16).padStart(2, '0')}`; } function hex_to_rgba(hex) { const rgba = new Gdk.RGBA(); rgba.parse(hex); return rgba; } export default class PingMonitorPreferences extends ExtensionPreferences { fillPreferencesWindow(window) { const settings = this.getSettings(); // Create preferences page const page = new Adw.PreferencesPage({ title: _('Preferences'), icon_name: 'dialog-information-symbolic' }); // Create color preferences group const colorGroup = new Adw.PreferencesGroup({ title: _('Color Settings'), description: _('Configure colors for different ping states') }); page.add(colorGroup); // Good color const goodRow = this._createColorRow( settings, _('Good'), _('Color for good ping response'), 'ping-good-color' ); colorGroup.add(goodRow); // Warning color const warningRow = this._createColorRow( settings, _('Warning'), _('Color for warning ping response'), 'ping-warning-color' ); colorGroup.add(warningRow); // Bad color const badRow = this._createColorRow( settings, _('Bad'), _('Color for bad ping response'), 'ping-bad-color' ); colorGroup.add(badRow); // Loss color const lossRow = this._createColorRow( settings, _('Loss'), _('Color for ping packet loss'), 'ping-loss-color' ); colorGroup.add(lossRow); // Create configuration file group const configGroup = new Adw.PreferencesGroup({ title: _('Configuration'), description: _('Configure the path to the configuration file') }); page.add(configGroup); // Config path row const configRow = new Adw.ActionRow({ title: _('Configuration File'), subtitle: settings.get_string('ping-config-path') || _('No file selected') }); const fileButton = new Gtk.Button({ label: _('Select File'), valign: Gtk.Align.CENTER }); fileButton.connect('clicked', () => { const dialog = new Gtk.FileDialog(); dialog.set_title(_('Open configuration file')); const initialFolder = Gio.File.new_for_path(GLib.getenv('HOME') + '/.config'); dialog.set_initial_folder(initialFolder); const currentPath = settings.get_string('ping-config-path'); if (currentPath) { const currentFile = Gio.File.new_for_path(currentPath); dialog.set_initial_file(currentFile); } dialog.open(window, null, (source, result) => { try { const file = dialog.open_finish(result); if (file) { const path = file.get_path(); settings.set_string('ping-config-path', path); configRow.subtitle = path; } } catch (e) { if (e.matches(Gtk.DialogError, Gtk.DialogError.DISMISSED)) { // User cancelled, do nothing } else { log('Error selecting file: ' + e); } } }); }); configRow.add_suffix(fileButton); configRow.activatable_widget = fileButton; configGroup.add(configRow); window.add(page); } _createColorRow(settings, title, subtitle, key) { const row = new Adw.ActionRow({ title: title, subtitle: subtitle }); const colorButton = new Gtk.ColorButton({ valign: Gtk.Align.CENTER }); colorButton.set_use_alpha(true); // Set initial color const currentColor = settings.get_string(key); const rgba = hex_to_rgba(currentColor); colorButton.set_rgba(rgba); // Connect color change signal colorButton.connect('color-set', (button) => { settings.set_string(key, color_to_hex(button.get_rgba())); }); row.add_suffix(colorButton); row.activatable_widget = colorButton; return row; } }