From 56b9e537150cc3baae063f98567312eea1d8770a Mon Sep 17 00:00:00 2001 From: Michael Cardillo Date: Thu, 19 Oct 2023 01:13:49 -0700 Subject: [PATCH 1/2] Gnome 45 Updates --- BWClipboard.js | 7 +- blur.js | 60 +++--- carousel.js | 31 +-- convenience.js | 45 +---- extension.js | 112 ++++++----- metadata.json | 2 +- prefs.js | 514 +++++++++++++++++++++++++------------------------ thumbnail.js | 6 +- utils.js | 153 +++++++-------- 9 files changed, 450 insertions(+), 480 deletions(-) diff --git a/BWClipboard.js b/BWClipboard.js index b4e7d67a..279c65e3 100644 --- a/BWClipboard.js +++ b/BWClipboard.js @@ -6,11 +6,12 @@ // (at your option) any later version. // See the GNU General Public License, version 3 or later for details. -const St = imports.gi.St; +import St from 'gi://St'; +import Gio from 'gi://Gio'; + const CLIPBOARD_TYPE = St.ClipboardType.CLIPBOARD; -const Gio = imports.gi.Gio; -var BWClipboard = class BWClipboard { +export default class BWClipboard { constructor() { this.clipboard = St.Clipboard.get_default(); } diff --git a/blur.js b/blur.js index 60b7018a..7f950713 100644 --- a/blur.js +++ b/blur.js @@ -9,22 +9,22 @@ // This code based on https://github.com/PRATAP-KUMAR/Control_Blur_Effect_On_Lock_Screen // and https://github.com/sunwxg/gnome-shell-extension-unlockDialogBackground -const St = imports.gi.St; -const Main = imports.ui.main; -const Shell = imports.gi.Shell; -const Background = imports.ui.background; -const ScreenShield = imports.ui.screenShield; -const UnlockDialog = imports.ui.unlockDialog.UnlockDialog; -const ExtensionUtils = imports.misc.extensionUtils; -var _updateBackgroundEffects = UnlockDialog.prototype._updateBackgroundEffects; -var _showClock = UnlockDialog.prototype._showClock; -var _showPrompt = UnlockDialog.prototype._showPrompt; -const Me = ExtensionUtils.getCurrentExtension(); -const Utils = Me.imports.utils; - -var shellVersionMajor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[0]); -var shellVersionMinor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[1]); -var shellVersionPoint = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[2]); +import St from 'gi://St'; +import Shell from 'gi://Shell'; +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as Background from 'resource:///org/gnome/shell/ui/background.js'; +import * as ScreenShield from 'resource:///org/gnome/shell/ui/screenShield.js'; +import * as UnlockDialog from 'resource:///org/gnome/shell/ui/unlockDialog.js'; +import * as Config from 'resource:///org/gnome/shell/misc/config.js'; +import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js'; +var _updateBackgroundEffects = UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects; +var _showClock = UnlockDialog.UnlockDialog.prototype._showClock; +var _showPrompt = UnlockDialog.UnlockDialog.prototype._showPrompt; +import * as Utils from './utils.js'; + +var shellVersionMajor = parseInt(Config.PACKAGE_VERSION.split('.')[0]); +var shellVersionMinor = parseInt(Config.PACKAGE_VERSION.split('.')[1]); +var shellVersionPoint = parseInt(Config.PACKAGE_VERSION.split('.')[2]); // default BWP mild blur var BWP_BLUR_SIGMA = 2; @@ -86,7 +86,7 @@ function _showPrompt_BWP() { this._updateBackgroundEffects(); } -var Blur = class Blur { +export default class Blur { constructor() { this.enabled = false; log('Bing Wallpaper adjustable blur is '+supportedVersion()?'available':'not available'); @@ -122,15 +122,15 @@ var Blur = class Blur { _enable() { if (supportedVersion()) { - log("Blur._enable() called on GNOME "+imports.misc.config.PACKAGE_VERSION); - UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects_BWP; + log("Blur._enable() called on GNOME "+Config.PACKAGE_VERSION); + UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects_BWP; // we override _showClock and _showPrompt to patch in updates to blur effect before calling the GNOME functions - UnlockDialog.prototype._showClock = _showClock_BWP; - UnlockDialog.prototype._showPrompt = _showPrompt_BWP; + UnlockDialog.UnlockDialog.prototype._showClock = _showClock_BWP; + UnlockDialog.UnlockDialog.prototype._showPrompt = _showPrompt_BWP; // this are the original functions which we call into from our versions above - UnlockDialog.prototype._showClock_GNOME = _showClock; - UnlockDialog.prototype._showPrompt_GNOME = _showPrompt; + UnlockDialog.UnlockDialog.prototype._showClock_GNOME = _showClock; + UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME = _showPrompt; } this.enabled = true; @@ -142,14 +142,14 @@ var Blur = class Blur { log("_lockscreen_blur_disable() called"); if (supportedVersion()) { // restore default functions - UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects; - UnlockDialog.prototype._showClock = _showClock; - UnlockDialog.prototype._showPrompt = _showPrompt; + UnlockDialog.UnlockDialog.prototype._updateBackgroundEffects = _updateBackgroundEffects; + UnlockDialog.UnlockDialog.prototype._showClock = _showClock; + UnlockDialog.UnlockDialog.prototype._showPrompt = _showPrompt; // clean up unused functions we created - UnlockDialog.prototype._showClock_GNOME = null; - delete UnlockDialog.prototype._showClock_GNOME; - UnlockDialog.prototype._showPrompt_GNOME = null; - delete UnlockDialog.prototype._showPrompt_GNOME; + UnlockDialog.UnlockDialog.prototype._showClock_GNOME = null; + delete UnlockDialog.UnlockDialog.prototype._showClock_GNOME; + UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME = null; + delete UnlockDialog.UnlockDialog.prototype._showPrompt_GNOME; } this.enabled = false; } diff --git a/carousel.js b/carousel.js index 97c36b93..e03de222 100644 --- a/carousel.js +++ b/carousel.js @@ -7,18 +7,22 @@ // See the GNU General Public License, version 3 or later for details. // Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod -const { Gtk, Gdk, GdkPixbuf, Gio, GLib } = imports.gi; -const Me = imports.misc.extensionUtils.getCurrentExtension(); -const Utils = Me.imports.utils; +import Gtk from 'gi://Gtk'; +import Gdk from 'gi://Gdk'; +import GdkPixbuf from 'gi://GdkPixbuf'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import * as Utils from './utils.js'; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; + + -const Gettext = imports.gettext.domain('BingWallpaper'); -const _ = Gettext.gettext; const default_dimensions = [30, 30, 1650, 800]; // TODO: pull from and save dimensions to settings, but perhaps verify that dimensions are ok const GALLERY_THUMB_WIDTH = 320; const GALLERY_THUMB_HEIGHT = 180; -var Carousel = class Carousel { +export default class Carousel { constructor(settings, button = null, callbackfunc = null, prefs_flowbox = null) { //create_gallery(widget, settings); this.settings = settings; @@ -28,6 +32,7 @@ var Carousel = class Carousel { this.window = null; this.imageList = Utils.imageListSortByDate(Utils.getImageList(this.settings)).reverse(); // get images and reverse order this.searchEntry = null; + this.extensionPath = ExtensionPreferences.lookupByUUID('BingWallpaper@ineffable-gmail.com').path this.log('create carousel...'); @@ -65,12 +70,12 @@ var Carousel = class Carousel { win.set_title(title); if (Gtk.get_major_version() < 4) { - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ['carouselScrollable']); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel.ui', ['carouselScrollable']); flowBox = buildable.get_object('carouselFlowBox'); win.add(buildable.get_object('carouselScrollable')); } else { - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ['carouselViewPort']); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ['carouselViewPort']); flowBox = buildable.get_object('carouselFlowBox'); win.set_child(buildable.get_object('carouselScrollable')); } @@ -100,9 +105,9 @@ var Carousel = class Carousel { // grab appropriate object from UI file if (Gtk.get_major_version() < 4) - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ["flowBoxChild"]); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel.ui', ["flowBoxChild"]); else - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxChild"]); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ["flowBoxChild"]); // assign variables to the UI objects we've just loaded let galleryImage = buildable.get_object('galleryImage'); @@ -187,10 +192,10 @@ var Carousel = class Carousel { // grab appropriate object from UI file if (Gtk.get_major_version() < 4) { - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel.ui', ["flowBoxRandom"]); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel.ui', ["flowBoxRandom"]); } else { - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxRandom"]); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ["flowBoxRandom"]); } let randomLabel = buildable.get_object('randomLabel'); @@ -214,7 +219,7 @@ var Carousel = class Carousel { // grab appropriate object from UI file if (Gtk.get_major_version() >= 4) { - buildable.add_objects_from_file(Me.dir.get_path() + '/ui/carousel4.ui', ["flowBoxPlaceholder"]); + buildable.add_objects_from_file(this.extensionPath + '/ui/carousel4.ui', ["flowBoxPlaceholder"]); } else { return null; diff --git a/convenience.js b/convenience.js index 3391ced8..bcb6f4d3 100644 --- a/convenience.js +++ b/convenience.js @@ -25,7 +25,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -const Config = imports.misc.config; const versionArray = (v) => v.split(".").map(Number); @@ -44,7 +43,7 @@ function versionEqual(a, b) { , true); } -function versionGreater(a, b) { +export function versionGreater(a, b) { const diff = zip(versionArray(a), versionArray(b), 0).find(([a, b]) => a !== b); if (!diff) { return false; @@ -53,42 +52,10 @@ function versionGreater(a, b) { return x > y; } -function versionSmaller(a, b) { - return (!versionEqual(a, b)) && (!versionGreater(a, b)); -} - -function currentVersion() { - return ''+Config.PACKAGE_VERSION.replace(/(alpha|beta)/,'0'); -} - -function currentVersionEqual(v) { - return versionEqual(currentVersion(), v); -} - -function currentVersionGreater(v) { - return versionGreater(currentVersion(), v); -} - -function currentVersionGreaterEqual(v) { - return versionEqual(currentVersion(), v) - || versionGreater(currentVersion(), v); -} - -function currentVersionSmaller(v) { - return versionSmaller(currentVersion(), v); -} - -function currentVersionSmallerEqual(v) { - return versionEqual(currentVersion(), v) - && (!versionGreater(currentVersion(), v)); +export function versionGreaterEqual(a,b) { + return versionEqual(a, b) || versionGreater(a, b); } -var exports = { - currentVersion, - currentVersionEqual, - currentVersionGreater, - currentVersionGreaterEqual, - currentVersionSmaller, - currentVersionSmallerEqual -}; - +function versionSmaller(a, b) { + return (!versionEqual(a, b)) && (!versionGreater(a, b)); +} \ No newline at end of file diff --git a/extension.js b/extension.js index ba0c2068..3b81dcd1 100644 --- a/extension.js +++ b/extension.js @@ -7,23 +7,29 @@ // See the GNU General Public License, version 3 or later for details. // Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod -const {St, Soup, Gio, GObject, GLib, Clutter, Cogl, Gdk} = imports.gi; -const Main = imports.ui.main; -const MessageTray = imports.ui.messageTray; -const Util = imports.misc.util; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; +import St from 'gi://St'; +import Soup from 'gi://Soup'; +import Gio from 'gi://Gio'; +import GObject from 'gi://GObject'; +import GLib from 'gi://GLib'; +import Clutter from 'gi://Clutter'; +import Cogl from 'gi://Cogl'; +import Gdk from 'gi://Gdk'; + +import * as Main from 'resource:///org/gnome/shell/ui/main.js'; +import * as MessageTray from 'resource:///org/gnome/shell/ui/messageTray.js'; +import * as Util from 'resource:///org/gnome/shell/misc/util.js'; +import {Button} from 'resource:///org/gnome/shell/ui/panelMenu.js'; +import * as PopupMenu from 'resource:///org/gnome/shell/ui/popupMenu.js'; +import * as Config from 'resource:///org/gnome/shell/misc/config.js'; const ByteArray = imports.byteArray; -const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Utils = Me.imports.utils; -const Blur = Me.imports.blur; -const Thumbnail = Me.imports.thumbnail; -const BWClipboard = Me.imports.BWClipboard; -const Convenience = Me.imports.convenience; -const Gettext = imports.gettext.domain('BingWallpaper'); -const _ = Gettext.gettext; +import {Extension, gettext as _} from 'resource:///org/gnome/shell/extensions/extension.js'; +import * as Utils from './utils.js'; +import Blur from './blur.js'; +import Thumbnail from './thumbnail.js'; +import BWClipboard from './BWClipboard.js'; +import * as Convenience from './convenience.js'; const BingImageURL = Utils.BingImageURL; const BingURL = 'https://www.bing.com'; @@ -39,16 +45,13 @@ const ICON_TIMED_MODE_BUTTON = 'document-open-recent-symbolic'; const ICON_PAUSE_MODE_BUTTON = 'media-playback-pause-symbolic'; const ICON_PLAY_MODE_BUTTON = 'media-playback-start-symbolic'; const ICON_REFRESH = 'view-refresh-symbolic'; -const ICON_RANDOM = Me.dir.get_child('icons').get_path() + '/'+'game-die-symbolic.svg'; -const ICON_FAVE_BUTTON = Me.dir.get_child('icons').get_path() + '/'+'fav-symbolic.svg'; -const ICON_UNFAVE_BUTTON = Me.dir.get_child('icons').get_path() + '/'+'unfav-symbolic.svg'; let bingWallpaperIndicator = null; let blur = null; // remove this when dropping support for < 3.33, see https://github.com/OttoAllmendinger/ const getActorCompat = (obj) => - Convenience.currentVersionGreaterEqual('3.33') ? obj : obj.actor; + Convenience.versionGreaterEqual(Config.PACKAGE_VERSION.replace(/(alpha|beta)/,'0'), '3.33') ? obj : obj.actor; const newMenuItem = (label) => { return new PopupMenu.PopupMenuItem(label); @@ -90,8 +93,8 @@ function doSetBackground(uri, schema) { } const BingWallpaperIndicator = GObject.registerClass( -class BingWallpaperIndicator extends PanelMenu.Button { - _init(params = {}) { +class BingWallpaperIndicator extends Button { + _init(ext) { super._init(0, IndicatorName, false); this.title = ""; @@ -110,13 +113,19 @@ class BingWallpaperIndicator extends PanelMenu.Button { this.thumbnail = null; this.thumbnailItem = null; this.selected_image = "current"; - this.clipboard = new BWClipboard.BWClipboard(); + this.clipboard = new BWClipboard(); this.imageIndex = null; this.logger = null; this.favourite_status = false; + this._extension = ext; + let extensionIconsPath = ext.dir.get_child('icons').get_path() + this.ICON_RANDOM = extensionIconsPath + '/'+'game-die-symbolic.svg'; + this.ICON_FAVE_BUTTON = extensionIconsPath + '/'+'fav-symbolic.svg'; + this.ICON_UNFAVE_BUTTON = extensionIconsPath + '/'+'unfav-symbolic.svg'; + if (!blur) // as Blur isn't disabled on screen lock (like the rest of the extension is) - blur = new Blur.Blur(); + blur = new Blur(); /* blur.BWP_BLUR_BRIGHTNESS = 2; @@ -124,7 +133,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { */ // take a variety of actions when the gsettings values are modified by prefs - this._settings = ExtensionUtils.getSettings(Utils.BING_SCHEMA); + this._settings = this._extension.getSettings(Utils.BING_SCHEMA); this._initSoup(); @@ -214,7 +223,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { // create soup Session _initSoup() { this.httpSession = new Soup.Session(); - this.httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + imports.misc.config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + Me.metadata.version; + this.httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + Config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + this._extension.metadata.version; } // listen for configuration changes @@ -313,7 +322,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { } _openPrefs() { - ExtensionUtils.openPrefs(); + this._extension.openPreferences(); } _openMenu() { @@ -360,9 +369,9 @@ class BingWallpaperIndicator extends PanelMenu.Button { // set indicator icon (tray icon) _setIcon() { - Utils.validate_icon(this._settings); + Utils.validate_icon(this._settings, this._extension.path); let icon_name = this._settings.get_string('icon-name'); - let gicon = Gio.icon_new_for_string(Me.dir.get_child('icons').get_path() + '/' + icon_name + '.svg'); + let gicon = Gio.icon_new_for_string(this._extension.dir.get_child('icons').get_path() + '/' + icon_name + '.svg'); this.icon = new St.Icon({gicon: gicon, style_class: 'system-status-icon'}); log('Replace icon set to: ' + icon_name); getActorCompat(this).remove_all_children(); @@ -373,7 +382,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { _setBackground() { if (this.filename == '') return; - this.thumbnail = new Thumbnail.Thumbnail(this.filename); // historically thumbnails were a bit unsafe on Wayland, but now fixed + this.thumbnail = new Thumbnail(this.filename); // historically thumbnails were a bit unsafe on Wayland, but now fixed this._setThumbnailImage(); if (this._settings.get_boolean('set-background')) this._setBackgroundDesktop(); @@ -436,7 +445,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { else { this.explainItem.label.set_text(this.explanation ? this.explanation : ''); } - this._setFavouriteIcon(this.favourite_status?ICON_FAVE_BUTTON:ICON_UNFAVE_BUTTON); + this._setFavouriteIcon(this.favourite_status?this.ICON_FAVE_BUTTON:this.ICON_UNFAVE_BUTTON); } _wrapLabelItem(menuItem) { @@ -449,7 +458,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { _setControls() { this.favouriteBtn = this._newMenuIcon( - this.favourite_status?ICON_FAVE_BUTTON:ICON_UNFAVE_BUTTON, + this.favourite_status?this.ICON_FAVE_BUTTON:this.ICON_UNFAVE_BUTTON, this.controlItem, this._favouriteImage); this.prevBtn = this._newMenuIcon( @@ -465,7 +474,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { this.controlItem, this._curImage); this.randomizeBtn = this._newMenuIcon( - ICON_RANDOM, + this.ICON_RANDOM, this.controlItem, this._shuffleImage); } @@ -577,7 +586,7 @@ class BingWallpaperIndicator extends PanelMenu.Button { log('favourite image '+this.imageURL+' status was '+this.favourite_status); this.favourite_status = !this.favourite_status; Utils.setImageFavouriteStatus(this._settings, this.imageURL, this.favourite_status); - this._setFavouriteIcon(this.favourite_status?ICON_FAVE_BUTTON:ICON_UNFAVE_BUTTON); + this._setFavouriteIcon(this.favourite_status?this.ICON_FAVE_BUTTON:this.ICON_UNFAVE_BUTTON); } _setFavouriteIcon(icon_name) { @@ -990,26 +999,23 @@ class BingWallpaperIndicator extends PanelMenu.Button { } }); -function init(extensionMeta) { - ExtensionUtils.initTranslations("BingWallpaper"); -} - -function enable() { - bingWallpaperIndicator = new BingWallpaperIndicator(); - Main.panel.addToStatusArea(IndicatorName, bingWallpaperIndicator); -} - -function disable() { - bingWallpaperIndicator.stop(); - bingWallpaperIndicator.destroy(); - bingWallpaperIndicator = null; - - // *** NOTE for EGO reviewers *** - // blur.js remains active during lockscreen, while the rest of the extension is disabled - // this code ONLY modifies the background blur effects for the lockscreen no web connectivity - if (!Main.sessionMode.isLocked) { - blur._disable(); // disable blur (blur.js) override and cleanup - blur = null; +export default class BingWallpaperExtension extends Extension { + enable() { + bingWallpaperIndicator = new BingWallpaperIndicator(this); + Main.panel.addToStatusArea(IndicatorName, bingWallpaperIndicator); + } + disable() { + bingWallpaperIndicator.stop(); + bingWallpaperIndicator.destroy(); + bingWallpaperIndicator = null; + + // *** NOTE for EGO reviewers *** + // blur.js remains active during lockscreen, while the rest of the extension is disabled + // this code ONLY modifies the background blur effects for the lockscreen no web connectivity + if (!Main.sessionMode.isLocked) { + blur._disable(); // disable blur (blur.js) override and cleanup + blur = null; + } } } diff --git a/metadata.json b/metadata.json index 5eef2c17..673473a3 100644 --- a/metadata.json +++ b/metadata.json @@ -1,6 +1,6 @@ { "uuid": "BingWallpaper@ineffable-gmail.com", - "shell-version": ["3.36", "3.38", "40", "41", "42", "43", "44"], + "shell-version": ["3.36", "3.38", "40", "41", "42", "43", "44", "45"], "name": "Bing Wallpaper", "settings-schema": "org.gnome.shell.extensions.bingwallpaper", "description": "Sync your wallpaper to today's Microsoft Bing image of the day (the image you see when you visit Bing.com).\n\n *Disclaimer*: this extension is unofficial and not affiliated with Bing or Microsoft in any way. Images are protected by copyright and are licensed only for use as wallpapers.\n\nFeatures:\n* UHD resolution wallpapers\n* Automatically fetches current Bing wallpaper of the day and sets as both lock screen and desktop wallpaper (user selectable on GNOME versions that support it)\n* Doesn't poll continuously - only once per day and on startup (schedules a refresh when Bing is due to update)\n * random mode (from previously downloaded wallpapers)\n *NEW: select/cycle wallpaper through previously downloaded images\n* Language support: English (en), German (de), Dutch (nl), Italian (it), Polish (pl), Chinese (zh_CN, zh_TW), French (fr_FR), Portuguese (pt, pt_BR), Ukrainian (uk), Russian (ru_RU), Spanish (es), Korean (ko), Indonesian (id), Catalan (ca), Norwegian Bokmål (nb) & Nynorsk (ni), Swedish (sv), Arabic (ar), Hungarian (hu) and Japanese (ja) - a HUGE thanks to the translators\n\nThis extension was forked from the NASA APOD extension by Elinvention (https://github.com/Elinvention) and inspired by Bing Desktop Wallpaper Changer by Utkarsh Gupta (https://github.com/UtkarshGpta).\n\nAlways restart GNOME after manually updating extensions. Please report bugs to the GitHub page below:", diff --git a/prefs.js b/prefs.js index b39b9138..c1055a78 100644 --- a/prefs.js +++ b/prefs.js @@ -7,16 +7,18 @@ // See the GNU General Public License, version 3 or later for details. // Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod -imports.gi.versions.Soup = "2.4"; // force single version of Soup, not sure if there is a way to force latest version - -const {Gtk, Gdk, GdkPixbuf, Gio, GLib, Soup} = imports.gi; -const ExtensionUtils = imports.misc.extensionUtils; -const Me = ExtensionUtils.getCurrentExtension(); -const Utils = Me.imports.utils; -const Convenience = Me.imports.convenience; -const Gettext = imports.gettext.domain('BingWallpaper'); -const _ = Gettext.gettext; -const Carousel = Me.imports.carousel; +import Gtk from 'gi://Gtk'; +import Gdk from 'gi://Gdk'; +import GdkPixbuf from 'gi://GdkPixbuf'; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import Soup from 'gi://Soup?version=2.4'; +import Adw from 'gi://Adw'; +import {ExtensionPreferences, gettext as _} from 'resource:///org/gnome/Shell/Extensions/js/extensions/prefs.js'; +import * as Config from 'resource:///org/gnome/Shell/Extensions/js/misc/config.js'; +import * as Utils from './utils.js'; +import * as Convenience from './convenience.js'; +import Carousel from './carousel.js'; const BingImageURL = Utils.BingImageURL; @@ -25,272 +27,274 @@ var DESKTOP_SCHEMA = 'org.gnome.desktop.background'; var PREFS_DEFAULT_WIDTH = 650; var PREFS_DEFAULT_HEIGHT = 650; -function init() { - ExtensionUtils.initTranslations("BingWallpaper"); // this is now included in ExtensionUtils -} - -function buildPrefsWidget() { - // formally globals - let settings = ExtensionUtils.getSettings(Utils.BING_SCHEMA); - let desktop_settings = ExtensionUtils.getSettings(Utils.DESKTOP_SCHEMA); - - let icon_image = null; - let provider = new Gtk.CssProvider(); - - let carousel = null; - let httpSession = null; +export default class BingWallpaperExtensionPreferences extends ExtensionPreferences { + fillPreferencesWindow(window) { + // formally globals + let settings = this.getSettings(Utils.BING_SCHEMA); + let desktop_settings = this.getSettings(Utils.DESKTOP_SCHEMA); + + let icon_image = null; + let provider = new Gtk.CssProvider(); + + let carousel = null; + let httpSession = null; + + let log = (msg) => { // avoids need for globals + if (settings.get_boolean('debug-logging')) + print("BingWallpaper extension: " + msg); // disable to keep the noise down in journal + } + + // Prepare labels and controls + let buildable = new Gtk.Builder(); + if (Gtk.get_major_version() == 4) { // GTK4 removes some properties, and builder breaks when it sees them + buildable.add_from_file( this.dir.get_path() + '/ui/Settings4.ui' ); + provider.load_from_path(this.dir.get_path() + '/ui/prefs.css'); + Gtk.StyleContext.add_provider_for_display( + Gdk.Display.get_default(), + provider, + Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); + } + else { + buildable.add_from_file( this.dir.get_path() + '/ui/Settings.ui' ); + } + + let box = buildable.get_object('prefs_widget'); + + // fix size of prefs window in GNOME shell 40+ (but super racy, so is unreliable) + + if (Convenience.versionGreaterEqual(Config.PACKAGE_VERSION.replace(/(alpha|beta)/,'0'), '40')) { + box.connect('realize', () => { + let window = box.get_root(); + //window.default_width = PREFS_DEFAULT_WIDTH; + window.default_height = PREFS_DEFAULT_HEIGHT; + }); + } + + buildable.get_object('extension_version').set_text(this.metadata.version.toString()); + buildable.get_object('extension_name').set_text(this.metadata.name.toString()); + + // assign variables to UI objects we've loaded + let hideSwitch = buildable.get_object('hide'); + let iconEntry = buildable.get_object('icon'); + let notifySwitch = buildable.get_object('notify'); + let bgSwitch = buildable.get_object('background'); + let styleEntry = buildable.get_object('background_style'); + let fileChooserBtn = buildable.get_object('download_folder'); + let fileChooser = buildable.get_object('file_chooser'); // this should only exist on Gtk4 + let folderOpenBtn = buildable.get_object('button_open_download_folder'); + let marketEntry = buildable.get_object('market'); + let resolutionEntry = buildable.get_object('resolution'); + let historyEntry = buildable.get_object('history'); + let galleryButton = buildable.get_object('button_open_gallery'); + let deleteSwitch = buildable.get_object('delete_previous'); + icon_image = buildable.get_object('icon_image'); + let overrideSwitch = buildable.get_object('lockscreen_override'); + let strengthEntry = buildable.get_object('entry_strength'); + let brightnessEntry = buildable.get_object('entry_brightness'); + let debugSwitch = buildable.get_object('debug_switch'); + let revertSwitch = buildable.get_object('revert_switch'); + let unsafeSwitch = buildable.get_object('unsafe_switch'); + let randomIntervalEntry = buildable.get_object('entry_random_interval'); + let change_log = buildable.get_object('change_log'); + let buttonGDMdefault = buildable.get_object('button_default_gnome'); + let buttonnoblur = buildable.get_object('button_no_blur'); + let buttonslightblur = buildable.get_object('button_slight_blur'); + let buttonImportData = buildable.get_object('button_json_import'); + let buttonExportData = buildable.get_object('button_json_export'); + let switchAlwaysExport = buildable.get_object('always_export_switch'); + /*let searchEntry = buildable.get_object('searchEntry'); + let searchBuffer = buildable.get_object('searchBuffer');*/ + let carouselFlowBox = (Gtk.get_major_version() == 4) ? buildable.get_object('carouselFlowBox'): null; + + try { + httpSession = new Soup.Session(); + httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + Config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + this.metadata.version; + } + catch (e) { + log("Error creating httpSession: " + e); + } + + // check that these are valid (can be edited through dconf-editor) + Utils.validate_resolution(settings); + Utils.validate_icon(settings, this.path, icon_image); - let log = (msg) => { // avoids need for globals - if (settings.get_boolean('debug-logging')) - print("BingWallpaper extension: " + msg); // disable to keep the noise down in journal - } + // Indicator & notifications + settings.bind('hide', hideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('notify', notifySwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - // Prepare labels and controls - let buildable = new Gtk.Builder(); - if (Gtk.get_major_version() == 4) { // GTK4 removes some properties, and builder breaks when it sees them - buildable.add_from_file( Me.dir.get_path() + '/ui/Settings4.ui' ); - provider.load_from_path(Me.dir.get_path() + '/ui/prefs.css'); - Gtk.StyleContext.add_provider_for_display( - Gdk.Display.get_default(), - provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION); - } - else { - buildable.add_from_file( Me.dir.get_path() + '/ui/Settings.ui' ); - } - - let box = buildable.get_object('prefs_widget'); - - // fix size of prefs window in GNOME shell 40+ (but super racy, so is unreliable) - if (Convenience.currentVersionGreaterEqual('40')) { - box.connect('realize', () => { - let window = box.get_root(); - //window.default_width = PREFS_DEFAULT_WIDTH; - window.default_height = PREFS_DEFAULT_HEIGHT; + // add markets to dropdown list (aka a GtkComboText) + Utils.icon_list.forEach((iconname, index) => { + iconEntry.append(iconname, iconname); }); - } - buildable.get_object('extension_version').set_text(Me.metadata.version.toString()); - buildable.get_object('extension_name').set_text(Me.metadata.name.toString()); - - // assign variables to UI objects we've loaded - let hideSwitch = buildable.get_object('hide'); - let iconEntry = buildable.get_object('icon'); - let notifySwitch = buildable.get_object('notify'); - let bgSwitch = buildable.get_object('background'); - let styleEntry = buildable.get_object('background_style'); - let fileChooserBtn = buildable.get_object('download_folder'); - let fileChooser = buildable.get_object('file_chooser'); // this should only exist on Gtk4 - let folderOpenBtn = buildable.get_object('button_open_download_folder'); - let marketEntry = buildable.get_object('market'); - let resolutionEntry = buildable.get_object('resolution'); - let historyEntry = buildable.get_object('history'); - let galleryButton = buildable.get_object('button_open_gallery'); - let deleteSwitch = buildable.get_object('delete_previous'); - icon_image = buildable.get_object('icon_image'); - let overrideSwitch = buildable.get_object('lockscreen_override'); - let strengthEntry = buildable.get_object('entry_strength'); - let brightnessEntry = buildable.get_object('entry_brightness'); - let debugSwitch = buildable.get_object('debug_switch'); - let revertSwitch = buildable.get_object('revert_switch'); - let unsafeSwitch = buildable.get_object('unsafe_switch'); - let randomIntervalEntry = buildable.get_object('entry_random_interval'); - let change_log = buildable.get_object('change_log'); - let buttonGDMdefault = buildable.get_object('button_default_gnome'); - let buttonnoblur = buildable.get_object('button_no_blur'); - let buttonslightblur = buildable.get_object('button_slight_blur'); - let buttonImportData = buildable.get_object('button_json_import'); - let buttonExportData = buildable.get_object('button_json_export'); - let switchAlwaysExport = buildable.get_object('always_export_switch'); - /*let searchEntry = buildable.get_object('searchEntry'); - let searchBuffer = buildable.get_object('searchBuffer');*/ - let carouselFlowBox = (Gtk.get_major_version() == 4) ? buildable.get_object('carouselFlowBox'): null; - - try { - httpSession = new Soup.Session(); - httpSession.user_agent = 'User-Agent: Mozilla/5.0 (X11; GNOME Shell/' + imports.misc.config.PACKAGE_VERSION + '; Linux x86_64; +https://github.com/neffo/bing-wallpaper-gnome-extension ) BingWallpaper Gnome Extension/' + Me.metadata.version; - } - catch (e) { - log("Error creating httpSession: " + e); - } - - // check that these are valid (can be edited through dconf-editor) - Utils.validate_resolution(settings); - Utils.validate_icon(settings, icon_image); - - // Indicator & notifications - settings.bind('hide', hideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('notify', notifySwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - - // add markets to dropdown list (aka a GtkComboText) - Utils.icon_list.forEach((iconname, index) => { - iconEntry.append(iconname, iconname); - }); - - // user selectable indicator icons - settings.bind('icon-name', iconEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); - settings.connect('changed::icon-name', () => { - Utils.validate_icon(settings, icon_image); - }); - iconEntry.set_active_id(settings.get_string('icon-name')); - - // connect switches to settings changes - settings.bind('set-background', bgSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('debug-logging', debugSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('revert-to-current-image', revertSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('override-unsafe-wayland', unsafeSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('random-interval', randomIntervalEntry, 'value', Gio.SettingsBindFlags.DEFAULT); - settings.bind('always-export-bing-json', switchAlwaysExport, 'active', Gio.SettingsBindFlags.DEFAULT); - - // button opens Nautilus at our image folder - folderOpenBtn.connect('clicked', (widget) => { - Utils.openImageFolder(settings); - }); - - // open image carousel (gallery) window (gtk3, gnome <40) or populate the tab (gtk4+, gnome 40+) - if (Gtk.get_major_version() == 4) { - carousel = new Carousel.Carousel(settings, null, null, carouselFlowBox); // auto load carousel - - } - else { - galleryButton.connect('clicked', (widget) => { - carousel = new Carousel.Carousel(settings, widget, null, carouselFlowBox); + // user selectable indicator icons + settings.bind('icon-name', iconEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + settings.connect('changed::icon-name', () => { + Utils.validate_icon(settings, this.path, icon_image); }); - - } - - // this is intended for migrating image folders between computers (or even sharing) or backups - // we export the Bing JSON data to the image directory, so this folder becomes portable - buttonImportData.connect('clicked', () => { - Utils.importBingJSON(settings); - }); - buttonExportData.connect('clicked', () => { - Utils.exportBingJSON(settings); - }); - - //download folder - if (Gtk.get_major_version() == 4) { // we need to use native file choosers in Gtk4 - fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); - - fileChooserBtn.connect('clicked', (widget) => { - let parent = widget.get_root(); - let curWallpaperDir = Gio.File.new_for_path(Utils.getWallpaperDir(settings)); - fileChooser.set_current_folder(curWallpaperDir.get_parent()); - fileChooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER); - fileChooser.set_transient_for(parent); - fileChooser.set_accept_label(_('Select folder')); - fileChooser.show(); + iconEntry.set_active_id(settings.get_string('icon-name')); + + // connect switches to settings changes + settings.bind('set-background', bgSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('debug-logging', debugSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('revert-to-current-image', revertSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('override-unsafe-wayland', unsafeSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('random-interval', randomIntervalEntry, 'value', Gio.SettingsBindFlags.DEFAULT); + settings.bind('always-export-bing-json', switchAlwaysExport, 'active', Gio.SettingsBindFlags.DEFAULT); + + // button opens Nautilus at our image folder + folderOpenBtn.connect('clicked', (widget) => { + Utils.openImageFolder(settings); }); - fileChooser.connect('response', (widget, response) => { - if (response !== Gtk.ResponseType.ACCEPT) { - return; - } - let fileURI = fileChooser.get_file().get_path().replace('file://', ''); - log("fileChooser returned: "+fileURI); - fileChooserBtn.set_label(fileURI); - Utils.moveImagesToNewFolder(settings, Utils.getWallpaperDir(settings), fileURI); - Utils.setWallpaperDir(settings, fileURI); + // open image carousel (gallery) window (gtk3, gnome <40) or populate the tab (gtk4+, gnome 40+) + if (Gtk.get_major_version() == 4) { + carousel = new Carousel(settings, null, null, carouselFlowBox); // auto load carousel + } + else { + galleryButton.connect('clicked', (widget) => { + carousel = new Carousel(settings, widget, null, carouselFlowBox); + }); + } + + // this is intended for migrating image folders between computers (or even sharing) or backups + // we export the Bing JSON data to the image directory, so this folder becomes portable + buttonImportData.connect('clicked', () => { + Utils.importBingJSON(settings); }); - - // in Gtk 4 instead we use a DropDown, but we need to treat it a bit special - let market_grid = buildable.get_object('market_grid'); - marketEntry = Gtk.DropDown.new_from_strings(Utils.marketName); - marketEntry.set_selected(Utils.markets.indexOf(settings.get_string('market'))); - market_grid.attach(marketEntry, 1, 0, 1, 2); - marketEntry.connect('notify::selected-item', () => { - let id = marketEntry.get_selected(); - settings.set_string('market', Utils.markets[id]); - log('dropdown selected '+id+' = '+Utils.markets[id]+" - "+Utils.marketName[id]); + buttonExportData.connect('clicked', () => { + Utils.exportBingJSON(settings); }); - settings.connect('changed::market', () => { + //download folder + if (Gtk.get_major_version() == 4) { // we need to use native file choosers in Gtk4 + fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); + + fileChooserBtn.connect('clicked', (widget) => { + let parent = widget.get_root(); + let curWallpaperDir = Gio.File.new_for_path(Utils.getWallpaperDir(settings)); + fileChooser.set_current_folder(curWallpaperDir.get_parent()); + fileChooser.set_action(Gtk.FileChooserAction.SELECT_FOLDER); + fileChooser.set_transient_for(parent); + fileChooser.set_accept_label(_('Select folder')); + fileChooser.show(); + }); + + fileChooser.connect('response', (widget, response) => { + if (response !== Gtk.ResponseType.ACCEPT) { + return; + } + let fileURI = fileChooser.get_file().get_path().replace('file://', ''); + log("fileChooser returned: "+fileURI); + fileChooserBtn.set_label(fileURI); + Utils.moveImagesToNewFolder(settings, Utils.getWallpaperDir(settings), fileURI); + Utils.setWallpaperDir(settings, fileURI); + }); + + // in Gtk 4 instead we use a DropDown, but we need to treat it a bit special + let market_grid = buildable.get_object('market_grid'); + marketEntry = Gtk.DropDown.new_from_strings(Utils.marketName); marketEntry.set_selected(Utils.markets.indexOf(settings.get_string('market'))); - }); + market_grid.attach(marketEntry, 1, 0, 1, 2); + marketEntry.connect('notify::selected-item', () => { + let id = marketEntry.get_selected(); + settings.set_string('market', Utils.markets[id]); + log('dropdown selected '+id+' = '+Utils.markets[id]+" - "+Utils.marketName[id]); + }); + + settings.connect('changed::market', () => { + marketEntry.set_selected(Utils.markets.indexOf(settings.get_string('market'))); + }); + + settings.connect('changed::download-folder', () => { + fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); + }); + } + else { // Gtk 3 + fileChooserBtn.set_filename(Utils.getWallpaperDir(settings)); + log("fileChooser filename/dirname set to '"+fileChooserBtn.get_filename()+"' setting is '"+settings.get_string('download-folder')+"'"); - settings.connect('changed::download-folder', () => { - fileChooserBtn.set_label(Utils.getWallpaperDir(settings)); + fileChooserBtn.add_shortcut_folder_uri("file://" + GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES)+"/BingWallpaper"); + fileChooserBtn.connect('file-set', (widget) => { + Utils.moveImagesToNewFolder(settings, settings.get_string('download-folder'), widget.get_filename()); + Utils.setWallpaperDir(settings, widget.get_filename()); + }); + + Utils.markets.forEach((bingmarket, index) => { // add markets to dropdown list (aka a GtkComboText) + marketEntry.append(bingmarket, bingmarket+": "+Utils.marketName[index]); + }); + + settings.bind('market', marketEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + + settings.connect('changed::download-folder', () => { + fileChooserBtn.set_filename(Utils.getWallpaperDir(settings)); + }); + } + + // Resolution + Utils.resolutions.forEach((res) => { // add res to dropdown list (aka a GtkComboText) + resolutionEntry.append(res, res); }); - } - else { // Gtk 3 - fileChooserBtn.set_filename(Utils.getWallpaperDir(settings)); - log("fileChooser filename/dirname set to '"+fileChooserBtn.get_filename()+"' setting is '"+settings.get_string('download-folder')+"'"); - fileChooserBtn.add_shortcut_folder_uri("file://" + GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES)+"/BingWallpaper"); - fileChooserBtn.connect('file-set', (widget) => { - Utils.moveImagesToNewFolder(settings, settings.get_string('download-folder'), widget.get_filename()); - Utils.setWallpaperDir(settings, widget.get_filename()); + settings.bind('resolution', resolutionEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + + settings.connect('changed::resolution', () => { + Utils.validate_resolution(settings); }); - Utils.markets.forEach((bingmarket, index) => { // add markets to dropdown list (aka a GtkComboText) - marketEntry.append(bingmarket, bingmarket+": "+Utils.marketName[index]); + // History + let imageList = Utils.getImageList(settings); + historyEntry.append('current', _('Most recent image')); + historyEntry.append('random', _('Random image')); + + imageList.forEach((image) => { + historyEntry.append(image.urlbase.replace('/th?id=OHR.', ''), Utils.shortenName(Utils.getImageTitle(image), 50)); }); - settings.bind('market', marketEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + // selected image can also be changed through the menu or even dconf + settings.bind('selected-image', historyEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + settings.connect('changed::selected-image', () => { + Utils.validate_imagename(settings); + }); - settings.connect('changed::download-folder', () => { - fileChooserBtn.set_filename(Utils.getWallpaperDir(settings)); + // background styles (e.g. zoom or span) + Utils.backgroundStyle.forEach((style) => { + styleEntry.append(style, style); }); - } + desktop_settings.bind('picture-options', styleEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); - // Resolution - Utils.resolutions.forEach((res) => { // add res to dropdown list (aka a GtkComboText) - resolutionEntry.append(res, res); - }); - - settings.bind('resolution', resolutionEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); + settings.bind('delete-previous', deleteSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.connect('changed::resolution', () => { - Utils.validate_resolution(settings); - }); + // GDM3 lockscreen blur override + settings.bind('override-lockscreen-blur', overrideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); + settings.bind('lockscreen-blur-strength', strengthEntry, 'value', Gio.SettingsBindFlags.DEFAULT); + settings.bind('lockscreen-blur-brightness', brightnessEntry, 'value', Gio.SettingsBindFlags.DEFAULT); + + // add a couple of preset buttons + buttonGDMdefault.connect('clicked', (widget) => { + Utils.set_blur_preset(settings, Utils.PRESET_GNOME_DEFAULT); + }); + buttonnoblur.connect('clicked', (widget) => { + Utils.set_blur_preset(settings, Utils.PRESET_NO_BLUR); + }); + buttonslightblur.connect('clicked', (widget) => { + Utils.set_blur_preset(settings, Utils.PRESET_SLIGHT_BLUR); + }); - // History - let imageList = Utils.getImageList(settings); - historyEntry.append('current', _('Most recent image')); - historyEntry.append('random', _('Random image')); - - imageList.forEach((image) => { - historyEntry.append(image.urlbase.replace('/th?id=OHR.', ''), Utils.shortenName(Utils.getImageTitle(image), 50)); - }); - - // selected image can also be changed through the menu or even dconf - settings.bind('selected-image', historyEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); - settings.connect('changed::selected-image', () => { - Utils.validate_imagename(settings); - }); - - // background styles (e.g. zoom or span) - Utils.backgroundStyle.forEach((style) => { - styleEntry.append(style, style); - }); - desktop_settings.bind('picture-options', styleEntry, 'active_id', Gio.SettingsBindFlags.DEFAULT); - - settings.bind('delete-previous', deleteSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - - // GDM3 lockscreen blur override - settings.bind('override-lockscreen-blur', overrideSwitch, 'active', Gio.SettingsBindFlags.DEFAULT); - settings.bind('lockscreen-blur-strength', strengthEntry, 'value', Gio.SettingsBindFlags.DEFAULT); - settings.bind('lockscreen-blur-brightness', brightnessEntry, 'value', Gio.SettingsBindFlags.DEFAULT); - - // add a couple of preset buttons - buttonGDMdefault.connect('clicked', (widget) => { - Utils.set_blur_preset(settings, Utils.PRESET_GNOME_DEFAULT); - }); - buttonnoblur.connect('clicked', (widget) => { - Utils.set_blur_preset(settings, Utils.PRESET_NO_BLUR); - }); - buttonslightblur.connect('clicked', (widget) => { - Utils.set_blur_preset(settings, Utils.PRESET_SLIGHT_BLUR); - }); - - // not required in GTK4 as widgets are displayed by default - if (Gtk.get_major_version() < 4) - box.show_all(); - - // fetch - if (httpSession) - Utils.fetch_change_log(Me.metadata.version.toString(), change_log, httpSession); - - return box; -} + // not required in GTK4 as widgets are displayed by default + if (Gtk.get_major_version() < 4) + box.show_all(); + + // fetch + if (httpSession) + Utils.fetch_change_log(this.metadata.version.toString(), change_log, httpSession); + + const page = new Adw.PreferencesPage(); + const group = new Adw.PreferencesGroup(); + group.add(box); + page.add(group); + + window.add(page); + } +} diff --git a/thumbnail.js b/thumbnail.js index e5474821..f4554bf7 100644 --- a/thumbnail.js +++ b/thumbnail.js @@ -6,10 +6,10 @@ // (at your option) any later version. // See the GNU General Public License, version 3 or later for details. -const Gio = imports.gi.Gio; -const GdkPixbuf = imports.gi.GdkPixbuf; +import Gio from 'gi://Gio'; +import GdkPixbuf from 'gi://GdkPixbuf'; -var Thumbnail = class Thumbnail { +export default class Thumbnail { constructor(filePath) { if (!filePath) { throw new Error(`need argument ${filePath}`); diff --git a/utils.js b/utils.js index 7f926bf4..981fd31d 100644 --- a/utils.js +++ b/utils.js @@ -7,26 +7,20 @@ // See the GNU General Public License, version 3 or later for details. // Based on GNOME shell extension NASA APOD by Elia Argentieri https://github.com/Elinvention/gnome-shell-extension-nasa-apod -const {Gio, GLib, Soup, GdkPixbuf} = imports.gi; -const ExtensionUtils = imports.misc.extensionUtils; -const Me = imports.misc.extensionUtils.getCurrentExtension(); -const Config = imports.misc.config; -const Convenience = Me.imports.convenience; -const Gettext = imports.gettext.domain('BingWallpaper'); -const _ = Gettext.gettext; +import Gio from 'gi://Gio'; +import GLib from 'gi://GLib'; +import Soup from 'gi://Soup'; +import GdkPixbuf from 'gi://GdkPixbuf'; +import * as Convenience from './convenience.js'; const ByteArray = imports.byteArray; -var PRESET_GNOME_DEFAULT = { blur: 60, dim: 55 }; // as at GNOME 40 -var PRESET_NO_BLUR = { blur: 0, dim: 60 }; -var PRESET_SLIGHT_BLUR = { blur: 2, dim: 60 }; +export var PRESET_GNOME_DEFAULT = { blur: 60, dim: 55 }; // as at GNOME 40 +export var PRESET_NO_BLUR = { blur: 0, dim: 60 }; +export var PRESET_SLIGHT_BLUR = { blur: 2, dim: 60 }; -var BING_SCHEMA = 'org.gnome.shell.extensions.bingwallpaper'; -var DESKTOP_SCHEMA = 'org.gnome.desktop.background'; -var LOCKSCREEN_SCHEMA = 'org.gnome.desktop.screensaver'; - -var shellVersionMajor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[0]); -var shellVersionMinor = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[1]); //FIXME: these checks work will probably break on newer shell versions -var shellVersionPoint = parseInt(imports.misc.config.PACKAGE_VERSION.split('.')[2]); +export var BING_SCHEMA = 'org.gnome.shell.extensions.bingwallpaper'; +export var DESKTOP_SCHEMA = 'org.gnome.desktop.background'; +export var LOCKSCREEN_SCHEMA = 'org.gnome.desktop.screensaver'; var vertical_blur = null; var horizontal_blur = null; @@ -35,18 +29,18 @@ let gitreleaseurl = 'https://api.github.com/repos/neffo/bing-wallpaper-gnome-ext let debug = false; // remove this when dropping support for < 3.33, see https://github.com/OttoAllmendinger/ -var getActorCompat = (obj) => - Convenience.currentVersionGreaterEqual('3.33') ? obj : obj.actor; +export var getActorCompat = (obj) => + Convenience.versionGreaterEqual(Config.PACKAGE_VERSION.replace(/(alpha|beta)/,'0'), '3.33') ? obj : obj.actor; -var icon_list = ['bing-symbolic', 'brick-symbolic', 'high-frame-symbolic', 'mid-frame-symbolic', 'low-frame-symbolic']; -var resolutions = ['auto', 'UHD', '1920x1200', '1920x1080', '1366x768', '1280x720', '1024x768', '800x600']; -var markets = ['auto', 'ar-XA', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'en-AU', 'en-CA', 'en-GB', +export var icon_list = ['bing-symbolic', 'brick-symbolic', 'high-frame-symbolic', 'mid-frame-symbolic', 'low-frame-symbolic']; +export var resolutions = ['auto', 'UHD', '1920x1200', '1920x1080', '1366x768', '1280x720', '1024x768', '800x600']; +export var markets = ['auto', 'ar-XA', 'da-DK', 'de-AT', 'de-CH', 'de-DE', 'en-AU', 'en-CA', 'en-GB', 'en-ID', 'en-IE', 'en-IN', 'en-MY', 'en-NZ', 'en-PH', 'en-SG', 'en-US', 'en-WW', 'en-XA', 'en-ZA', 'es-AR', 'es-CL', 'es-ES', 'es-MX', 'es-US', 'es-XL', 'et-EE', 'fi-FI', 'fr-BE', 'fr-CA', 'fr-CH', 'fr-FR', 'he-IL', 'hr-HR', 'hu-HU', 'it-IT', 'ja-JP', 'ko-KR', 'lt-LT', 'lv-LV', 'nb-NO', 'nl-BE', 'nl-NL', 'pl-PL', 'pt-BR', 'pt-PT', 'ro-RO', 'ru-RU', 'sk-SK', 'sl-SL', 'sv-SE', 'th-TH', 'tr-TR', 'uk-UA', 'zh-CN', 'zh-HK', 'zh-TW']; -var marketName = [ +export var marketName = [ 'auto', '(شبه الجزيرة العربية‎) العربية', 'dansk (Danmark)', 'Deutsch (Österreich)', 'Deutsch (Schweiz)', 'Deutsch (Deutschland)', 'English (Australia)', 'English (Canada)', 'English (United Kingdom)', 'English (Indonesia)', 'English (Ireland)', 'English (India)', 'English (Malaysia)', @@ -60,15 +54,15 @@ var marketName = [ 'slovenčina (Slovensko)', 'slovenščina (Slovenija)', 'svenska (Sverige)', 'ไทย (ไทย)', 'Türkçe (Türkiye)', 'українська (Україна)', '中文(中国)', '中文(中國香港特別行政區)', '中文(台灣)' ]; -var backgroundStyle = ['none', 'wallpaper', 'centered', 'scaled', 'stretched', 'zoom', 'spanned']; +export var backgroundStyle = ['none', 'wallpaper', 'centered', 'scaled', 'stretched', 'zoom', 'spanned']; -var randomIntervals = [300, 3600, 86400, 604800]; -var randomIntervalsTitle = ['00:00:05:00', '00:01:00:00', '00:24:00:00', '07:00:00:00']; +export var randomIntervals = [300, 3600, 86400, 604800]; +export var randomIntervalsTitle = ['00:00:05:00', '00:01:00:00', '00:24:00:00', '07:00:00:00']; -var BingImageURL = 'https://www.bing.com/HPImageArchive.aspx'; -var BingParams = { format: 'js', idx: '0' , n: '8' , mbl: '1' , mkt: '' } ; +export var BingImageURL = 'https://www.bing.com/HPImageArchive.aspx'; +export var BingParams = { format: 'js', idx: '0' , n: '8' , mbl: '1' , mkt: '' } ; -function validate_icon(settings, icon_image = null) { +export function validate_icon(settings, extension_path, icon_image = null) { log('validate_icon()'); let icon_name = settings.get_string('icon-name'); if (icon_name == '' || icon_list.indexOf(icon_name) == -1) { @@ -77,20 +71,20 @@ function validate_icon(settings, icon_image = null) { } // if called from prefs if (icon_image) { - log('set icon to: ' + Me.dir.get_path() + '/icons/' + icon_name + '.svg'); - let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(Me.dir.get_path() + '/icons/' + icon_name + '.svg', 32, 32); + log('set icon to: ' + extension_path + '/icons/' + icon_name + '.svg'); + let pixbuf = GdkPixbuf.Pixbuf.new_from_file_at_size(extension_path + '/icons/' + icon_name + '.svg', 32, 32); icon_image.set_from_pixbuf(pixbuf); } } -function validate_resolution(settings) { +export function validate_resolution(settings) { let resolution = settings.get_string('resolution'); if (resolution == '' || resolutions.indexOf(resolution) == -1) // if not a valid resolution settings.reset('resolution'); } // FIXME: needs work -function validate_imagename(settings) { +export function validate_imagename(settings) { let filename = settings.get_string('selected-image'); if (filename != 'current' || filename != 'random') return; @@ -101,13 +95,13 @@ function validate_imagename(settings) { } } -function get_current_bg(schema) { +export function get_current_bg(schema) { let gsettings = new Gio.Settings({ schema: schema }); let cur = gsettings.get_string('picture-uri'); return (cur); } -function fetch_change_log(version, label, httpSession) { +export function fetch_change_log(version, label, httpSession) { // create an http message let url = gitreleaseurl + "v" + version; let request = Soup.Message.new('GET', url); @@ -136,36 +130,29 @@ function fetch_change_log(version, label, httpSession) { } } -function set_blur_preset(settings, preset) { +export function set_blur_preset(settings, preset) { settings.set_int('lockscreen-blur-strength', preset.blur); settings.set_int('lockscreen-blur-brightness', preset.dim); log("Set blur preset to " + preset.blur + " brightness to " + preset.dim); } -function is_x11() { +export function is_x11() { return GLib.getenv('XDG_SESSION_TYPE') == 'x11'; // don't do wayland unsafe things if set } -function enabled_unsafe() { +export function enabled_unsafe() { //log("User override, enabling unsafe Wayland functionality"); return true; } -function gnome_major_version() { - let [major] = Config.PACKAGE_VERSION.split('.'); - let shellVersion = Number.parseInt(major); - - return shellVersion; -} - -function imageHasBasename(image_item, i, b) { +export function imageHasBasename(image_item, i, b) { //log("imageHasBasename : " + image_item.urlbase + " =? " + this); if (this && this.search(image_item.urlbase.replace('th?id=OHR.', ''))) return true; return false; } -function dateFromLongDate(longdate, add_seconds) { +export function dateFromLongDate(longdate, add_seconds) { if (typeof longdate === 'number') longdate = longdate.toString(); return GLib.DateTime.new(GLib.TimeZone.new_utc(), @@ -177,7 +164,7 @@ function dateFromLongDate(longdate, add_seconds) { 0 ).add_seconds(add_seconds); // seconds } -function dateFromShortDate(shortdate) { +export function dateFromShortDate(shortdate) { if (typeof shortdate === 'number') shortdate = shortdate.toString(); return GLib.DateTime.new(GLib.TimeZone.new_utc(), @@ -187,31 +174,31 @@ function dateFromShortDate(shortdate) { 0, 0, 0 ); } -function getImageList(settings) { +export function getImageList(settings) { return JSON.parse(settings.get_string('bing-json')); } -function setImageList(settings, imageList) { +export function setImageList(settings, imageList) { settings.set_string('bing-json', JSON.stringify(imageList)); if (settings.get_boolean('always-export-bing-json')) { // save copy of current JSON exportBingJSON(settings); } } -function getImageTitle(image_data) { +export function getImageTitle(image_data) { return image_data.copyright.replace(/\s*\(.*?\)\s*/g, ''); } -function getImageUrlBase(image_data) { +export function getImageUrlBase(image_data) { return image_data.urlbase.replace('/th?id=OHR.', ''); } -function getMaxLongDate(settings) { +export function getMaxLongDate(settings) { let imageList = getImageList(settings); return Math.max.apply(Math, imageList.map(function(o) { return o.fullstartdate; })); } -function getCurrentImageIndex (imageList) { +export function getCurrentImageIndex (imageList) { if (!imageList) return -1; let maxLongDate = Math.max.apply(Math, imageList.map(function(o) { return o.fullstartdate; })); @@ -220,7 +207,7 @@ function getCurrentImageIndex (imageList) { return index; } -function setImageFavouriteStatus(settings, imageURL, newState) { +export function setImageFavouriteStatus(settings, imageURL, newState) { log('set favourite status of '+imageURL+' to '+newState); let imageList = getImageList(settings); imageList.forEach(function(x, i) { @@ -233,7 +220,7 @@ function setImageFavouriteStatus(settings, imageURL, newState) { setImageList(settings, imageList); // save back to settings } -function getCurrentImage(imageList) { +export function getCurrentImage(imageList) { if (!imageList || imageList.length == 0) return null; let index = getCurrentImageIndex(imageList); @@ -242,7 +229,7 @@ function getCurrentImage(imageList) { return imageList[index]; } -function inImageList(imageList, urlbase) { +export function inImageList(imageList, urlbase) { let image = null; imageList.forEach(function(x, i) { if (urlbase.replace('/th?id=OHR.', '') == x.urlbase.replace('/th?id=OHR.', '')) @@ -251,7 +238,7 @@ function inImageList(imageList, urlbase) { return image; } -function inImageListByTitle(imageList, title) { +export function inImageListByTitle(imageList, title) { let image = null; imageList.forEach(function(x, i) { log('inImageListbyTitle(): ' + title + ' == ' + getImageTitle(x)); @@ -261,7 +248,7 @@ function inImageListByTitle(imageList, title) { return image; } -function mergeImageLists(settings, imageList) { +export function mergeImageLists(settings, imageList) { let curList = getImageList(settings); let newList = []; // list of only new images (for future notifications) imageList.forEach(function(x, i) { @@ -274,21 +261,21 @@ function mergeImageLists(settings, imageList) { return newList; // return this to caller for notifications } -function imageIndex(imageList, urlbase) { +export function imageIndex(imageList, urlbase) { return imageList.map(p => p.urlbase.replace('/th?id=OHR.', '')).indexOf(urlbase.replace('/th?id=OHR.', '')); } -function isFavourite(image) { +export function isFavourite(image) { return (image.favourite && image.favourite === true); } -function getImageByIndex(imageList, index) { +export function getImageByIndex(imageList, index) { if (imageList.length == 0 || index < 0 || index > imageList.length - 1) return null; return imageList[index]; } -function cleanupImageList(settings) { +export function cleanupImageList(settings) { let curList = imageListSortByDate(getImageList(settings)); let cutOff = GLib.DateTime.new_now_utc().add_days(-8); // 8 days ago let newList = []; @@ -306,7 +293,7 @@ function cleanupImageList(settings) { setImageList(settings, newList); } -function getWallpaperDir(settings) { +export function getWallpaperDir(settings) { let homeDir = GLib.get_home_dir(); let BingWallpaperDir = settings.get_string('download-folder').replace('~', homeDir); let userPicturesDir = GLib.get_user_special_dir(GLib.UserDirectory.DIRECTORY_PICTURES); @@ -328,24 +315,24 @@ function getWallpaperDir(settings) { return BingWallpaperDir; } -function setWallpaperDir(settings, uri) { +export function setWallpaperDir(settings, uri) { let homeDir = GLib.get_home_dir(); let relUri = uri.replace(homeDir, '~'); settings.set_string('download-folder', relUri); } -function imageToFilename(settings, image, resolution = null) { +export function imageToFilename(settings, image, resolution = null) { return getWallpaperDir(settings) + image.startdate + '-' + image.urlbase.replace(/^.*[\\\/]/, '').replace('th?id=OHR.', '') + '_' + (resolution ? resolution : getResolution(settings, image)) + '.jpg'; } -function getRandomInt(max) { +export function getRandomInt(max) { return Math.floor(Math.random() * max); } // Utility function -function dump(object, level = 0) { +export function dump(object, level = 0) { let output = ''; for (let property in object) { output += ' - '.repeat(level)+property + ': ' + object[property]+'\n '; @@ -357,7 +344,7 @@ function dump(object, level = 0) { return(output); } -function friendly_time_diff(time, short = true) { +export function friendly_time_diff(time, short = true) { // short we want to keep ~4-5 characters let timezone = GLib.TimeZone.new_local(); let now = GLib.DateTime.new_now(timezone).to_unix(); @@ -380,7 +367,7 @@ function friendly_time_diff(time, short = true) { } } -function getResolution(settings, image) { +export function getResolution(settings, image) { let resolution = settings.get_string('resolution'); if (resolutions.indexOf(resolution) == -1 || (image ? image.wp == false : true) || // wp == false when background is animated settings.get_string('resolution') == 'auto' ) { @@ -390,26 +377,26 @@ function getResolution(settings, image) { return resolution; } -function openImageFolder(settings) { +export function openImageFolder(settings) { //const context = global?global.create_app_launch_context(0, -1):null; Gio.AppInfo.launch_default_for_uri('file://' + getWallpaperDir(settings), null); } -function imageListSortByDate(imageList) { +export function imageListSortByDate(imageList) { return imageList.sort(function(a, b) { var x = parseInt(a.fullstartdate); var y = parseInt(b.fullstartdate); return ((x < y) ? -1 : ((x > y) ? 1 : 0)); }); } -function shortenName(string, limit) { +export function shortenName(string, limit) { if (string.length > limit) { string = string.substr(0, limit - 4) + '...'; } return string; } -function moveImagesToNewFolder(settings, oldPath, newPath) { +export function moveImagesToNewFolder(settings, oldPath, newPath) { // possible race condition here, need to think about how to fix it //let BingWallpaperDir = settings.get_string('download-folder'); let dir = Gio.file_new_for_path(oldPath); @@ -433,17 +420,17 @@ function moveImagesToNewFolder(settings, oldPath, newPath) { moveBackground(oldPath, newPath, DESKTOP_SCHEMA); } -function dirname(path) { +export function dirname(path) { return path.match(/.*\//); } -function slash(path) { +export function slash(path) { if (!path.endsWith('/')) return path += '/'; return path; } -function moveBackground(oldPath, newPath, schema) { +export function moveBackground(oldPath, newPath, schema) { let gsettings = new Gio.Settings({schema: schema}); let uri = gsettings.get_string('picture-uri'); gsettings.set_string('picture-uri', uri.replace(oldPath, newPath)); @@ -458,12 +445,12 @@ function moveBackground(oldPath, newPath, schema) { gsettings.apply(); } -function log(msg) { +export function log(msg) { if (debug) print("BingWallpaper extension: " + msg); // disable to keep the noise down in journal } -function deleteImage(to_delete) { +export function deleteImage(to_delete) { var file = Gio.file_new_for_path(to_delete); if (file.query_exists(null)) { try { @@ -477,7 +464,7 @@ function deleteImage(to_delete) { } // add image to persistant list so we can delete it later (in chronological order), delete the oldest image (if user wants this) -function purgeImages(settings) { +export function purgeImages(settings) { let deletepictures = settings.get_boolean('delete-previous'); if (deletepictures === false) return; @@ -497,7 +484,7 @@ function purgeImages(settings) { validate_imagename(settings); // if we deleted our current image, we want to reset it to something valid } -function openInSystemViewer(filename, is_file = true) { +export function openInSystemViewer(filename, is_file = true) { let context; try { context = global.create_app_launch_context(0, -1); @@ -510,7 +497,7 @@ function openInSystemViewer(filename, is_file = true) { Gio.AppInfo.launch_default_for_uri(filename, context); } -function exportBingJSON(settings) { +export function exportBingJSON(settings) { let json = settings.get_string('bing-json'); let filepath = getWallpaperDir(settings) + 'bing.json'; let file = Gio.file_new_for_path(filepath); @@ -520,7 +507,7 @@ function exportBingJSON(settings) { } } -function importBingJSON(settings) { +export function importBingJSON(settings) { let filepath = getWallpaperDir(settings) + 'bing.json'; let file = Gio.file_new_for_path(filepath); if (file.query_exists(null)) { From 80a3023596388790a68bc2c81cb0c8a238285805 Mon Sep 17 00:00:00 2001 From: Michael Cardillo Date: Thu, 19 Oct 2023 02:16:11 -0700 Subject: [PATCH 2/2] GNOME 45 Wayland tweaks --- extension.js | 7 +------ utils.js | 9 ++------- 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/extension.js b/extension.js index 3b81dcd1..743cd238 100644 --- a/extension.js +++ b/extension.js @@ -139,11 +139,6 @@ class BingWallpaperIndicator extends Button { getActorCompat(this).visible = !this._settings.get_boolean('hide'); - // enable testing potentially unsafe features on Wayland if the user overrides it - if (!Utils.is_x11() && this._settings.get_boolean('override-unsafe-wayland')) { - Utils.is_x11 = Utils.enabled_unsafe; - } - this.refreshDueItem = newMenuItem(_("")); this.titleItem = new PopupMenu.PopupSubMenuMenuItem(_("Awaiting refresh..."), false); this.explainItem = newMenuItem(_("Awaiting refresh...")); @@ -328,7 +323,7 @@ class BingWallpaperIndicator extends Button { _openMenu() { // Grey out menu items if an update is pending this.refreshItem.setSensitive(!this._updatePending); - if (Utils.is_x11()) { + if (Utils.is_x11(this._settings)) { this.clipboardImageItem.setSensitive(!this._updatePending && this.imageURL != ""); this.clipboardURLItem.setSensitive(!this._updatePending && this.imageURL != ""); } diff --git a/utils.js b/utils.js index 981fd31d..724577fb 100644 --- a/utils.js +++ b/utils.js @@ -136,13 +136,8 @@ export function set_blur_preset(settings, preset) { log("Set blur preset to " + preset.blur + " brightness to " + preset.dim); } -export function is_x11() { - return GLib.getenv('XDG_SESSION_TYPE') == 'x11'; // don't do wayland unsafe things if set -} - -export function enabled_unsafe() { - //log("User override, enabling unsafe Wayland functionality"); - return true; +export function is_x11(settings) { + return settings.get_boolean('override-unsafe-wayland') || GLib.getenv('XDG_SESSION_TYPE') == 'x11'; // don't do wayland unsafe things if set } export function imageHasBasename(image_item, i, b) {