diff --git a/src/modules/Switcher.js b/src/modules/Switcher.js index 6659854..b3cfbb5 100644 --- a/src/modules/Switcher.js +++ b/src/modules/Switcher.js @@ -65,7 +65,9 @@ var Switcher = class { log_debug('Extension enabled.'); } catch(e) { - main.notifyError(Me.metadata.name, e.message); + if ( e.message ) { + main.notifyError(Me.metadata.name, e.message); + } } } @@ -84,12 +86,26 @@ var Switcher = class { } _on_theme_changed() { - this.theme.update_variants(); - this.theme.set_variant(this.time.current); + try { + this.theme.update_variants(); + this.theme.set_variant(this.time.current); + } + catch(e) { + if ( e.message ) { + main.notifyError(Me.metadata.name, e.message); + } + } } _on_time_changed() { - this.theme.set_variant(this.time.current); + try { + this.theme.set_variant(this.time.current); + } + catch(e) { + if ( e.message ) { + main.notifyError(Me.metadata.name, e.message); + } + } } } diff --git a/src/modules/Themer.js b/src/modules/Themer.js index 0d3d093..1ac6cf4 100644 --- a/src/modules/Themer.js +++ b/src/modules/Themer.js @@ -22,11 +22,15 @@ const { main } = imports.ui; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; +const utils = Me.imports.utils; const { log_debug } = Me.imports.utils; const { Variants } = Me.imports.modules.Variants; +const Gettext = imports.gettext.domain(Me.metadata.uuid); +const _ = Gettext.gettext; + /* The Themer communicates with the system to get the current theme or set a new @@ -44,23 +48,44 @@ var Themer = class { } enable() { - log_debug('Enabling Themer...'); - this.ready = false; - this._listen_to_theme_changes(); - this.update_variants(); - this.ready = true; - this.emit(); - log_debug('Themer enabled.'); + try { + log_debug('Enabling Themer...'); + this.ready = false; + this._listen_to_force_manual_status(); + if ( this._is_force_manual_enabled() ) { + log_debug('Using manually set variants.'); + this._listen_to_prefs_theme_change(); + } + else { + log_debug('Automatically detecting variants.'); + this._listen_to_theme_changes(); + this.update_variants(); + } + this.ready = true; + this.emit(); + log_debug('Themer enabled.'); + } + catch(e) { + if ( e.message ) { + main.notifyError(Me.metadata.name, e.message); + } + } } disable() { log_debug('Disabling Themer...'); - this._stop_listening_to_theme_changes(); - // GNOME Shell disables extensions when locking the screen. We'll only - // reset the theme if the user disables the extension to prevent - // flickering when unlocking. - if ( !main.screenShield.locked ) { - this.reset_theme(); + this._stop_listening_to_force_manual_status(); + if ( this._is_force_manual_enabled() ) { + this._stop_listening_to_prefs_theme_change(); + } + else { + this._stop_listening_to_theme_changes(); + // GNOME Shell disables extensions when locking the screen. We'll + // only reset the theme if the user disables the extension to + // prevent flickering when unlocking. + if ( !main.screenShield.locked ) { + this.reset_theme(); + } } log_debug('Themer disabled.'); } @@ -99,7 +124,7 @@ var Themer = class { } update_variants() { - if ( !this._are_variants_up_to_date() ) { + if ( !this._are_variants_up_to_date() && !this._is_force_manual_enabled() ) { this._update_variants(); } } @@ -107,8 +132,14 @@ var Themer = class { _update_variants() { if ( this.current_theme ) { const variants = Variants.guess_from(this.current_theme); - variants.forEach( (theme, variant) => this.settings.set_string(`theme-${variant}`, theme) ); - log_debug(`Variants updated: {day: "${variants.get('day')}", night: "${variants.get('night')}"}`); + if ( utils.is_theme_installed(variants.get('day')) && utils.is_theme_installed(variants.get('night')) ) { + variants.forEach( (theme, variant) => this.settings.set_string(`theme-${variant}`, theme) ); + log_debug(`Variants updated: {day: "${variants.get('day')}", night: "${variants.get('night')}"}`); + } + else { + const message = _('The extension cannot detect the day and night variants for the "%s" theme. Please choose another theme or manually set variants in the extension preferences.').format(variants.get('original')); + throw new Error(message); + } } } @@ -116,6 +147,33 @@ var Themer = class { return ( this.current_theme === this.settings.get_string('theme-day') || this.current_theme === this.settings.get_string('theme-night') ); } + _is_force_manual_enabled() { + return this.settings.get_boolean('theme-force-manual'); + } + + _listen_to_force_manual_status() { + if ( !this.force_manual_status_connect ) { + this.force_manual_status_connect = this.settings.connect( + 'changed::theme-force-manual', + this._on_force_manual_status_changed.bind(this) + ); + log_debug('Listening to manual variants status changes...'); + } + } + + _stop_listening_to_force_manual_status() { + if ( this.settings && this.force_manual_status_connect ) { + this.settings.disconnect(this.force_manual_status_connect); + this.force_manual_status_connect = null; + log_debug('Stopped listening to manual variants status changes.'); + } + } + + _on_force_manual_status_changed() { + log_debug('Manual variants status has changed.'); + this.enable(); + } + _listen_to_theme_changes() { if ( !this.theme_change_connect ) { this.theme_change_connect = this.theme_gsettings.connect( @@ -136,7 +194,28 @@ var Themer = class { _on_theme_changed() { log_debug(`Theme has changed to "${this.current_theme}".`); - this.emit(); + this.ready ? this.emit() : this.enable(); + } + + _listen_to_prefs_theme_change() { + if ( !this.prefs_theme_change_connect ) { + this.prefs_theme_change_connect = new Map(); + ['day', 'night'].forEach(time => { + this.prefs_theme_change_connect.set(time, this.settings.connect( + `changed::theme-${time}`, + this._on_theme_changed.bind(this) + )); + log_debug(`Listening for ${time} theme preference changes...`); + }); + } + } + + _stop_listening_to_prefs_theme_change() { + if ( this.settings && this.prefs_theme_change_connect ) { + this.prefs_theme_change_connect.forEach(connect => this.settings.disconnect(connect)); + this.prefs_theme_change_connect = null; + log_debug('Stopped listening to theme preferences changes.'); + } } } diff --git a/src/modules/Timer.js b/src/modules/Timer.js index b5ffcd4..bc6c362 100644 --- a/src/modules/Timer.js +++ b/src/modules/Timer.js @@ -49,7 +49,7 @@ var Timer = class { this.settings = extensionUtils.getSettings(); this.nightlight_gsettings = new Gio.Settings({ schema: config.NIGHTLIGHT_GSETTINGS_SCHEMA }); this.location_gsettings = new Gio.Settings({ schema: config.LOCATION_GSETTINGS_SCHEMA }); - log_debug('Nightlighter initialized.'); + log_debug('Timer initialized.'); } enable() { diff --git a/src/po/fr.po b/src/po/fr.po index 23d66da..2cd63a4 100644 --- a/src/po/fr.po +++ b/src/po/fr.po @@ -7,8 +7,8 @@ msgid "" msgstr "" "Project-Id-Version: Night Theme Switcher 7\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-06 16:40+0200\n" -"PO-Revision-Date: 2020-05-06 16:40+0200\n" +"POT-Creation-Date: 2020-05-09 10:52+0200\n" +"PO-Revision-Date: 2020-05-09 10:58+0200\n" "Last-Translator: Romain Vigier \n" "Language-Team: French - France \n" "Language: fr_FR\n" @@ -18,7 +18,43 @@ msgstr "" "Plural-Forms: nplurals=2; plural=(n > 1)\n" "X-Generator: Gtranslator 3.36.0\n" -#: src/prefs.js:58 +#: src/prefs.js:65 +msgid "Theme" +msgstr "Thème" + +#: src/prefs.js:71 +msgid "" +"The extension will try to automatically detect the day and night variants of " +"your theme.\n" +"If the theme you use isn't supported, please submit a request.\n" +"If you prefer, you can manually set variants." +msgstr "" +"L’extension essayera de détecter automatiquement les variantes diurne et " +"nocturne de votre thème.\n" +"Si le thème que vous utilisez n’est pas supporté, merci d’en " +"faire la requête.\n" +"Si vous préférez, vous pouvez définir manuellement les variantes." + +#: src/prefs.js:107 +msgid "Manual variants" +msgstr "Variantes manuelles" + +#: src/prefs.js:151 +msgid "Day variant" +msgstr "Variante diurne" + +#: src/prefs.js:152 +msgid "Night variant" +msgstr "Variante nocturne" + +#: src/prefs.js:197 +msgid "Schedule" +msgstr "Horaires" + +#: src/prefs.js:203 msgid "" "The extension will try to use Night Light or Location Services to " "automatically set your current sunrise and sunset times if they are " @@ -30,49 +66,60 @@ msgstr "" "de coucher du soleil.\n" "Si vous préférez, vous pouvez définir manuellement un horaire." -#: src/prefs.js:93 -msgid "Manual schedule:" -msgstr "Horaire manuel :" +#: src/prefs.js:238 +msgid "Manual schedule" +msgstr "Horaire manuel" -#: src/prefs.js:138 -msgid "Sunrise: " -msgstr "Lever du soleil :" +#: src/prefs.js:283 +msgid "Sunrise" +msgstr "Lever du soleil" -#: src/prefs.js:139 -msgid "Sunset: " -msgstr "Coucher du soleil :" +#: src/prefs.js:284 +msgid "Sunset" +msgstr "Coucher du soleil" -#: src/modules/Timer.js:268 +#: src/modules/Themer.js:140 +#, javascript-format +msgid "" +"The extension cannot detect the day and night variants for the \"%s\" theme. " +"Please choose another theme or manually set variants in the extension " +"preferences." +msgstr "" +"L’extension ne parvient pas à détecter les variantes diurne et nocturne pour " +"le thème \"%s\". Merci de sélectionner un autre thème ou de définir " +"manuellement les variantes dans les préférences de l’extension." + +#: src/modules/Timer.js:269 msgid "Unable to connect to Color DBus proxy." msgstr "Impossible de se connecter à la passerelle DBus Color." -#: src/modules/Timer.js:330 +#: src/modules/Timer.js:331 msgid "Unable to connect to GeoClue Manager DBus proxy." msgstr "Impossible de se connecter à la passerelle DBus GeoClue Manager." -#: src/modules/Timer.js:340 +#: src/modules/Timer.js:341 msgid "Unable to get a GeoClue Client." msgstr "Impossible d’obtenir un client GeoClue." -#: src/modules/Timer.js:358 +#: src/modules/Timer.js:359 msgid "Unable to connect to GeoClue Client DBus proxy." msgstr "Impossible de se connecter à la passerelle DBus GeoClue Client." -#: src/modules/Timer.js:417 +#: src/modules/Timer.js:422 msgid "Unable to connect to GeoClue Location DBus proxy." msgstr "Impossible de se connecter à la passerelle DBus GeoClue Location." -#: src/modules/Timer.js:447 +#: src/modules/Timer.js:450 msgid "Unable to get current location." msgstr "Impossible d’obtenir l’emplacement actuel." #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:6 -msgid "Original theme" -msgstr "Thème original" +msgid "Use manual variants" +msgstr "Utiliser des variantes manuelles" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:7 -msgid "The theme to restore if the extension is disabled" -msgstr "Thème à restaurer si l’extension est désactivée" +msgid "Disable automatic variants detection" +msgstr "Désactive la détection automatique des variantes" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:11 msgid "Day theme" @@ -91,37 +138,54 @@ msgid "The theme to use during nighttime" msgstr "Thème à utiliser pendant la nuit" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:21 +msgid "Original theme" +msgstr "Thème original" + +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:22 +msgid "The theme to restore if the extension is disabled" +msgstr "Thème à restaurer si l’extension est désactivée" + +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:26 msgid "Use manual schedule" msgstr "Utiliser un horaire manuel" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:22 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:27 msgid "Disable automatic times detection" msgstr "Désactive la détection automatique des horaires" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:31 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:36 msgid "Time source" msgstr "Source des horaires" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:32 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:37 msgid "The source used to check current time" msgstr "Source utilisée pour vérifier les horaires" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:36 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:41 msgid "Sunrise time" msgstr "Heure du lever" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:37 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:42 msgid "When the day starts" msgstr "Quand le jour se lève" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:41 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:46 msgid "Sunset time" msgstr "Heure du coucher" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:42 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:47 msgid "When the day ends" msgstr "Quand le jour se couche" +#~ msgid "Manual schedule:" +#~ msgstr "Horaire manuel :" + +#~ msgid "Sunrise: " +#~ msgstr "Lever du soleil :" + +#~ msgid "Sunset: " +#~ msgstr "Coucher du soleil :" + #~ msgid "" #~ "Night Light or Location Services must be enabled to use this extension. " #~ "Please enable it in your system settings." diff --git a/src/po/nightthemeswitcher@romainvigier.fr.pot b/src/po/nightthemeswitcher@romainvigier.fr.pot index 073ddb5..9849bc5 100644 --- a/src/po/nightthemeswitcher@romainvigier.fr.pot +++ b/src/po/nightthemeswitcher@romainvigier.fr.pot @@ -6,9 +6,9 @@ #, fuzzy msgid "" msgstr "" -"Project-Id-Version: Night Theme Switcher 25\n" +"Project-Id-Version: Night Theme Switcher 26\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-05-06 16:40+0200\n" +"POT-Creation-Date: 2020-05-09 10:52+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,7 +17,37 @@ msgstr "" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: src/prefs.js:58 +#: src/prefs.js:65 +msgid "Theme" +msgstr "" + +#: src/prefs.js:71 +msgid "" +"The extension will try to automatically detect the day and night variants of " +"your theme.\n" +"If the theme you use isn't supported, please submit a request.\n" +"If you prefer, you can manually set variants." +msgstr "" + +#: src/prefs.js:107 +msgid "Manual variants" +msgstr "" + +#: src/prefs.js:151 +msgid "Day variant" +msgstr "" + +#: src/prefs.js:152 +msgid "Night variant" +msgstr "" + +#: src/prefs.js:197 +msgid "Schedule" +msgstr "" + +#: src/prefs.js:203 msgid "" "The extension will try to use Night Light or Location Services to " "automatically set your current sunrise and sunset times if they are " @@ -25,48 +55,56 @@ msgid "" "If you prefer, you can set a manual schedule." msgstr "" -#: src/prefs.js:93 -msgid "Manual schedule:" +#: src/prefs.js:238 +msgid "Manual schedule" msgstr "" -#: src/prefs.js:138 -msgid "Sunrise: " +#: src/prefs.js:283 +msgid "Sunrise" msgstr "" -#: src/prefs.js:139 -msgid "Sunset: " +#: src/prefs.js:284 +msgid "Sunset" msgstr "" -#: src/modules/Timer.js:268 +#: src/modules/Themer.js:140 +#, javascript-format +msgid "" +"The extension cannot detect the day and night variants for the \"%s\" theme. " +"Please choose another theme or manually set variants in the extension " +"preferences." +msgstr "" + +#: src/modules/Timer.js:269 msgid "Unable to connect to Color DBus proxy." msgstr "" -#: src/modules/Timer.js:330 +#: src/modules/Timer.js:331 msgid "Unable to connect to GeoClue Manager DBus proxy." msgstr "" -#: src/modules/Timer.js:340 +#: src/modules/Timer.js:341 msgid "Unable to get a GeoClue Client." msgstr "" -#: src/modules/Timer.js:358 +#: src/modules/Timer.js:359 msgid "Unable to connect to GeoClue Client DBus proxy." msgstr "" -#: src/modules/Timer.js:417 +#: src/modules/Timer.js:422 msgid "Unable to connect to GeoClue Location DBus proxy." msgstr "" -#: src/modules/Timer.js:447 +#: src/modules/Timer.js:450 msgid "Unable to get current location." msgstr "" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:6 -msgid "Original theme" +msgid "Use manual variants" msgstr "" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:7 -msgid "The theme to restore if the extension is disabled" +msgid "Disable automatic variants detection" msgstr "" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:11 @@ -86,33 +124,41 @@ msgid "The theme to use during nighttime" msgstr "" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:21 -msgid "Use manual schedule" +msgid "Original theme" msgstr "" #: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:22 +msgid "The theme to restore if the extension is disabled" +msgstr "" + +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:26 +msgid "Use manual schedule" +msgstr "" + +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:27 msgid "Disable automatic times detection" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:31 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:36 msgid "Time source" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:32 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:37 msgid "The source used to check current time" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:36 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:41 msgid "Sunrise time" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:37 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:42 msgid "When the day starts" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:41 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:46 msgid "Sunset time" msgstr "" -#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:42 +#: src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml:47 msgid "When the day ends" msgstr "" diff --git a/src/prefs.js b/src/prefs.js index 3018c64..16e70c2 100644 --- a/src/prefs.js +++ b/src/prefs.js @@ -23,6 +23,7 @@ const { extensionUtils } = imports.misc; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; +const utils = Me.imports.utils; const { log_debug } = Me.imports.utils; @@ -41,43 +42,187 @@ function init() { } function buildPrefsWidget() { - const prefs_widget = new Gtk.Box({ + const prefs_widget = new Gtk.Notebook({ + visible: true + }); + + /* + Theme preferences + */ + + const prefs_theme_box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, spacing: 30, margin_top: 30, margin_end: 36, margin_start: 36, + margin_bottom: 36, valign: Gtk.Align.START, halign: Gtk.Align.CENTER, - width_request: 450, - margin_bottom: 36, visible: true - }) + }); + const prefs_theme_box_label = new Gtk.Label({ + label: _('Theme'), + visible: true + }); + prefs_widget.append_page(prefs_theme_box, prefs_theme_box_label); - const prefs_info = new Gtk.Label({ - label: _('The extension will try to use Night Light or Location Services to automatically set your current sunrise and sunset times if they are enabled.\nIf you prefer, you can set a manual schedule.'), - wrap: true, + const prefs_theme_info = new Gtk.Label({ + label: _('The extension will try to automatically detect the day and night variants of your theme.\nIf the theme you use isn\'t supported, please submit a request.\nIf you prefer, you can manually set variants.'), + use_markup: true, max_width_chars: 60, - halign: Gtk.Align.FILL, + wrap: true, + halign: Gtk.Align.START, opacity: 0.7, visible: true }); - prefs_widget.pack_start(prefs_info, true, true, 0); + prefs_theme_box.pack_start(prefs_theme_info, false, false, 0); - const prefs_frame = new Gtk.Frame({ + const prefs_theme_frame = new Gtk.Frame({ can_focus: false, visible: true }); - prefs_widget.pack_start(prefs_frame, true, true, 0); + prefs_theme_box.pack_start(prefs_theme_frame, false, false, 0); - const prefs_list = new Gtk.ListBox({ + const prefs_theme_list = new Gtk.ListBox({ border_width: 0, margin: 0, can_focus: false, selection_mode: Gtk.SelectionMode.NONE, visible: true }); - prefs_frame.add(prefs_list); + prefs_theme_frame.add(prefs_theme_list); + + // Force manual toggle + const theme_force_manual_box = new Gtk.Box({ + margin: 16, + spacing: 12, + orientation: Gtk.Orientation.HORIZONTAL, + can_focus: false, + visible: true + }); + prefs_theme_list.add(theme_force_manual_box); + + const theme_force_manual_label = new Gtk.Label({ + label: _('Manual variants'), + halign: Gtk.Align.START, + visible: true + }); + theme_force_manual_box.pack_start(theme_force_manual_label, true, true, 0); + + const theme_force_manual_toggle = new Gtk.Switch({ + active: this.settings.get_boolean('time-force-manual'), + halign: Gtk.Align.END, + visible: true + }); + settings.bind( + 'theme-force-manual', + theme_force_manual_toggle, + 'active', + Gio.SettingsBindFlags.DEFAULT + ); + theme_force_manual_box.pack_start(theme_force_manual_toggle, false, false, 0); + + prefs_theme_list.add(new Gtk.Separator({ + orientation: Gtk.Orientation.VERTICAL, + can_focus: false, + visible: true + })); + + ['day', 'night'].forEach((time, i, times) => { + const variant_box = new Gtk.Box({ + margin: 16, + spacing: 12, + orientation: Gtk.Orientation.HORIZONTAL, + can_focus: false, + visible: true + }); + prefs_theme_list.add(variant_box); + + if ( i < times.length - 1 ) { + prefs_theme_list.add(new Gtk.Separator({ + orientation: Gtk.Orientation.VERTICAL, + can_focus: false, + visible: true + })); + } + + const variant_labels = new Map([ + ['day', _('Day variant')], + ['night', _('Night variant')] + ]); + const variant_label = new Gtk.Label({ + label: variant_labels.get(time), + halign: Gtk.Align.START, + visible: true + }) + variant_box.pack_start(variant_label, true, true, 0); + + const variant_combo = new Gtk.ComboBoxText({ + visible: true + }); + const themes = Array.from(utils.get_installed_themes()).sort(); + themes.forEach(theme => variant_combo.append(theme, theme)); + settings.bind( + `theme-${time}`, + variant_combo, + 'active-id', + Gio.SettingsBindFlags.DEFAULT + ); + settings.bind( + 'theme-force-manual', + variant_combo, + 'sensitive', + Gio.SettingsBindFlags.DEFAULT + ); + variant_box.pack_start(variant_combo, false, false, 0); + + }); + + /* + Schedule preferences + */ + const prefs_time_box = new Gtk.Box({ + orientation: Gtk.Orientation.VERTICAL, + spacing: 30, + margin_top: 30, + margin_end: 36, + margin_start: 36, + margin_bottom: 36, + valign: Gtk.Align.START, + halign: Gtk.Align.CENTER, + visible: true + }); + const prefs_time_box_label = new Gtk.Label({ + label: _('Schedule'), + visible: true + }); + prefs_widget.append_page(prefs_time_box, prefs_time_box_label); + + const prefs_time_info = new Gtk.Label({ + label: _('The extension will try to use Night Light or Location Services to automatically set your current sunrise and sunset times if they are enabled.\nIf you prefer, you can set a manual schedule.'), + max_width_chars: 60, + wrap: true, + halign: Gtk.Align.START, + opacity: 0.7, + visible: true + }); + prefs_time_box.pack_start(prefs_time_info, false, false, 0); + + const prefs_time_frame = new Gtk.Frame({ + can_focus: false, + visible: true + }); + prefs_time_box.pack_start(prefs_time_frame, false, false, 0); + + const prefs_time_list = new Gtk.ListBox({ + border_width: 0, + margin: 0, + can_focus: false, + selection_mode: Gtk.SelectionMode.NONE, + visible: true + }); + prefs_time_frame.add(prefs_time_list); // Force manual toggle const force_manual_box = new Gtk.Box({ @@ -87,10 +232,10 @@ function buildPrefsWidget() { can_focus: false, visible: true }); - prefs_list.add(force_manual_box); + prefs_time_list.add(force_manual_box); const force_manual_label = new Gtk.Label({ - label: _('Manual schedule:'), + label: _('Manual schedule'), halign: Gtk.Align.START, visible: true }); @@ -109,7 +254,7 @@ function buildPrefsWidget() { ); force_manual_box.pack_start(force_manual_toggle, false, false, 0); - prefs_list.add(new Gtk.Separator({ + prefs_time_list.add(new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL, can_focus: false, visible: true @@ -124,10 +269,10 @@ function buildPrefsWidget() { can_focus: false, visible: true }); - prefs_list.add(time_box); + prefs_time_list.add(time_box); if ( i < suntimes.length - 1 ) { - prefs_list.add(new Gtk.Separator({ + prefs_time_list.add(new Gtk.Separator({ orientation: Gtk.Orientation.VERTICAL, can_focus: false, visible: true @@ -135,8 +280,8 @@ function buildPrefsWidget() { } const time_labels = new Map([ - ['sunrise', _('Sunrise: ')], - ['sunset', _('Sunset: ')] + ['sunrise', _('Sunrise')], + ['sunset', _('Sunset')] ]); const time_label = new Gtk.Label({ label: time_labels.get(suntime), diff --git a/src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml b/src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml index 7597ae4..569918e 100644 --- a/src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml +++ b/src/schemas/org.gnome.shell.extensions.nightthemeswitcher.gschema.xml @@ -1,21 +1,26 @@ - - "" - Original theme - The theme to restore if the extension is disabled + + false + Use manual variants + Disable automatic variants detection - "" + "Adwaita" Day theme The theme to use during daytime - "" + "Adwaita-dark" Night theme The theme to use during nighttime + + "" + Original theme + The theme to restore if the extension is disabled + false Use manual schedule diff --git a/src/utils.js b/src/utils.js index eb66e5d..c16b566 100644 --- a/src/utils.js +++ b/src/utils.js @@ -16,13 +16,60 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ +const { Gio, GLib, Gtk } = imports.gi; const { extensionUtils } = imports.misc; const Me = extensionUtils.getCurrentExtension(); const config = Me.imports.config; + var log_debug = function(message) { if ( config.debug ) { log(`[DEBUG] ${Me.metadata.name}: ${message}`); } } + +var get_installed_themes = function() { + const themes = new Set(['Adwaita', 'HighContrast', 'HighContrastInverse']); + + const data_dirs_paths = GLib.get_system_data_dirs().concat(GLib.get_user_data_dir()); + const themes_dirs_paths = data_dirs_paths.map(path => GLib.build_filenamev([path, 'themes'])); + themes_dirs_paths.push(GLib.build_filenamev([GLib.get_home_dir(), '.themes'])); + + themes_dirs_paths.forEach(themes_dir_path => { + const themes_dir = Gio.File.new_for_path(themes_dir_path); + + if ( themes_dir.query_file_type(Gio.FileQueryInfoFlags.NONE, null) !== Gio.FileType.DIRECTORY ) { + return; + } + + const theme_dirs_enumerator = themes_dir.enumerate_children('', Gio.FileQueryInfoFlags.NONE, null); + + while ( true ) { + let theme_dir_info = theme_dirs_enumerator.next_file(null); + + if ( theme_dir_info === null ) { + break; + } + + const theme_dir = theme_dirs_enumerator.get_child(theme_dir_info); + + [0, Gtk.MINOR_VERSION].forEach(gtk_version => { + if ( gtk_version % 2 ) { + gtk_version += 1; + } + const css_file = Gio.File.new_for_path(GLib.build_filenamev([theme_dir.get_path(), `gtk-3.${gtk_version}`, 'gtk.css'])); + if ( css_file.query_exists(null) ) { + themes.add(theme_dir.get_basename()); + } + }) + } + theme_dirs_enumerator.close(null); + }); + + return themes; +} + +var is_theme_installed = function(theme) { + return get_installed_themes().has(theme); +}