diff --git a/randomwallpaper@iflow.space/elements.js b/randomwallpaper@iflow.space/elements.js index a8f610b..a354191 100644 --- a/randomwallpaper@iflow.space/elements.js +++ b/randomwallpaper@iflow.space/elements.js @@ -8,26 +8,19 @@ const Clutter = imports.gi.Clutter; const Cogl = imports.gi.Cogl; const Gtk = imports.gi.Gtk; -// Filesystem -const Gio = imports.gi.Gio; - const Self = imports.misc.extensionUtils.getCurrentExtension(); const LoggerModule = Self.imports.logger; const Timer = Self.imports.timer; -var HistoryElement = new Lang.Class({ - Name: 'HistoryElement', - Extends: PopupMenu.PopupSubMenuMenuItem, - logger: null, - historyEntry: null, +var HistoryElement = class extends PopupMenu.PopupSubMenuMenuItem { - setAsWallpaperItem: null, - previewItem: null, - _previewActor: null, - - _init: function (historyEntry, index) { - this.parent("", false); + constructor(historyEntry, index) { + super("", false); this.logger = new LoggerModule.Logger('RWG3', 'HistoryElement'); + this.historyEntry = null; + this.setAsWallpaperItem = null; + this.previewItem = null; + this._previewActor = null; let timestamp = historyEntry.timestamp; let date = new Date(timestamp); @@ -149,26 +142,25 @@ var HistoryElement = new Lang.Class({ } } }) - }, + } - setIndex: function(index) { + setIndex(index) { this.prefixLabel.set_text(String(index)); - }, + } -}); +}; -var CurrentImageElement = new Lang.Class({ - Name: 'CurrentImageElement', - Extends: HistoryElement, +var CurrentImageElement = class extends HistoryElement { - _init: function (historyElement) { - this.parent(historyElement, 0); + constructor(historyElement) { + super(historyElement, 0); if (this.setAsWallpaperItem !== null) { this.setAsWallpaperItem.destroy(); } } -}); + +}; /** * Element for the New Wallpaper button and the remaining time for the auto fetch @@ -177,12 +169,10 @@ var CurrentImageElement = new Lang.Class({ * * @type {Lang.Class} */ -var NewWallpaperElement = new Lang.Class({ - Name: 'NewWallpaperElement', - Extends: PopupMenu.PopupBaseMenuItem, +var NewWallpaperElement = class extends PopupMenu.PopupBaseMenuItem { - _init: function (params) { - this.parent(params); + constructor(params) { + super(params); this._timer = new Timer.AFTimer(); @@ -202,9 +192,9 @@ var NewWallpaperElement = new Lang.Class({ this._container.add_child(this._remainingLabel); this.actor.add_child(this._container); - }, + } - show: function () { + show() { if (this._timer.isActive()) { let remainingMinutes = this._timer.remainingMinutes(); let minutes = remainingMinutes % 60; @@ -226,14 +216,12 @@ var NewWallpaperElement = new Lang.Class({ this._remainingLabel.hide(); } } -}); -var StatusElement = new Lang.Class({ - Name: 'StatusElement', +}; - icon: null, +var StatusElement = class { - _init: function () { + constructor() { this.icon = new St.Icon({ icon_name: 'preferences-desktop-wallpaper-symbolic', style_class: 'system-status-icon' @@ -272,34 +260,32 @@ var StatusElement = new Lang.Class({ } } - }, + } - startLoading: function () { + startLoading() { this.isLoading = true; Tweener.addTween(this.icon, this.loadingTweenOut); - }, + } - stopLoading: function () { + stopLoading() { this.isLoading = false; Tweener.removeTweens(this.icon); this.icon.opacity = 255; } -}); +}; -var HistorySection = new Lang.Class({ - Name: 'HistorySection', - Extends: PopupMenu.PopupMenuSection, +var HistorySection = class extends PopupMenu.PopupMenuSection { - /** - * Cache HistoryElements for performance of long histories. - */ - _historySectionCache: {}, + constructor() { + super(); - _historyCache: [], + /** + * Cache HistoryElements for performance of long histories. + */ + this._historySectionCache = {}; - _init: function () { - this.parent(); + this._historyCache = []; this.actor = new St.ScrollView({ hscrollbar_policy: Gtk.PolicyType.NEVER, @@ -307,9 +293,9 @@ var HistorySection = new Lang.Class({ }); this.actor.add_actor(this.box); - }, + } - updateList: function(history, onEnter, onLeave, onSelect) { + updateList(history, onEnter, onLeave, onSelect) { if (this._historyCache.length <= 1) { this.removeAll(); // remove empty history element } @@ -330,7 +316,7 @@ var HistorySection = new Lang.Class({ tmp.connect('activate', onSelect); this._historySectionCache[historyID] = tmp; - this.addMenuItem(tmp, i-1); + this.addMenuItem(tmp, i - 1); } else { tmp = this._historySectionCache[historyID]; tmp.setIndex(i); @@ -341,18 +327,18 @@ var HistorySection = new Lang.Class({ this._cleanupHistoryCache(existingHistoryElements); this._historyCache = history; - }, + } - _cleanupHistoryCache: function(existingIDs) { + _cleanupHistoryCache(existingIDs) { let destroyIDs = Object.keys(this._historySectionCache).filter((i) => existingIDs.indexOf(i) === -1); destroyIDs.map(id => { this._historySectionCache[id].destroy(); delete this._historySectionCache[id]; }); - }, + } - clear: function() { + clear() { this._cleanupHistoryCache([]); this.removeAll(); this.addMenuItem( @@ -365,7 +351,6 @@ var HistorySection = new Lang.Class({ ); this._historyCache = []; - }, - -}); + } +}; diff --git a/randomwallpaper@iflow.space/extension.js b/randomwallpaper@iflow.space/extension.js index 6e717a3..c1b18ff 100644 --- a/randomwallpaper@iflow.space/extension.js +++ b/randomwallpaper@iflow.space/extension.js @@ -1,215 +1,33 @@ -const Lang = imports.lang; -const GLib = imports.gi.GLib; -const Shell = imports.gi.Shell; - //self const Self = imports.misc.extensionUtils.getCurrentExtension(); const WallpaperController = Self.imports.wallpaperController; - +const RandomWallpaperMenu = Self.imports.randomWallpaperMenu; const LoggerModule = Self.imports.logger; -// UI Imports -const Main = imports.ui.main; -const St = imports.gi.St; -const PanelMenu = imports.ui.panelMenu; -const PopupMenu = imports.ui.popupMenu; -const CustomElements = Self.imports.elements; -const Tweener = imports.ui.tweener; - const Timer = Self.imports.timer; -// Filesystem -const Gio = imports.gi.Gio; - -// Settings -const Prefs = Self.imports.settings; - let wallpaperController; -let panelEntry; - -let settings; -let hidePanelIconHandler = null; +let panelMenu; +let logger; function init(metaData) { - settings = new Prefs.Settings(); + logger = new LoggerModule.Logger("RWG3", "Main"); wallpaperController = new WallpaperController.WallpaperController(); } function enable() { // enable Extension - - // UI - panelEntry = new RandomWallpaperEntry(0, "Random wallpaper"); - - // add to panel - Main.panel.addToStatusArea("random-wallpaper-menu", panelEntry); - - hidePanelIconHandler = settings.observe('hide-panel-icon', updatePanelMenuVisibility); - updatePanelMenuVisibility(); + logger.info("Enable extension."); + panelMenu = new RandomWallpaperMenu.RandomWallpaperMenu(wallpaperController); + panelMenu.init(); } function disable() { // disable Extension - panelEntry.clearHistoryList(); - panelEntry.destroy(); - - // remove all signal handlers - if (hidePanelIconHandler !== null) { - settings.disconnect(hidePanelIconHandler); - } + logger.info("Disable extension."); + panelMenu.cleanup(); // cleanup the timer singleton let timer = new Timer.AFTimer(); timer.cleanup(); } - -function updatePanelMenuVisibility(isVisible) { - - if (settings.get('hide-panel-icon', 'boolean')) { - panelEntry.actor.hide(); - } else { - panelEntry.actor.show(); - } - -} - -var RandomWallpaperEntry = new Lang.Class({ - Extends: PanelMenu.Button, - Name: "RandomWallpaperEntry", - logger: null, - - _init: function (menuAlignment, nameText) { - this.parent(menuAlignment, nameText); - this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaperEntry'); - - // Panelmenu Icon - this.statusIcon = new CustomElements.StatusElement(); - this.actor.add_child(this.statusIcon.icon); - - // new wallpaper button - this.newWallpaperItem = new CustomElements.NewWallpaperElement(); - - this.menu.addMenuItem(this.newWallpaperItem); - - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - // current background section - this.currentBackgroundSection = new PopupMenu.PopupMenuSection(); - this.menu.addMenuItem(this.currentBackgroundSection); - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - // history section - this.historySection = new CustomElements.HistorySection(); - this.menu.addMenuItem(this.historySection); - - this.setHistoryList(); - - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); - - // clear history button - this.clearHistoryItem = new PopupMenu.PopupMenuItem('Clear History'); - this.menu.addMenuItem(this.clearHistoryItem); - - // open wallpaper folder button - this.openFolder = new PopupMenu.PopupMenuItem('Open Wallpaper Folder'); - this.menu.addMenuItem(this.openFolder); - - // settings button - this.openSettings = new PopupMenu.PopupMenuItem('Settings'); - this.menu.addMenuItem(this.openSettings); - - /* - add eventlistener - */ - wallpaperController.registerStartLoadingHook(this.statusIcon.startLoading.bind(this.statusIcon)); - wallpaperController.registerStopLoadingHook(this.statusIcon.stopLoading.bind(this.statusIcon)); - wallpaperController.registerStopLoadingHook(this.setHistoryList.bind(this)); - - // new wallpaper event - this.newWallpaperItem.connect('activate', function () { - wallpaperController.fetchNewWallpaper(); - }); - - // clear history event - this.clearHistoryItem.connect('activate', function () { - wallpaperController.deleteHistory(); - }); - - // Open Wallpaper Folder - this.openFolder.connect('activate', function (event) { - let uri = GLib.filename_to_uri(wallpaperController.wallpaperlocation, ""); - Gio.AppInfo.launch_default_for_uri(uri, global.create_app_launch_context(0, -1)) - }); - - this.openSettings.connect("activate", function () { - // call gnome settings tool for this extension - let app = Shell.AppSystem.get_default().lookup_app("gnome-shell-extension-prefs.desktop"); - if (app != null) { - // only works in Gnome >= 3.12 - let info = app.get_app_info(); - let timestamp = global.display.get_current_time_roundtrip(); - info.launch_uris([Self.uuid], global.create_app_launch_context(timestamp, -1)); - } - }); - - this.menu.actor.connect('show', function () { - this.newWallpaperItem.show(); - }.bind(this)); - - // when the popupmenu disapears, check if the wallpaper is the original and - // reset it if needed - this.menu.actor.connect('hide', () => { - wallpaperController.resetWallpaper(); - }); - - this.menu.actor.connect('leave-event', () => { - wallpaperController.resetWallpaper(); - }); - - settings.observe('history', this.setHistoryList.bind(this)); - }, - - setCurrentBackgroundElement: function () { - this.currentBackgroundSection.removeAll(); - - let historyController = wallpaperController.getHistoryController(); - let history = historyController.history; - - if (history.length > 0) { - let currentImage = new CustomElements.CurrentImageElement(history[0]); - this.currentBackgroundSection.addMenuItem(currentImage); - } - }, - - setHistoryList: function () { - wallpaperController.update(); - this.setCurrentBackgroundElement(); - - let historyController = wallpaperController.getHistoryController(); - let history = historyController.history; - - if (history.length <= 1) { - this.clearHistoryList(); - return; - } - - function onLeave(actor) { - wallpaperController.resetWallpaper(); - } - - function onEnter(actor) { - wallpaperController.previewWallpaper(actor.historyId); - } - - function onSelect(actor) { - wallpaperController.setWallpaper(actor.historyEntry.id); - } - - this.historySection.updateList(history, onEnter, onLeave, onSelect); - }, - - clearHistoryList: function () { - this.historySection.clear(); - }, - -}); diff --git a/randomwallpaper@iflow.space/history.js b/randomwallpaper@iflow.space/history.js index 9cd25cc..9aaa73e 100644 --- a/randomwallpaper@iflow.space/history.js +++ b/randomwallpaper@iflow.space/history.js @@ -1,6 +1,3 @@ -const Lang = imports.lang; -const Mainloop = imports.gi.GLib; - // Filesystem const Gio = imports.gi.Gio; @@ -9,14 +6,12 @@ const Prefs = Self.imports.settings; const LoggerModule = Self.imports.logger; -var HistoryEntry = new Lang.Class({ - Name: "HistoryEntry", - timestamp: null, - id: null, - path: null, - source: null, +var HistoryEntry = class { - _init: function (author, source, url) { + constructor(author, source, url) { + this.id = null; + this.path = null; + this.source = null; this.timestamp = new Date().getTime(); this.source = { @@ -27,39 +22,34 @@ var HistoryEntry = new Lang.Class({ imageDownloadUrl: url, // URL used for downloading the image imageLinkUrl: url // URL used for linking back to the website of the image }; - }, -}); + } -var HistoryController = new Lang.Class({ - Name: "HistoryController", - _settings: null, - _wallpaperlocation: null, +}; - logger: null, - size: 10, - history: [], +var HistoryController = class { - _init: function (wallpaperlocation) { + constructor(wallpaperlocation) { this.logger = new LoggerModule.Logger('RWG3', 'HistoryController'); - + this.size = 10; + this.history = []; this._settings = new Prefs.Settings(); this._wallpaperlocation = wallpaperlocation; this.load(); - }, + } - insert: function (historyElement) { + insert(historyElement) { this.history.unshift(historyElement); this._deleteOldPictures(); this.save(); - }, + } /** * Set the given id to to the first history element (the current one) * @param id * @returns {boolean} */ - promoteToActive: function (id) { + promoteToActive(id) { let element = this.get(id); if (element === null) { return false; @@ -72,14 +62,14 @@ var HistoryController = new Lang.Class({ this.save(); return true; - }, + } /** * Returns the corresponding HistoryEntry or null * @param id * @returns {*} */ - get: function (id) { + get(id) { for (let elem of this.history) { if (elem.id == id) { return elem; @@ -87,35 +77,35 @@ var HistoryController = new Lang.Class({ } return null; - }, + } /** * Load the history from the gschema */ - load: function () { + load() { this.size = this._settings.get('history-length', 'int'); let stringHistory = this._settings.get('history', 'strv'); this.history = stringHistory.map(elem => { return JSON.parse(elem) }); - }, + } /** * Save the history to the gschema */ - save: function () { + save() { let stringHistory = this.history.map(elem => { return JSON.stringify(elem) }); this._settings.set('history', 'strv', stringHistory); Gio.Settings.sync(); - }, + } /** * Clear the history and delete all photos except the current one. * @returns {boolean} */ - clear: function () { + clear() { let firstHistoryElement = this.history[0]; if (firstHistoryElement) @@ -147,19 +137,19 @@ var HistoryController = new Lang.Class({ this.save(); return true; - }, + } /** * Delete all pictures that have no slot in the history. * @private */ - _deleteOldPictures: function () { + _deleteOldPictures() { this.size = this._settings.get('history-length', 'int'); let deleteFile; while (this.history.length > this.size) { deleteFile = Gio.file_new_for_path(this.history.pop().path); deleteFile.delete(null); } - }, + } -}); \ No newline at end of file +}; \ No newline at end of file diff --git a/randomwallpaper@iflow.space/logger.js b/randomwallpaper@iflow.space/logger.js index 264cb74..8288550 100644 --- a/randomwallpaper@iflow.space/logger.js +++ b/randomwallpaper@iflow.space/logger.js @@ -1,32 +1,28 @@ -const Lang = imports.lang; +var Logger = class { -var Logger = new Lang.Class({ - Name: "Logger", - _prefix: null, - _callingClass: null, - - _init: function (prefix, callingClass) { + constructor(prefix, callingClass) { this._prefix = prefix; this._callingClass = callingClass; - }, + } - _log: function (level, message) { + _log(level, message) { global.log(this._prefix + " [" + level + "] >> " + this._callingClass + " :: " + message); - }, + } - debug: function (message) { + debug(message) { this._log("DEBUG", message); - }, + } - info: function (message) { + info(message) { this._log("INFO", message); - }, + } - warn: function (message) { + warn(message) { this._log("WARNING", message); - }, + } - error: function (message) { + error(message) { this._log("ERROR", message); } -}); \ No newline at end of file + +}; diff --git a/randomwallpaper@iflow.space/prefs.js b/randomwallpaper@iflow.space/prefs.js index 5d194a0..d56545a 100644 --- a/randomwallpaper@iflow.space/prefs.js +++ b/randomwallpaper@iflow.space/prefs.js @@ -1,8 +1,6 @@ const Gio = imports.gi.Gio; const GLib = imports.gi.GLib; const Gtk = imports.gi.Gtk; -const Gdk = imports.gi.Gdk; -const Lang = imports.lang; const ExtensionUtils = imports.misc.extensionUtils; const Self = ExtensionUtils.getCurrentExtension(); @@ -10,9 +8,6 @@ const Convenience = Self.imports.convenience; const WallpaperController = Self.imports.wallpaperController; -const Gettext = imports.gettext.domain('space.iflow.randomwallpaper'); -//const _ = Gettext.gettext; - const RWG_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.space.iflow.randomwallpaper'; const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper'; const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash'; @@ -35,28 +30,20 @@ function buildPrefsWidget() { } /* UI Setup */ -var RandomWallpaperSettings = new Lang.Class({ - Name: 'RandomWallpaper.Settings', - logger: null, +var RandomWallpaperSettings = class { - currentSourceSettingsWidget: null, + constructor() { + this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaper.Settings'); - noSettings: null, - desktopperSettings: null, - unsplashSettings: null, - wallhavenSettings: null, - redditSettings: null, - genericJsonSettings: null, + this.currentSourceSettingsWidget = null; - _wallpaperController: null, + this._wallpaperController = null; - _init: function () { this._settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA); this._builder = new Gtk.Builder(); //this._builder.set_translation_domain(Self.metadata['gettext-domain']); this._builder.add_from_file(Self.path + '/settings.ui'); - this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaper.Settings'); this.noSettings = this._builder.get_object('no-settings'); @@ -158,9 +145,9 @@ var RandomWallpaperSettings = new Lang.Class({ this._wallpaperController = new WallpaperController.WallpaperController(); this._bindButtons(); - }, + } - _toggleAfSliders: function () { + _toggleAfSliders() { if (this._builder.get_object('af-switch').active) { this._builder.get_object('duration-slider-hours').set_sensitive(true); this._builder.get_object('duration-slider-minutes').set_sensitive(true); @@ -168,16 +155,16 @@ var RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('duration-slider-hours').set_sensitive(false); this._builder.get_object('duration-slider-minutes').set_sensitive(false); } - }, + } - bindDesktopper: function () { + bindDesktopper() { this._desktopper_settings.bind('allow-unsafe', this._builder.get_object('desktopper-allow-unsafe'), 'active', Gio.SettingsBindFlags.DEFAULT); - }, + } - bindUnsplash: function () { + bindUnsplash() { this._unsplash_settings.bind('unsplash-keyword', this._builder.get_object('unsplash-keyword'), 'text', @@ -202,9 +189,9 @@ var RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('unsplash-featured-only'), 'active', Gio.SettingsBindFlags.DEFAULT); - }, + } - bindWallhaven: function () { + bindWallhaven() { this._wallhaven_settings.bind('wallhaven-keyword', this._builder.get_object('wallhaven-keyword'), 'text', @@ -235,9 +222,9 @@ var RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('wallhaven-allow-sketchy'), 'active', Gio.SettingsBindFlags.DEFAULT); - }, + } - bindReddit: function () { + bindReddit() { this._reddit_settings.bind('subreddits', this._builder.get_object('reddit-subreddits'), 'text', @@ -246,9 +233,9 @@ var RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('reddit-allow-sfw'), 'active', Gio.SettingsBindFlags.DEFAULT); - }, + } - bindGenericJSON: function () { + bindGenericJSON() { this._builder.get_object('generic-json-docs-link').set_label("More information here"); this._generic_json_settings.bind('generic-json-request-url', this._builder.get_object('generic-json-request-url'), @@ -262,9 +249,9 @@ var RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('generic-json-url-prefix'), 'text', Gio.SettingsBindFlags.DEFAULT); - }, + } - _bindButtons: function () { + _bindButtons() { let newWallpaperButton = this._builder.get_object('request-new-wallpaper'); let origNewWallpaperText = newWallpaperButton.get_label(); newWallpaperButton.connect('clicked', () => { @@ -272,7 +259,7 @@ var RandomWallpaperSettings = new Lang.Class({ newWallpaperButton.set_sensitive(false); this._wallpaperController.update(); - this._wallpaperController.fetchNewWallpaper(()=>{ + this._wallpaperController.fetchNewWallpaper(() => { this._wallpaperController.update(); newWallpaperButton.set_label(origNewWallpaperText); newWallpaperButton.set_sensitive(true); @@ -290,4 +277,4 @@ var RandomWallpaperSettings = new Lang.Class({ }); } -}); +}; diff --git a/randomwallpaper@iflow.space/randomWallpaperMenu.js b/randomwallpaper@iflow.space/randomWallpaperMenu.js new file mode 100644 index 0000000..b802488 --- /dev/null +++ b/randomwallpaper@iflow.space/randomWallpaperMenu.js @@ -0,0 +1,184 @@ +const GLib = imports.gi.GLib; +const Shell = imports.gi.Shell; + +//self +const Self = imports.misc.extensionUtils.getCurrentExtension(); +const LoggerModule = Self.imports.logger; +const Timer = Self.imports.timer; + +// UI Imports +const PanelMenu = imports.ui.panelMenu; +const PopupMenu = imports.ui.popupMenu; +const CustomElements = Self.imports.elements; +const Main = imports.ui.main; + +// Filesystem +const Gio = imports.gi.Gio; + +// Settings +const Prefs = Self.imports.settings; + +var RandomWallpaperMenu = class { + + constructor(wallpaperController) { + this.panelMenu = new PanelMenu.Button(0, "Random wallpaper"); + this.settings = new Prefs.Settings(); + this.wallpaperController = wallpaperController; + this.logger = new LoggerModule.Logger('RWG3', 'RandomWallpaperEntry'); + this.hidePanelIconHandler = this.settings.observe('hide-panel-icon', this.updatePanelMenuVisibility.bind(this)); + + // Panelmenu Icon + this.statusIcon = new CustomElements.StatusElement(); + this.panelMenu.actor.add_child(this.statusIcon.icon); + + // new wallpaper button + this.newWallpaperItem = new CustomElements.NewWallpaperElement(); + + this.panelMenu.menu.addMenuItem(this.newWallpaperItem); + + this.panelMenu.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + + // current background section + this.currentBackgroundSection = new PopupMenu.PopupMenuSection(); + this.panelMenu.menu.addMenuItem(this.currentBackgroundSection); + this.panelMenu.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + + // history section + this.historySection = new CustomElements.HistorySection(); + this.panelMenu.menu.addMenuItem(this.historySection); + + this.panelMenu.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()); + + // clear history button + this.clearHistoryItem = new PopupMenu.PopupMenuItem('Clear History'); + this.panelMenu.menu.addMenuItem(this.clearHistoryItem); + + // open wallpaper folder button + this.openFolder = new PopupMenu.PopupMenuItem('Open Wallpaper Folder'); + this.panelMenu.menu.addMenuItem(this.openFolder); + + // settings button + this.openSettings = new PopupMenu.PopupMenuItem('Settings'); + this.panelMenu.menu.addMenuItem(this.openSettings); + + /* + add eventlistener + */ + this.wallpaperController.registerStartLoadingHook(this.statusIcon.startLoading.bind(this.statusIcon)); + this.wallpaperController.registerStopLoadingHook(this.statusIcon.stopLoading.bind(this.statusIcon)); + this.wallpaperController.registerStopLoadingHook(this.setHistoryList.bind(this)); + + // new wallpaper event + this.newWallpaperItem.connect('activate', () => { + this.wallpaperController.fetchNewWallpaper(); + }); + + // clear history event + this.clearHistoryItem.connect('activate', () => { + this.wallpaperController.deleteHistory(); + }); + + // Open Wallpaper Folder + this.openFolder.connect('activate', (event) => { + let uri = GLib.filename_to_uri(this.wallpaperController.wallpaperlocation, ""); + Gio.AppInfo.launch_default_for_uri(uri, global.create_app_launch_context(0, -1)) + }); + + this.openSettings.connect("activate", () => { + // call gnome settings tool for this extension + let app = Shell.AppSystem.get_default().lookup_app("gnome-shell-extension-prefs.desktop"); + if (app != null) { + // only works in Gnome >= 3.12 + let info = app.get_app_info(); + let timestamp = global.display.get_current_time_roundtrip(); + info.launch_uris([Self.uuid], global.create_app_launch_context(timestamp, -1)); + } + }); + + this.panelMenu.menu.actor.connect('show', () => { + this.newWallpaperItem.show(); + }); + + // when the popupmenu disapears, check if the wallpaper is the original and + // reset it if needed + this.panelMenu.menu.actor.connect('hide', () => { + this.wallpaperController.resetWallpaper(); + }); + + this.panelMenu.menu.actor.connect('leave-event', () => { + this.wallpaperController.resetWallpaper(); + }); + + this.settings.observe('history', this.setHistoryList.bind(this)); + } + + init() { + this.updatePanelMenuVisibility(); + this.setHistoryList(); + + // add to panel + Main.panel.addToStatusArea("random-wallpaper-menu", this.panelMenu); + } + + cleanup() { + this.clearHistoryList(); + this.panelMenu.destroy(); + + // remove all signal handlers + if (this.hidePanelIconHandler !== null) { + this.settings.disconnect(this.hidePanelIconHandler); + } + } + + updatePanelMenuVisibility() { + if (this.settings.get('hide-panel-icon', 'boolean')) { + this.panelMenu.actor.hide(); + } else { + this.panelMenu.actor.show(); + } + } + + setCurrentBackgroundElement() { + this.currentBackgroundSection.removeAll(); + + let historyController = this.wallpaperController.getHistoryController(); + let history = historyController.history; + + if (history.length > 0) { + let currentImage = new CustomElements.CurrentImageElement(history[0]); + this.currentBackgroundSection.addMenuItem(currentImage); + } + } + + setHistoryList() { + this.wallpaperController.update(); + this.setCurrentBackgroundElement(); + + let historyController = this.wallpaperController.getHistoryController(); + let history = historyController.history; + + if (history.length <= 1) { + this.clearHistoryList(); + return; + } + + function onLeave(actor) { + this.wallpaperController.resetWallpaper(); + } + + function onEnter(actor) { + this.wallpaperController.previewWallpaper(actor.historyId); + } + + function onSelect(actor) { + this.wallpaperController.setWallpaper(actor.historyEntry.id); + } + + this.historySection.updateList(history, onEnter.bind(this), onLeave.bind(this), onSelect.bind(this)); + } + + clearHistoryList() { + this.historySection.clear(); + } + +}; diff --git a/randomwallpaper@iflow.space/settings.js b/randomwallpaper@iflow.space/settings.js index 552ea81..1a34895 100644 --- a/randomwallpaper@iflow.space/settings.js +++ b/randomwallpaper@iflow.space/settings.js @@ -1,13 +1,9 @@ -const Lang = imports.lang; -const Glib = imports.gi.GLib; const Gio = imports.gi.Gio; const Self = imports.misc.extensionUtils.getCurrentExtension(); const Convenience = Self.imports.convenience; -var Settings = new Lang.Class({ - Name: "Settings", - _settings: null, +var Settings = class { /** * Settings object. @@ -15,27 +11,28 @@ var Settings = new Lang.Class({ * @param [schema] * @private */ - _init: function (schema) { + constructor(schema) { this._settings = Convenience.getSettings(schema); - }, + } - observe: function (key, callback) { + observe(key, callback) { return this._settings.connect('changed::' + key, callback); - }, + } - disconnect: function (handler) { + disconnect(handler) { return this._settings.disconnect(handler); - }, + } - set: function (key, type, value) { + set(key, type, value) { if (this._settings['set_' + type](key, value)) { Gio.Settings.sync(); // wait for write } else { throw "Could not set " + key + " (type: " + type + ") with the value " + value; } - }, + } - get: function (key, type) { + get(key, type) { return this._settings['get_' + type](key); } -}); + +}; diff --git a/randomwallpaper@iflow.space/sourceAdapter.js b/randomwallpaper@iflow.space/sourceAdapter.js index 6161ced..ade16ba 100755 --- a/randomwallpaper@iflow.space/sourceAdapter.js +++ b/randomwallpaper@iflow.space/sourceAdapter.js @@ -1,9 +1,7 @@ -const Lang = imports.lang; const Self = imports.misc.extensionUtils.getCurrentExtension(); // network requests const Soup = imports.gi.Soup; -const Json = imports.gi.Json; const RWG_SETTINGS_SCHEMA_DESKTOPPER = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.desktopper'; const RWG_SETTINGS_SCHEMA_UNSPLASH = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.unsplash'; @@ -17,13 +15,11 @@ const HistoryModule = Self.imports.history; const LoggerModule = Self.imports.logger; const JSONPath = Self.imports.jsonpath.jsonpath; -var BaseAdapter = new Lang.Class({ - Name: "BaseAdapter", - logger: null, +var BaseAdapter = class { - _init: function () { + constructor() { this.logger = new LoggerModule.Logger('RWG3', 'BaseAdapter'); - }, + } /** * Retrieves a new url for an image and calls the given callback with an HistoryEntry as parameter. @@ -31,11 +27,11 @@ var BaseAdapter = new Lang.Class({ * * @param callback(historyElement, error) */ - requestRandomImage: function (callback) { + requestRandomImage(callback) { this._error("requestRandomImage not implemented", callback); - }, + } - fileName: function (uri) { + fileName(uri) { while (this._isURIEncoded(uri)) { uri = decodeURIComponent(uri); } @@ -45,9 +41,9 @@ var BaseAdapter = new Lang.Class({ base = base.substr(0, base.indexOf('?')); } return base; - }, + } - _isURIEncoded: function (uri) { + _isURIEncoded(uri) { uri = uri || ''; try { @@ -56,9 +52,9 @@ var BaseAdapter = new Lang.Class({ this.logger.error(err); return false; } - }, + } - _error: function (err, callback) { + _error(err, callback) { let error = {"error": err}; this.logger.error(JSON.stringify(error)); @@ -67,21 +63,17 @@ var BaseAdapter = new Lang.Class({ } } -}); +}; -var DesktopperAdapter = new Lang.Class({ - Name: "DesktopperAdapter", - Extends: BaseAdapter, +var DesktopperAdapter = class extends BaseAdapter { - _settings: null, - - _init: function () { - this.parent(); + constructor() { + super(); this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_DESKTOPPER); - }, + } - requestRandomImage: function (callback) { + requestRandomImage(callback) { let session = new Soup.SessionAsync(); let url = 'https://api.desktoppr.co/1/wallpapers/random'; @@ -117,34 +109,31 @@ var DesktopperAdapter = new Lang.Class({ } }); } -}); -var UnsplashAdapter = new Lang.Class({ - Name: "UnsplashAdapter", - Extends: BaseAdapter, +}; - sourceName: 'Unsplash', - sourceUrl: 'https://unsplash.com/', +var UnsplashAdapter = class extends BaseAdapter { - _settings: null, + constructor() { + super(); - // query options - options: { - 'username': '', - 'query': '', - 'collections': [], - 'w': 1920, - 'h': 1080, - 'featured': false - }, + this.sourceName = 'Unsplash'; + this.sourceUrl = 'https://unsplash.com/'; - _init: function () { - this.parent(); + // query options + this.options = { + 'username': '', + 'query': '', + 'collections': [], + 'w': 1920, + 'h': 1080, + 'featured': false + }; this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_UNSPLASH); - }, + } - requestRandomImage: function (callback) { + requestRandomImage(callback) { let session = new Soup.SessionAsync(); this._readOptionsFromSettings(); @@ -203,9 +192,9 @@ var UnsplashAdapter = new Lang.Class({ } }); }); - }, + } - _generateOptionsString: function () { + _generateOptionsString() { let options = this.options; let optionsString = ""; @@ -218,9 +207,9 @@ var UnsplashAdapter = new Lang.Class({ } return optionsString; - }, + } - _readOptionsFromSettings: function () { + _readOptionsFromSettings() { this.options.query = this._settings.get('unsplash-keyword', 'string'); this.options.username = this._settings.get('unsplash-username', 'string'); @@ -238,29 +227,25 @@ var UnsplashAdapter = new Lang.Class({ this.options.featured = this._settings.get('featured-only', 'boolean'); } -}); +}; -var WallhavenAdapter = new Lang.Class({ - Name: "WallhavenAdapter", - Extends: BaseAdapter, - _settings: null, +var WallhavenAdapter = class extends BaseAdapter { - // query options - options: { - 'q': '', - 'purity': '110', // SFW, sketchy - 'sorting': 'random', - 'categories': '111', // General, Anime, People - 'resolutions': ['1920x1200', '2560x1440'] - }, + constructor() { + super(); - _init: function () { - this.parent(); + this.options = { + 'q': '', + 'purity': '110', // SFW, sketchy + 'sorting': 'random', + 'categories': '111', // General, Anime, People + 'resolutions': ['1920x1200', '2560x1440'] + }; this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_WALLHAVEN); - }, + } - requestRandomImage: function (callback) { + requestRandomImage(callback) { let session = new Soup.SessionAsync(); this._readOptionsFromSettings(); @@ -274,6 +259,11 @@ var WallhavenAdapter = new Lang.Class({ let body = message.response_body.data; let urlArray = body.match(new RegExp(/http[s]*:\/\/alpha.wallhaven.cc\/wallpaper\/[0-9]+/g)); + if (!urlArray || urlArray.length === 0) { + this._error("No image found.", callback); + return; + } + // remove dublicates from array let uniqueUrlArray = urlArray.filter(function (item, pos) { return urlArray.indexOf(item) == pos; @@ -305,14 +295,13 @@ var WallhavenAdapter = new Lang.Class({ } } catch (e) { this._error("Unexpected response. (" + e + ")", callback); - return; } }) }); - }, + } - _generateOptionsString: function () { + _generateOptionsString() { let options = this.options; let optionsString = ""; @@ -329,9 +318,9 @@ var WallhavenAdapter = new Lang.Class({ } return optionsString; - }, + } - _readOptionsFromSettings: function () { + _readOptionsFromSettings() { this.options.q = this._settings.get('wallhaven-keyword', 'string'); this.options.resolutions = this._settings.get('resolutions', 'string').split(','); @@ -351,24 +340,21 @@ var WallhavenAdapter = new Lang.Class({ purity.push(0); // required by wallhaven this.options.purity = purity.join(''); } -}); +}; -var RedditAdapter = new Lang.Class({ - Name: "RedditAdapter", - Extends: BaseAdapter, +var RedditAdapter = class extends BaseAdapter { - _settings: null, + constructor() { + super(); - _init: function () { - this.parent(); this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_REDDIT); - }, + } - _ampDecode: function(string) { - return string.replace(/\&/g,'&'); - }, + _ampDecode(string) { + return string.replace(/\&/g, '&'); + } - requestRandomImage: function (callback) { + requestRandomImage(callback) { let session = new Soup.SessionAsync(); const subreddits = this._settings.get('subreddits', 'string').split(',').map(s => s.trim()).join('+'); @@ -385,11 +371,11 @@ var RedditAdapter = new Lang.Class({ session.queue_message(message, (session, message) => { try { const submissions = JSON.parse(message.response_body.data).data.children.filter(child => { - if(child.data.post_hint !== 'image') return false; - if(require_sfw) return child.data.over_18 === false; + if (child.data.post_hint !== 'image') return false; + if (require_sfw) return child.data.over_18 === false; return true; }); - if(submissions.length === 0) { + if (submissions.length === 0) { this._error("No suitable submissions found!", callback); return; } @@ -405,26 +391,21 @@ var RedditAdapter = new Lang.Class({ } } catch (e) { this._error("Could not create request. (" + e + ")", callback); - return; } }); } -}); -var GenericJsonAdapter = new Lang.Class({ - Name: "GenericJsonAdapter", - Extends: BaseAdapter, +}; - _settings: null, - _jsonPathParser: null, +var GenericJsonAdapter = class extends BaseAdapter { - _init: function () { - this.parent(); + constructor() { + super(); this._jsonPathParser = new JSONPath.JSONPathParser(); this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_GENERIC_JSON); - }, + } - requestRandomImage: function (callback) { + requestRandomImage(callback) { let session = new Soup.SessionAsync(); let url = this._settings.get("generic-json-request-url", "string"); @@ -451,9 +432,9 @@ var GenericJsonAdapter = new Lang.Class({ } } catch (e) { this._error("Unexpected response. (" + e + ")", callback); - return; } }); } -}); + +}; diff --git a/randomwallpaper@iflow.space/timer.js b/randomwallpaper@iflow.space/timer.js index 21c1ca2..2dc7471 100644 --- a/randomwallpaper@iflow.space/timer.js +++ b/randomwallpaper@iflow.space/timer.js @@ -20,49 +20,47 @@ var AFTimer = function () { * * @type {Lang} */ -var _AFTimer = new Lang.Class({ - Name: 'AFTimer', - logger: null, +var _AFTimer = class { - _timeout: null, - _timoutEndCallback: null, - _minutes: 30, - - _init: function () { + constructor() { this.logger = new LoggerModule.Logger('RWG3', 'Timer'); + this._timeout = null; + this._timoutEndCallback = null; + this._minutes = 30; + this._settings = new Prefs.Settings(); - }, + } - isActive: function () { + isActive() { return this._settings.get('auto-fetch', 'boolean'); - }, + } - remainingMinutes: function () { + remainingMinutes() { let minutesElapsed = this._minutesElapsed(); let remainder = minutesElapsed % this._minutes; return Math.max(this._minutes - remainder, 0); - }, + } - registerCallback: function (callback) { + registerCallback(callback) { this._timoutEndCallback = callback; - }, + } /** * Sets the minutes of the timer. * * @param minutes */ - setMinutes: function (minutes) { + setMinutes(minutes) { this._minutes = minutes; - }, + } /** * Start the timer. * * @return void */ - start: function () { + start() { this.cleanup(); let last = this._settings.get('timer-last-trigger', 'int64'); @@ -90,41 +88,41 @@ var _AFTimer = new Lang.Class({ this.reset(); // reset timer this.start(); // restart timer }); - }, + } /** * Stop the timer. * * @return void */ - stop: function () { + stop() { this._settings.set('timer-last-trigger', 'int64', 0); this.cleanup(); - }, + } /** * Cleanup the timeout callback if it exists. * * @return void */ - cleanup: function () { + cleanup() { if (this._timeout) { // only remove if a timeout is active GLib.source_remove(this._timeout); this._timeout = null; } - }, + } /** * Reset the timer. * * @return void */ - reset: function () { + reset() { this._settings.set('timer-last-trigger', 'int64', new Date().getTime()); this.cleanup(); - }, + } - _minutesElapsed: function () { + _minutesElapsed() { let now = Date.now(); let last = this._settings.get('timer-last-trigger', 'int64'); @@ -134,9 +132,9 @@ var _AFTimer = new Lang.Class({ let elapsed = Math.max(now - last, 0); return Math.floor(elapsed / (60 * 1000)); - }, + } - _surpassedInterval: function () { + _surpassedInterval() { let now = Date.now(); let last = this._settings.get('timer-last-trigger', 'int64'); let diff = now - last; @@ -145,4 +143,4 @@ var _AFTimer = new Lang.Class({ return diff > intervalLength; } -}); +}; diff --git a/randomwallpaper@iflow.space/wallpaperController.js b/randomwallpaper@iflow.space/wallpaperController.js index b9d2901..ba0c5da 100644 --- a/randomwallpaper@iflow.space/wallpaperController.js +++ b/randomwallpaper@iflow.space/wallpaperController.js @@ -1,46 +1,33 @@ -const Lang = imports.lang; const Mainloop = imports.gi.GLib; -// network requests -const Soup = imports.gi.Soup; -const Json = imports.gi.Json; - // Filesystem const Gio = imports.gi.Gio; //self const Self = imports.misc.extensionUtils.getCurrentExtension(); const SourceAdapter = Self.imports.sourceAdapter; -const Convenience = Self.imports.convenience; const Prefs = Self.imports.settings; const Timer = Self.imports.timer; const HistoryModule = Self.imports.history; const LoggerModule = Self.imports.logger; -var WallpaperController = new Lang.Class({ - Name: "WallpaperController", - logger: null, +var WallpaperController = class { - wallpaperlocation: '', - currentWallpaper: '', - _historyController: null, - imageSourceAdapter: null, - - _timer: null, - _autoFetch: { - active: false, - duration: 30, - }, - - // functions will be called uppon loading a new wallpaper - _startLoadingHooks: [], - // functions will be called when loading a new wallpaper stopped. If an error occured then the error will be passed as parameter. - _stopLoadingHooks: [], - - _init: function () { + constructor() { this.logger = new LoggerModule.Logger('RWG3', 'WallpaperController'); this.wallpaperlocation = Self.path + '/wallpapers/'; + this.imageSourceAdapter = null; + + this._autoFetch = { + active: false, + duration: 30, + }; + + // functions will be called uppon loading a new wallpaper + this._startLoadingHooks = []; + // functions will be called when loading a new wallpaper stopped. If an error occured then the error will be passed as parameter. + this._stopLoadingHooks = []; this._timer = new Timer.AFTimer(); this._historyController = new HistoryModule.HistoryController(this.wallpaperlocation); @@ -61,13 +48,13 @@ var WallpaperController = new Lang.Class({ this._updateAutoFetching(); this.currentWallpaper = this._getCurrentWallpaper(); - }, + } - _updateHistory: function () { + _updateHistory() { this._historyController.load(); - }, + } - _updateAutoFetching: function () { + _updateAutoFetching() { let duration = 0; duration += this._settings.get('minutes', 'int'); duration += this._settings.get('hours', 'int') * 60; @@ -81,12 +68,12 @@ var WallpaperController = new Lang.Class({ } else { this._timer.stop(); } - }, + } /* forwards the request to the adapter */ - _requestRandomImageFromAdapter: function (callback) { + _requestRandomImageFromAdapter(callback) { this.imageSourceAdapter = this._desktopperAdapter; switch (this._settings.get('source', 'enum')) { case 0: @@ -110,7 +97,7 @@ var WallpaperController = new Lang.Class({ } this.imageSourceAdapter.requestRandomImage(callback); - }, + } /** * copy file from uri to local wallpaper directory and calls the given callback with the name and the full filepath @@ -119,7 +106,7 @@ var WallpaperController = new Lang.Class({ * @param callback(name, path, error) * @private */ - _fetchFile: function (uri, callback) { + _fetchFile(uri, callback) { //extract the name from the url and let date = new Date(); let name = date.getTime() + '_' + this.imageSourceAdapter.fileName(uri); // timestamp ensures uniqueness @@ -156,7 +143,7 @@ var WallpaperController = new Lang.Class({ callback(name, output_file.get_path()); } }); - }, + } /** * Sets the wallpaper and the lockscreen when enabled to the given path. Executes the callback on success. @@ -164,7 +151,7 @@ var WallpaperController = new Lang.Class({ * @param callback * @private */ - _setBackground: function (path, callback) { + _setBackground(path, callback) { let background_setting = new Gio.Settings({schema: "org.gnome.desktop.background"}); path = "file://" + path; @@ -185,7 +172,7 @@ var WallpaperController = new Lang.Class({ } } }); - }, + } /** * Set the picture-uri property of the given settings object to the path. @@ -195,7 +182,7 @@ var WallpaperController = new Lang.Class({ * @param callback * @private */ - _setPictureUriOfSettingsObject: function (settings, path, callback) { + _setPictureUriOfSettingsObject(settings, path, callback) { /* inspired from: https://bitbucket.org/LukasKnuth/backslide/src/7e36a49fc5e1439fa9ed21e39b09b61eca8df41a/backslide@codeisland.org/settings.js?at=master @@ -217,14 +204,14 @@ var WallpaperController = new Lang.Class({ } else { this._bailOutWithCallback("Could not set wallpaper.", callback); } - }, + } - _getCurrentWallpaper: function () { + _getCurrentWallpaper() { let background_setting = new Gio.Settings({schema: "org.gnome.desktop.background"}); return background_setting.get_string("picture-uri").replace(/^(file:\/\/)/, ""); - }, + } - setWallpaper: function (historyId) { + setWallpaper(historyId) { let historyElement = this._historyController.get(historyId); if (this._historyController.promoteToActive(historyElement.id)) { @@ -234,9 +221,9 @@ var WallpaperController = new Lang.Class({ this.logger.warn("The history id (" + historyElement.id + ") could not be found.") // TODO: Error handling history id not found. } - }, + } - fetchNewWallpaper: function (callback) { + fetchNewWallpaper(callback) { this._startLoadingHooks.forEach((element) => { element(); }); @@ -275,9 +262,9 @@ var WallpaperController = new Lang.Class({ }); }); }); - }, + } - _backgroundTimeout: function (delay) { + _backgroundTimeout(delay) { if (this.timeout) { return; } @@ -294,54 +281,55 @@ var WallpaperController = new Lang.Class({ } return false; }); - }, + } - previewWallpaper: function (historyid, delay) { + previewWallpaper(historyid, delay) { if (!this._settings.get('disable-hover-preview', 'boolean')) { this.previewId = historyid; this._resetWallpaper = false; this._backgroundTimeout(delay); } - }, + } - resetWallpaper: function () { + resetWallpaper() { if (!this._settings.get('disable-hover-preview', 'boolean')) { this._resetWallpaper = true; this._backgroundTimeout(); } - }, + } - getHistoryController: function () { + getHistoryController() { return this._historyController; - }, + } - deleteHistory: function () { + deleteHistory() { this._historyController.clear(); - }, + } - update: function () { + update() { this._updateHistory(); this.currentWallpaper = this._getCurrentWallpaper(); - }, + } - registerStartLoadingHook: function (fn) { + registerStartLoadingHook(fn) { if (typeof fn === "function") { this._startLoadingHooks.push(fn) } - }, + } - registerStopLoadingHook: function (fn) { + registerStopLoadingHook(fn) { if (typeof fn === "function") { this._stopLoadingHooks.push(fn) } - }, + } - _bailOutWithCallback: function (msg, callback) { + _bailOutWithCallback(msg, callback) { this.logger.error(msg); if (callback) { callback(); } } -}); + +};