diff --git a/Makefile b/Makefile index 2489034..ac84f17 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,7 @@ build: build-clean gnome-extensions pack \ --extra-source=../LICENSE \ --extra-source=./config.js \ + --extra-source=./utils.js \ --extra-source=./modules/ \ --podir=./po/ \ --gettext-domain=$(UUID) \ diff --git a/src/config.js b/src/config.js index f860925..fb47850 100644 --- a/src/config.js +++ b/src/config.js @@ -24,3 +24,5 @@ var THEME_GSETTINGS_PROPERTY = 'gtk-theme'; var NIGHTLIGHT_GSETTINGS_SCHEMA = 'org.gnome.settings-daemon.plugins.color'; var NIGHTLIGHT_GSETTINGS_PROPERTY = 'night-light-enabled'; + +var debug = false; diff --git a/src/modules/Nightlighter.js b/src/modules/Nightlighter.js index 30dcb6f..1f5e647 100644 --- a/src/modules/Nightlighter.js +++ b/src/modules/Nightlighter.js @@ -23,6 +23,8 @@ const { main } = imports.ui; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; +const { log_debug } = Me.imports.utils; + const Gettext = imports.gettext.domain(config.EXT_UUID); const _ = Gettext.gettext; @@ -38,16 +40,21 @@ if it is enabled and warns the user if that's not the case. var Nightlighter = class { constructor() { + log_debug('Initializing Nightlighter...'); this.nightlight_gsettings = new Gio.Settings({ schema: config.NIGHTLIGHT_GSETTINGS_SCHEMA }); + log_debug('Nightlighter initialized.'); } enable() { + log_debug('Enabling NightLighter...'); // As Night Light must be enabled for the extension to work, we have to monitor any change of that setting. - this._listen_to_nightlight_status(); try { + this._listen_to_nightlight_status(); this._check_nightlight_status(); this._connect_to_dbus(); this._listen_to_nightlight_changes(); + this.emit(); + log_debug('Nightlighter enabled.'); } catch(e) { main.notifyError(config.EXT_NAME, e.message); @@ -55,20 +62,21 @@ var Nightlighter = class { } disable() { + log_debug('Disabling Nightlighter...'); this._stop_listening_to_nightlight_status(); this._stop_listening_to_nightlight_changes(); this._disconnect_from_dbus(); + log_debug('Nightlighter disabled.'); } get status() { - if ( !this.dbus_proxy ) { - throw new Error(); - } - try { - return this.dbus_proxy.get_cached_property('NightLightActive').get_boolean(); - } - catch(e) { - return false; // Sometimes when Night Light hasn't changed colors yet it returns an error, we consider it is inactive. + if ( this.dbus_proxy ) { + try { + return this.dbus_proxy.get_cached_property('NightLightActive').get_boolean(); + } + catch(e) { + return false; // Sometimes when Night Light hasn't changed colors yet it returns an error, we consider it is inactive. + } } } @@ -99,6 +107,7 @@ var Nightlighter = class { 'changed::' + config.NIGHTLIGHT_GSETTINGS_PROPERTY, this._on_nightlight_status_change.bind(this) ); + log_debug('Listening to Night Light status changes...'); } } @@ -106,16 +115,18 @@ var Nightlighter = class { if ( this.nightlight_gsettings && this.nightlight_status_connect ) { this.nightlight_gsettings.disconnect(this.nightlight_status_connect); this.nightlight_status_connect = null; + log_debug('Stopped listening to Night Light status changes.'); } } _on_nightlight_status_change() { + log_debug('Night Light status has changed.'); this.enable(); - this.emit(); } _connect_to_dbus() { if ( !this.dbus_proxy ) { + log_debug('Connecting to DBus...'); const connection = Gio.bus_get_sync(Gio.BusType.SESSION, null); if ( connection === null ) { const message = _('Unable to connect to the session bus.'); @@ -140,6 +151,7 @@ var Nightlighter = class { _disconnect_from_dbus() { if ( this.dbus_proxy ) { this.dbus_proxy = null; + log_debug('Disconnected from DBus.'); } } @@ -149,17 +161,20 @@ var Nightlighter = class { 'g-properties-changed', this._on_nightlight_change.bind(this) ); + log_debug('Listening to Night Light changes...'); } } _stop_listening_to_nightlight_changes() { - if ( this.dbus_proxy && this.connect ) { + if ( this.dbus_proxy && this.nightlight_changes_connect ) { this.dbus_proxy.disconnect(this.nightlight_changes_connect); this.nightlight_changes_connect = null; + log_debug('Stopped listening to Night Light changes.'); } } _on_nightlight_change() { + log_debug('Night Light has changed.'); this.emit(); } diff --git a/src/modules/Switcher.js b/src/modules/Switcher.js index 04a1a0d..6d258f3 100644 --- a/src/modules/Switcher.js +++ b/src/modules/Switcher.js @@ -1,5 +1,5 @@ /* -Night Theme Switcher Gnome Shell extension +Night Shell Switcher Gnome Shell extension Copyright (C) 2020 Romain Vigier @@ -22,9 +22,10 @@ const { main } = imports.ui; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; +const { log_debug } = Me.imports.utils; + const { Nightlighter } = Me.imports.modules.Nightlighter; const { Themer } = Me.imports.modules.Themer; -const { Variants } = Me.imports.modules.Variants; /* @@ -44,21 +45,24 @@ explicitely selected, stops listening to changes and cleans itself. var Switcher = class { constructor() { + log_debug('Initializing extension...'); extensionUtils.initTranslations(config.EXT_UUID); + log_debug('Extension initialized.'); } enable() { + log_debug('Enabling extension...'); try { this.theme = new Themer(); this.theme.enable(); - this.variants = Variants.guess_from(this.theme.current); this.theme.subscribe(this._on_theme_change.bind(this)); this.nightlight = new Nightlighter(); this.nightlight.enable(); this.nightlight.subscribe(this._on_nightlight_change.bind(this)); - this._apply_theme_variant(); + this.theme.set_variant(this.nightlight.status); + log_debug('Extension enabled.'); } catch(e) { main.notifyError(config.EXT_NAME, e.message); @@ -66,38 +70,34 @@ var Switcher = class { } disable() { + log_debug('Disabling extension...'); try { this.theme.disable(); this.nightlight.disable(); - this.theme.current = this.variants.original; } catch(e) {} // Since we're disabling, we'll just ignore errors. finally { this.theme = null; - this.variants = null; this.nightlight = null; } + log_debug('Extension disabled.'); } - _apply_theme_variant() { - try { - this.theme.current = this.nightlight.status ? this.variants.night : this.variants.day; - } - catch(e) { - this.theme.current = this.variants.original; + async _await_extensionManager_init() { + log_debug('Waiting for the Extension Manager to be initialized...'); + while ( true ) { + if ( main.extensionManager._initialized ) return; + await null; } } _on_theme_change() { - const new_theme = this.theme.current; - if ( new_theme !== this.variants.day && new_theme !== this.variants.night ) { - this.variants = Variants.guess_from(new_theme); - } - this._apply_theme_variant(); + this.theme.update_variants(); + this.theme.set_variant(this.nightlight.status); } _on_nightlight_change() { - this._apply_theme_variant(); + this.theme.set_variant(this.nightlight.status); } } diff --git a/src/modules/Themer.js b/src/modules/Themer.js index 1c617f5..980a6d8 100644 --- a/src/modules/Themer.js +++ b/src/modules/Themer.js @@ -22,6 +22,10 @@ const { Gio } = imports.gi; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; +const { log_debug } = Me.imports.utils; + +const { Variants } = Me.imports.modules.Variants; + /* The Themer communicates with the system to get the current theme or set a new @@ -31,15 +35,24 @@ one. It can also be asked to listen to theme changes. var Themer = class { constructor() { + log_debug('Initializing Themer...'); this.gsettings = new Gio.Settings({ schema: config.THEME_GSETTINGS_SCHEMA }); + log_debug('Themer initialized.'); } enable() { + log_debug('Enabling Themer...'); this._listen_to_theme_changes(); + this._update_variants(); + this.emit(); + log_debug('Themer enabled.'); } disable() { + log_debug('Disabling Themer...'); this._stop_listening_to_theme_changes(); + this.reset_theme(); + log_debug('Themer disabled.'); } get current() { @@ -49,6 +62,7 @@ var Themer = class { set current(theme) { if ( theme !== this.current ) { this.gsettings.set_string(config.THEME_GSETTINGS_PROPERTY, theme); + log_debug(`Theme has been set to "${theme}"`); } } @@ -62,20 +76,55 @@ var Themer = class { } } + set_variant(night) { + if ( night !== undefined && this.variants ) { + this.current = night ? this.variants.night : this.variants.day; + } + } + + reset_theme() { + if ( this.variants ) { + this.current = this.variants.original; + log_debug('Theme has been reset to the user\'s original variant.') + } + } + + update_variants() { + if ( this.variants ) { + const new_theme = this.current; + if ( new_theme && new_theme !== this.variants.day && new_theme !== this.variants.night ) { + this._update_variants(); + } + } + } + + _update_variants() { + if ( this.current ) { + this.variants = Variants.guess_from(this.current); + log_debug('Variants updated: ' + JSON.stringify(this.variants)); + } + } + _listen_to_theme_changes() { - if ( !this.connect ) { - this.connect = this.gsettings.connect('changed::' + config.THEME_GSETTINGS_PROPERTY, this._on_theme_change.bind(this)); + if ( !this.theme_change_connect ) { + this.theme_change_connect = this.gsettings.connect( + 'changed::' + config.THEME_GSETTINGS_PROPERTY, + this._on_theme_change.bind(this) + ); + log_debug('Listening for theme changes...'); } } _stop_listening_to_theme_changes() { - if ( this.gsettings && this.connect ){ - this.gsettings.disconnect(this.connect); - this.connect = null; + if ( this.gsettings && this.theme_change_connect ){ + this.gsettings.disconnect(this.theme_change_connect); + this.theme_change_connect = null; + log_debug('Stopped listening for theme changes.'); } } _on_theme_change() { + log_debug('Theme has changed.'); this.emit(); } diff --git a/src/utils.js b/src/utils.js new file mode 100644 index 0000000..61559c3 --- /dev/null +++ b/src/utils.js @@ -0,0 +1,28 @@ +/* +Night Theme Switcher Gnome Shell extension + +Copyright (C) 2020 Romain Vigier + +This program is free software: you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation, either version 3 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program. If not, see . +*/ + +const { extensionUtils } = imports.misc; + +const Me = extensionUtils.getCurrentExtension(); +const config = Me.imports.config; + +var log_debug = function(message) { + if ( config.debug ) { + log(`[DEBUG] ${config.EXT_NAME}: ${message}`); + } +}