From f0f558736e4b32ebe5f84f44902fa36c7dad6850 Mon Sep 17 00:00:00 2001 From: claudiux <33965039+claudiux@users.noreply.github.com> Date: Sun, 12 Jan 2025 20:06:20 +0100 Subject: [PATCH] [SpicesUpdate@claudiux] v7.5.1: Now uses mainloopTools to optimize loop management (#6754) * SpicesUpdate v7.5.1: Now use mainloopTools to optimize loop management * SpicesUpdate v7.5.1: applet.js code clean-up * SpicesUpdate v7.5.1: applet.js code clean-up 2 --- .../files/SpicesUpdate@claudiux/6.0/applet.js | 168 +++++++-------- .../SpicesUpdate@claudiux/6.0/httpLib.js | 2 +- .../6.0/mainloopTools.js | 191 ++++++++++++++++++ .../SpicesUpdate@claudiux/6.0/sourceExists.js | 17 -- .../files/SpicesUpdate@claudiux/CHANGELOG.md | 3 + .../files/SpicesUpdate@claudiux/metadata.json | 2 +- 6 files changed, 266 insertions(+), 117 deletions(-) create mode 100644 SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/mainloopTools.js delete mode 100644 SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/sourceExists.js diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/applet.js b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/applet.js index b8b8c44be11..8bc0492f240 100644 --- a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/applet.js +++ b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/applet.js @@ -21,15 +21,15 @@ const { LogLevelFlags, getenv, get_language_names, filename_to_uri, find_program const { network_monitor_get_default, NetworkConnectivity, file_new_for_path, icon_new_for_string, FileQueryInfoFlags, FileType, Settings, FileCreateFlags } = imports.gi.Gio; //Gtk: const Gtk = imports.gi.Gtk; // /!\ Gtk.Label != St.Label -// Gdk: +//Gdk: const { Display } = imports.gi.Gdk; +//Util +const { spawnCommandLineAsync } = imports.misc.util; //Mainloop: -const { source_remove, timeout_add_seconds } = imports.mainloop; -const { source_exists, timeout_exists, interval_exists } = require("./sourceExists"); +const { timeout_add_seconds, timeout_add, setTimeout, clearTimeout, setInterval, clearInterval, source_exists, source_remove, remove_all_sources } = require("mainloopTools"); const Main = imports.ui.main; const MessageTray = imports.ui.messageTray; -const Util = imports.misc.util; const Extension = imports.ui.extension; const Tooltips = imports.ui.tooltips; const Tweener = imports.ui.tweener; @@ -58,7 +58,7 @@ ICONTHEME.prepend_search_path(ICONS_DIR); //ICONTHEME.add_resource_path(ICONS_DIR); -Util.spawnCommandLineAsync("/bin/sh -c '%s/witness-debian.sh'".format(SCRIPTS_DIR)); +spawnCommandLineAsync("/bin/sh -c '%s/witness-debian.sh'".format(SCRIPTS_DIR)); @@ -111,7 +111,7 @@ function criticalNotify(msg, details, icon, button=[]) { notification.addButton(button[1], button[0]); notification.connect("action-invoked", (self, action) => { if (action === button[1]) { - Util.spawnCommandLineAsync(button[2]); + spawnCommandLineAsync(button[2]); } }); } @@ -164,10 +164,10 @@ class SpicesUpdate extends IconApplet { this.http = new HttpLib(); // To be sure that the scripts will be executable: - Util.spawnCommandLineAsync("/bin/bash -c 'cd %s && chmod 755 *.py *.sh'".format(SCRIPTS_DIR), null, null); + spawnCommandLineAsync("/bin/bash -c 'cd %s && chmod 755 *.py *.sh'".format(SCRIPTS_DIR), null, null); // Move themes to their new location (from ~/.themes to ~/.local/share/themes): - Util.spawnCommandLineAsync(SCRIPTS_DIR + "/move_themes.sh") + spawnCommandLineAsync(SCRIPTS_DIR + "/move_themes.sh") //http session: //~ this.define_http_session(); @@ -279,8 +279,7 @@ class SpicesUpdate extends IconApplet { this.disable_system_auto_update(); let stoId = setTimeout( () => { this._loop_refresh_cache(); - if (timeout_exists(stoId)) - clearTimeout(stoId); + clearTimeout(stoId); stoId = null; }, 20000); // Wait 20 seconds for mintupdate to run correctly. @@ -319,7 +318,7 @@ class SpicesUpdate extends IconApplet { //~ logDebug("is_to_download: "+is_to_download); if (is_to_download) { //~ logDebug("Cache refresh requested."); - Util.spawnCommandLineAsync(CACHE_UPDATER+" --update-all"); + spawnCommandLineAsync(CACHE_UPDATER+" --update-all"); } is_to_download = undefined; @@ -615,9 +614,7 @@ class SpicesUpdate extends IconApplet { this.applet_running = true; let id = setTimeout(() => { this.http = new HttpLib(); - //~ this._on_refresh_pressed(); - if (timeout_exists(id)) - clearTimeout(id); + clearTimeout(id); id = null }, 30000); } else { @@ -819,9 +816,9 @@ class SpicesUpdate extends IconApplet { notification.connect("action-invoked", (self, action) => { if (action == "su-%s-symbolic".format(""+type)) { - Util.spawnCommandLineAsync("%s %s -t %s -s %s".format(CS_PATH, ""+type, TAB, SORT)); + spawnCommandLineAsync("%s %s -t %s -s %s".format(CS_PATH, ""+type, TAB, SORT)); } else if (action == "software-update-available-symbolic") { - Util.spawnCommandLineAsync("%s %s -t %s -s %s -u".format(CS_PATH, ""+type, TAB, SORT)); + spawnCommandLineAsync("%s %s -t %s -s %s -u".format(CS_PATH, ""+type, TAB, SORT)); let n = this.notifications_about_updates[type].pop(this.notifications_about_updates[type].indexOf(notification)); n.destroy(3); } else if (action == "su-forget-symbolic") { @@ -897,7 +894,6 @@ class SpicesUpdate extends IconApplet { //~ let coeff = QUICK() ? 720 : 3600; this.refreshInterval = 3600 * this.general_frequency; this.loopId = timeout_add_seconds(this.refreshInterval, () => this.updateLoop()); - //~ coeff = undefined; } // End of on_frequency_changed on_display_type_changed() { @@ -956,23 +952,23 @@ class SpicesUpdate extends IconApplet { } // End of on_btn_test_notif_pressed on_btn_cs_applets_pressed() { - Util.spawnCommandLineAsync("%s applets -t %s -s %s".format(CS_PATH, TAB, SORT)); + spawnCommandLineAsync("%s applets -t %s -s %s".format(CS_PATH, TAB, SORT)); } // End of on_btn_cs_applets_pressed on_btn_cs_desklets_pressed() { - Util.spawnCommandLineAsync("%s desklets -t %s -s %s".format(CS_PATH, TAB, SORT)); + spawnCommandLineAsync("%s desklets -t %s -s %s".format(CS_PATH, TAB, SORT)); } // End of on_btn_cs_desklets_pressed on_btn_cs_extensions_pressed() { - Util.spawnCommandLineAsync("%s extensions -t %s -s %s".format(CS_PATH, TAB, SORT)); + spawnCommandLineAsync("%s extensions -t %s -s %s".format(CS_PATH, TAB, SORT)); } // End of on_btn_cs_extensions_pressed on_btn_cs_themes_pressed() { - Util.spawnCommandLineAsync("%s themes -t %s -s %s".format(CS_PATH, TAB, SORT)); + spawnCommandLineAsync("%s themes -t %s -s %s".format(CS_PATH, TAB, SORT)); } // End of on_btn_cs_themes_pressed on_btn_cs_actions_pressed() { - Util.spawnCommandLineAsync("%s actions -t %s -s %s".format(CS_PATH, TAB, SORT)); + spawnCommandLineAsync("%s actions -t %s -s %s".format(CS_PATH, TAB, SORT)); } // End of on_btn_cs_themes_pressed on_tooltip_max_width_screen_percentage_changed() { @@ -1065,12 +1061,8 @@ class SpicesUpdate extends IconApplet { } const blacklist = this.get_blacklisted_packages(); - //~ logDebug("blacklist: "+blacklist); // populate this.unprotected_ with the this.unprotected_ elements, removing uninstalled : - //~ let unprotectedSpices_length = unprotectedSpices.length; - //~ for (var i=0; i < unprotectedSpices_length; i++) { - //~ let a = unprotectedSpices[i]; for (let a of unprotectedSpices) { let d = file_new_for_path("%s/%s".format(DIR_MAP[type], a["name"])); if (d.query_exists(null)) { @@ -1129,21 +1121,36 @@ class SpicesUpdate extends IconApplet { } } + var _protected = []; + var _unprotected = []; + + this.unprotectedList[type].forEach( s => { + if (s["name"] === "AlbumArt3.0@claudiux") + s["isunprotected"] = false; + if (s["isunprotected"]) + _unprotected.push(s); + else + _protected.push(s); + }); + _unprotected.sort((a,b) => this._compare(a,b)); + _protected.sort((a,b) => this._compare(a,b)); + this.unprotectedList[type] = _protected.concat(_unprotected); + switch (type) { case "applets": - this.unprotected_applets = this.unprotectedList[type].sort((a,b) => this._compare(a,b)); + this.unprotected_applets = this.unprotectedList[type]; break; case "desklets": - this.unprotected_desklets = this.unprotectedList[type].sort((a,b) => this._compare(a,b)); + this.unprotected_desklets = this.unprotectedList[type]; break; case "extensions": - this.unprotected_extensions = this.unprotectedList[type].sort((a,b) => this._compare(a,b)); + this.unprotected_extensions = this.unprotectedList[type]; break; case "themes": - this.unprotected_themes = this.unprotectedList[type].sort((a,b) => this._compare(a,b)); + this.unprotected_themes = this.unprotectedList[type]; break; case "actions": - this.unprotected_actions = this.unprotectedList[type].sort((a,b) => this._compare(a,b)); + this.unprotected_actions = this.unprotectedList[type]; } children.close(null); @@ -1152,6 +1159,10 @@ class SpicesUpdate extends IconApplet { file_type = undefined; name = undefined; isSystemUnprotected = undefined; + _protected = []; + _unprotected = []; + _protected = undefined; + _unprotected = undefined; } dir = undefined; @@ -1182,22 +1193,12 @@ class SpicesUpdate extends IconApplet { } // End of populateSettingsUnprotectedActions _compare(a,b) { - // Protect AlbumArt3.0@claudiux desklet: - if (a["name"] === "AlbumArt3.0@claudiux") - a["isunprotected"] = false; - // We know that a["name"] and b["name"] are different. - if (!a["isunprotected"]) { - if (a["name"].toLowerCase() < b["name"].toLowerCase()) { - return -2; - } else { - return -1; - } - } - else if (a["name"].toLowerCase() < b["name"].toLowerCase()) { + if (a["name"].toLowerCase() < b["name"].toLowerCase()) { + return -1; + } else { return 1; } - return 2; } // End of _compare _get_singular_type(t) { @@ -1223,7 +1224,7 @@ class SpicesUpdate extends IconApplet { let _GentoWitnessFile = file_new_for_path("/etc/gentoo-release"); // Gentoo let _isGentoo = _GentoWitnessFile.query_exists(null); if (_isArchlinux || _isopenSUSE || _isGentoo) { - Util.spawnCommandLineAsync("/bin/sh -c \"%s/install_symbola_on_Arch.sh\"".format(SCRIPTS_DIR), null, null); + spawnCommandLineAsync("/bin/sh -c \"%s/install_symbola_on_Arch.sh\"".format(SCRIPTS_DIR), null, null); _fonts_installed = true } } @@ -1317,21 +1318,18 @@ class SpicesUpdate extends IconApplet { if (!_is_xdg_open_present) { if (terminal.length > 0) { - Util.spawnCommandLineAsync(terminal); + spawnCommandLineAsync(terminal); // TRANSLATORS: The next messages should not be translated. //~ if (_isDebian === true) { - //~ Util.spawnCommandLineAsync(terminal + " " + term_sep + " " + " '/bin/bash -c \"echo Spices Update message: Some packages needed!; echo To complete the installation, please become root with su then execute the command: ; echo "+ _apt_update + _and + _apt_install + "; sleep 1; exec bash\"'", null, null); + //~ spawnCommandLineAsync(terminal + " " + term_sep + " " + " '/bin/bash -c \"echo Spices Update message: Some packages needed!; echo To complete the installation, please become root with su then execute the command: ; echo "+ _apt_update + _and + _apt_install + "; sleep 1; exec bash\"'", null, null); //~ } else { - //~ Util.spawnCommandLineAsync(terminal + " " + term_sep + " " + `'/bin/bash -c \"echo Spices Update message: Some packages needed!; echo To complete the installation, please enter and execute the command: ; echo ${_apt_update} ${_and} ${_apt_install}; sleep 1; exec bash\"'`, null, null); + //~ spawnCommandLineAsync(terminal + " " + term_sep + " " + `'/bin/bash -c \"echo Spices Update message: Some packages needed!; echo To complete the installation, please enter and execute the command: ; echo ${_apt_update} ${_and} ${_apt_install}; sleep 1; exec bash\"'`, null, null); //~ } } } else { if (!this.fonts_installed) - Util.spawnCommandLineAsync("/usr/bin/xdg-open apt://fonts-symbola"); + spawnCommandLineAsync("/usr/bin/xdg-open apt://fonts-symbola"); } - //~ if (_is_xdg_open_present && !this.fonts_installed) { - //~ Util.spawnCommandLineAsync("/usr/bin/xdg-open apt://fonts-symbola"); - //~ } this.dependenciesMet = false; } // End of check_dependencies @@ -1531,8 +1529,7 @@ class SpicesUpdate extends IconApplet { //this.isProcessing = false; this.updateUI(); if (newSpices.length === 0) { - if (interval_exists(id)) - clearInterval(id); + clearInterval(id); this.isProcessing = false; this.updateUI(); newSpices = undefined; @@ -1559,8 +1556,7 @@ class SpicesUpdate extends IconApplet { this.do_rotation = false; this.updateUI(); } else { - if (interval_exists(id)) - clearInterval(id); + clearInterval(id); indexTypes = undefined; type = undefined; } @@ -1586,7 +1582,7 @@ class SpicesUpdate extends IconApplet { let command = THUMB_DOWNLOADER + " " + url + " " + this._get_singular_type(type) + " " + _basename; //~ logDebug("command: "+command); - Util.spawnCommandLineAsync(command); + spawnCommandLineAsync(command); memberName = undefined; url = undefined; target = undefined; @@ -1756,14 +1752,11 @@ class SpicesUpdate extends IconApplet { } // End of monitor_png_directory _on_pngDir_changed(type) { - if (timeout_exists(this.timeoutId)) { - clearTimeout(this.timeoutId); - } + clearTimeout(this.timeoutId); this.timeoutId = null; this.timeoutId = setTimeout(() => { this._on_refresh_pressed(); - if (timeout_exists(this.timeoutId)) - clearTimeout(this.timeoutId); + clearTimeout(this.timeoutId); this.timeoutId = null; }, 12000); } // End of _on_pngDir_changed @@ -1802,14 +1795,11 @@ class SpicesUpdate extends IconApplet { if (this.isLooping) { this.new_loop_requested = true; } else { - if (timeout_exists(this.timeoutId)) { - clearTimeout(this.timeoutId); - } + clearTimeout(this.timeoutId); this.timeoutId = null; this.timeoutId = setTimeout(() => { this._on_refresh_pressed(); - if (timeout_exists(this.timeoutId)) - clearTimeout(this.timeoutId); + clearTimeout(this.timeoutId); this.timeoutId = null; }, 12000); } @@ -1851,7 +1841,6 @@ class SpicesUpdate extends IconApplet { get_active_spices(type) { // Returns the list of active spices of type 'type' - //~ var dconfEnabled; var elt = (type.toString() === "applets") ? 3 : 0; let listCanBeUpdated = this.get_can_be_updated(type); let enabled; @@ -1938,7 +1927,7 @@ class SpicesUpdate extends IconApplet { if (this.new_Spices[t].length > 0) ts += " %s %s".format(char_new, (this.new_Spices[t].length).toString()); this.spicesMenuItems[t] = new PopupIndicatorMenuItem(ts); this.spicesMenuItems[t].connect("activate", (event) => { - Util.spawnCommandLineAsync("%s %s -t %s -s %s".format(CS_PATH, t.toString(), TAB, SORT)); + spawnCommandLineAsync("%s %s -t %s -s %s".format(CS_PATH, t.toString(), TAB, SORT)); }); this.spicesMenuItems[t].setShowDot(this.menuDots[t]); this.menu.addMenuItem(this.spicesMenuItems[t]); @@ -1969,7 +1958,7 @@ class SpicesUpdate extends IconApplet { let _optionTitle = _configureOptions[i]; let _icon = _iconNames[i]; _options[i] = new PopupIconMenuItem(_optionTitle, _icon, IconType.SYMBOLIC); - _options[i].connect("activate", (event) => Util.spawnCommandLineAsync("/usr/bin/xlet-settings applet %s -i %s -t %s".format(UUID, this.instanceId, i.toString()))); + _options[i].connect("activate", (event) => spawnCommandLineAsync("/usr/bin/xlet-settings applet %s -i %s -t %s".format(UUID, this.instanceId, i.toString()))); _configure.menu.addMenuItem(_options[i]) } _configure.menu.open(); @@ -1992,10 +1981,10 @@ class SpicesUpdate extends IconApplet { this.help_button.connect("activate", (event) => { let _language = this.get_user_language(); if (_language.startsWith("en")) { - Util.spawnCommandLineAsync("/usr/bin/xdg-open https://cinnamon-spices.linuxmint.com/applets/view/309"); + spawnCommandLineAsync("/usr/bin/xdg-open https://cinnamon-spices.linuxmint.com/applets/view/309"); } else { let url_help = "https://cinnamon--spices-linuxmint-com.translate.goog/applets/view/309?_x_tr_sl=auto&_x_tr_tl=%s&_x_tr_hl=%s&_x_tr_pto=wapp".format(_language, _language); - Util.spawnCommandLineAsync("/usr/bin/xdg-open "+url_help); + spawnCommandLineAsync("/usr/bin/xdg-open "+url_help); url_help = undefined; } }); @@ -2065,7 +2054,6 @@ class SpicesUpdate extends IconApplet { source_remove(this.loopId); } this.loopId = null; - //~ this.refreshInterval = QUICK() ? 720 * this.general_frequency : 3600 * this.general_frequency; this.refreshInterval = 3600 * this.general_frequency; this.do_rotation = true; this.updateLoop(); @@ -2190,8 +2178,6 @@ class SpicesUpdate extends IconApplet { if (this.do_rotation) { if (this.interval == null) this.interval = setInterval(() => this.icon_rotate(), 10); - //~ logDebug("updateUI this.interval.source_id: "+this.interval.source_id); - //~ logDebug("updateUI: source_exists("+this.interval.source_id+"): "+source_exists(this.interval.source_id)); } this.set_icon_color(); @@ -2231,12 +2217,8 @@ class SpicesUpdate extends IconApplet { let fontSize = this.badge_font_size(); if (this.isHorizontal) { this.numberLabel.set_pivot_point(this.horizontal_anchor_x(), this.horizontal_anchor_y()); - //~ this.numberLabel.anchor_x = this.horizontal_anchor_x(); - //~ this.numberLabel.anchor_y = this.horizontal_anchor_y() } else { this.numberLabel.set_pivot_point(this.vertical_anchor_x(), this.vertical_anchor_y()); - //~ this.numberLabel.anchor_x = this.vertical_anchor_x(); - //~ this.numberLabel.anchor_y = this.vertical_anchor_y() // FIXME: anchor_x and anchor_y are DEPRECATED. Use pivot_point instead. } this.numberLabel.style = "font-size: %spx; padding: 0px; color: %s;".format(""+fontSize, this.defaultColor); @@ -2246,8 +2228,7 @@ class SpicesUpdate extends IconApplet { transition: "linear", time: 0.5, onComplete: Lang.bind(this, function() { - if (interval_exists(this.interval)) - clearInterval(this.interval); + clearInterval(this.interval); this.interval = null; this.angle = 0; this.set_applet_icon_symbolic_name("spices-update"); @@ -2433,7 +2414,7 @@ class SpicesUpdate extends IconApplet { for (let t of TYPES) { if (this.nb_in_menu[t] > 0) { let command = "%s %s -t %s -s %s".format(CS_PATH, ""+t, TAB, SORT); - Util.spawnCommandLineAsync(command); + spawnCommandLineAsync(command); command = undefined; } } @@ -2531,35 +2512,26 @@ class SpicesUpdate extends IconApplet { logError(e) } } + + remove_all_sources(); } // End of on_applet_removed_from_panel on_applet_reloaded() { // When applet is reloaded or removed from panel: stop the loop, inhibit the update timer, // remove all bindings and disconnect all signals (if any) to avoid errors. this.applet_running = false; - if (source_exists(this.loopRefreshId)) { - source_remove(this.loopRefreshId); - } + source_remove(this.loopRefreshId); this.loopRefreshId = null; - if (source_exists(this.loopId)) { - source_remove(this.loopId); - } + source_remove(this.loopId); this.loopId = null; - //~ logDebug("on_applet_reloaded source_exists("+this.interval+"): "+source_exists(this.interval)); - if (interval_exists(this.interval)) { - clearInterval(this.interval); - } + clearInterval(this.interval); this.interval = null; - if (timeout_exists(this.timeoutId)) { - clearTimeout(this.timeoutId); - } + clearTimeout(this.timeoutId); this.timeoutId = null; - if (interval_exists(this.loopCacheIntervalId)) { - clearInterval(this.loopCacheIntervalId); - } + clearInterval(this.loopCacheIntervalId); this.loopCacheIntervalId = null; diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/httpLib.js b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/httpLib.js index ec556c13c25..d00315d48c5 100644 --- a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/httpLib.js +++ b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/httpLib.js @@ -2,7 +2,7 @@ const { source_remove, timeout_add_seconds, timeout_add -} = imports.mainloop; //Mainloop +} = require("mainloopTools"); /** * Usage of log and logError: diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/mainloopTools.js b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/mainloopTools.js new file mode 100644 index 00000000000..ccebf2e2e37 --- /dev/null +++ b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/mainloopTools.js @@ -0,0 +1,191 @@ +const GLib = imports.gi.GLib; +const Mainloop = imports.mainloop; + +/** + * _sourceIds + * Array containing IDs of all looping loops. + */ +var _sourceIds = []; + +/** + * timeout_add_seconds + * + * @callback (function) is executed every @sec (number) seconds + * with @params (dictionnary as {'key1': value1, 'key2': value2, ...}). + * + * @params is often null. + * + */ +function timeout_add_seconds(sec, callback, params=null) { + let id = Mainloop.timeout_add_seconds(sec, callback, params); + if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id); + return id; +} + +/** + * timeout_add_seconds + * + * @callback (function) is executed every @ms (number) milliseconds + * with @params (dictionnary as {'key1': value1, 'key2': value2, ...}). + * + * @params is often null. + * + */ +function timeout_add(ms, callback, params=null) { + let id = Mainloop.timeout_add_seconds(ms, callback, params); + if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id); + return id; +} + +/** + * setTimeout: + * @callback (function): Function to call at the end of the timeout. + * @ms (number): Milliseconds until the timeout expires. + * + * Convenience wrapper for a Mainloop.timeout_add loop that + * returns false. + * + * Returns (number): The ID of the loop. + */ +function setTimeout(callback, ms) { + let args = []; + if (arguments.length > 2) { + args = args.slice.call(arguments, 2); + } + + let id = Mainloop.timeout_add(ms, () => { + callback.call(null, ...args); + return false; // Stop repeating + }, null); + + if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id); + + return id; +} + +/** + * clearTimeout: + * @id (number): The ID of the loop to remove. + * + * Convenience wrapper for Mainloop.source_remove. + */ +function clearTimeout(id) { + if (id) { + Mainloop.source_remove(id); + const pos = _sourceIds.indexOf(id); + if (pos > -1) _sourceIds.splice(pos, 1); + } +} + + +/** + * setInterval: + * @callback (function): Function to call on every interval. + * @ms (number): Milliseconds between invocations. + * + * Convenience wrapper for a Mainloop.timeout_add loop that + * returns true. + * + * Returns (number): The ID of the loop. + */ +function setInterval(callback, ms) { + let args = []; + if (arguments.length > 2) { + args = args.slice.call(arguments, 2); + } + + let id = Mainloop.timeout_add(ms, () => { + callback.call(null, ...args); + return true; // Repeat + }, null); + + if (id && (_sourceIds.indexOf(id) === -1)) _sourceIds.push(id); + + return id; +} + +/** + * clearInterval: + * @id (number): The ID of the loop to remove. + * + * Convenience wrapper for Mainloop.source_remove. + */ +function clearInterval(id) { + if (id) { + Mainloop.source_remove(id); + const pos = _sourceIds.indexOf(id); + if (pos > -1) _sourceIds.splice(pos, 1); + } +}; + +/** + * source_exists + * + * @id (number, or null) + * + * Checks if @id is well the ID of a loop. + * + */ +function source_exists(id) { + let _id = id; + if (!_id) return false; + return (GLib.MainContext.default().find_source_by_id(_id) != null); +} + +//~ function timeout_exists(id) { + //~ if (!id) return false; + //~ if (!id.source_id) return false; + //~ return (GLib.MainContext.default().find_source_by_id(id.source_id) != null); +//~ } + +//~ function interval_exists(id) { + //~ return timeout_exists(id); +//~ } + +/** + * source_remove + * + * @id (number): The ID of the loop to stop. + * @remove_from_sourceIds (boolean): *true* (by default) when we want to + * remove @id from _sourceIds. May be *false* for internal functionning. + * + * Convenience wrapper for a Mainloop.source_remove(id) that returns a + * boolean. + */ +function source_remove(id, remove_from_sourceIds=true) { + if (source_exists(id)) { + Mainloop.source_remove(id); + if (remove_from_sourceIds) { + const pos = _sourceIds.indexOf(id); + if (pos > -1) _sourceIds.splice(pos, 1); + } + return true; + } + return false; +} + +/** + * remove_all_sources + * + * Execute it when removing the spice. + * Tries to delete all remaining sources, in order to remove all loops. + */ +function remove_all_sources() { + while (_sourceIds.length > 0) { + let id = _sourceIds.pop(); + source_remove(id, false); + } +} + +module.exports = { + _sourceIds, + timeout_add_seconds, + timeout_add, + setTimeout, + clearTimeout, + setInterval, + clearInterval, + source_exists, + source_remove, + remove_all_sources +} diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/sourceExists.js b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/sourceExists.js deleted file mode 100644 index e12bfb87ae3..00000000000 --- a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/6.0/sourceExists.js +++ /dev/null @@ -1,17 +0,0 @@ -const GLib = imports.gi.GLib; - -function source_exists(id) { - let _id = id; - if (!_id) return false; - return (GLib.MainContext.default().find_source_by_id(_id) != null); -} - -function timeout_exists(id) { - if (!id) return false; - if (!id.source_id) return false; - return (GLib.MainContext.default().find_source_by_id(id.source_id) != null); -} - -function interval_exists(id) { - return timeout_exists(id); -} diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/CHANGELOG.md b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/CHANGELOG.md index 21f5ff1e1ab..69f0160ad62 100644 --- a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/CHANGELOG.md +++ b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/CHANGELOG.md @@ -1,3 +1,6 @@ +### v7.5.1~20250112 + * Now use mainloopTools to optimize loop management. + ### v7.5.0~20250111 * Improved management of loops. diff --git a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/metadata.json b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/metadata.json index d226a5ec9e6..c5f8f16c1c8 100644 --- a/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/metadata.json +++ b/SpicesUpdate@claudiux/files/SpicesUpdate@claudiux/metadata.json @@ -3,7 +3,7 @@ "name": "Spices Update", "max-instances": "1", "hide-configuration": false, - "version": "7.5.0", + "version": "7.5.1", "description": "Warns you when installed Spices (actions, applets, desklets, extensions, themes) require an update or new Spices are available.", "multiversion": true, "cinnamon-version": [