import Gio from 'gi://Gio'; import GLib from 'gi://GLib'; import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; // GNOME lädt Extension-Code nur einmal pro Sitzung. Deshalb ist diese Datei nur ein Lader: // Beim Einschalten kopiert er die Module in einen frischen Ordner und importiert sie von dort. // Neuer Ordner heißt neue Adresse, also lädt GJS wirklich den aktuellen Code. Nach einer // Änderung reicht so make update (kopiert, schaltet aus und ein), ohne Ab- und Anmelden. // Nur diese Datei selbst wirkt erst nach dem nächsten Anmelden. export default class DesktopExtension extends Extension { _generation = 0; enable() { const generation = ++this._generation; const dir = copyModules(this.dir); import(`${dir.get_uri()}/app.js`) .then(app => { // Inzwischen aus- oder erneut eingeschaltet: dieser Stand ist überholt if (this._generation !== generation) return; this._app = app; app.enable(this); }) .catch(e => console.error(`desktop@marha.de: Laden fehlgeschlagen: ${e.message}\n${e.stack}`)); } disable() { this._generation++; this._app?.disable(this); this._app = null; } } // Alle Module außer dieser Datei nach ~/.cache/desktop-app/live- kopieren. Ältere Kopien // sind schon geladen und werden gelöscht. function copyModules(source) { const base = Gio.File.new_for_path(GLib.build_filenamev([GLib.get_user_cache_dir(), 'desktop-app'])); GLib.mkdir_with_parents(base.get_path(), 0o700); for (const name of listNames(base)) { if (name.startsWith('live-')) removeDir(base.get_child(name)); } const dest = base.get_child(`live-${GLib.get_real_time()}`); dest.make_directory(null); for (const name of listNames(source)) { if (name.endsWith('.js') && name !== 'extension.js') source.get_child(name).copy(dest.get_child(name), Gio.FileCopyFlags.OVERWRITE, null, null); } return dest; } function listNames(dir) { const names = []; const children = dir.enumerate_children('standard::name', Gio.FileQueryInfoFlags.NONE, null); let info; while ((info = children.next_file(null))) names.push(info.get_name()); children.close(null); return names; } function removeDir(dir) { for (const name of listNames(dir)) dir.get_child(name).delete(null); dir.delete(null); }