diff --git a/randomwallpaper@iflow.space/jsonpath/jsonpath.js b/randomwallpaper@iflow.space/jsonpath/jsonpath.js new file mode 100644 index 0000000..81c75a4 --- /dev/null +++ b/randomwallpaper@iflow.space/jsonpath/jsonpath.js @@ -0,0 +1,90 @@ +let JSONPathParser = function () { + + /** + * Access a simple json path expression of an object. + * Returns the accessed value or null if the access was not possible. + * + * @param inputObject the object to access + * @param inputString the json path expression + * @returns {*} + */ + this.access = function(inputObject, inputString) { + if (inputObject === null || inputObject === undefined) { + return null; + } + + if (inputString.length === 0) { + return inputObject; + } + + let startDot = inputString.indexOf('.'); + if (startDot === -1) { + startDot = inputString.length; + } + + let keyString = inputString.slice(0, startDot); + let inputStringTail = inputString.slice(startDot+1); + + let startParentheses = keyString.indexOf('['); + + if (startParentheses === -1) { + + let targetObject = this._getTargetObject(inputObject, keyString); + if (targetObject == null) { + return null; + } + + return this.access(targetObject, inputStringTail) + + } else { + + let indexString = keyString.slice(startParentheses+1, keyString.length-1); + keyString = keyString.slice(0, startParentheses); + + let targetObject = this._getTargetObject(inputObject, keyString); + if (targetObject == null) { + return null; + } + + switch (indexString) { + case "@random": + return this.access(this.randomElement(targetObject), inputStringTail); + // add special keywords here + default: + // expecting integer + return this.access(targetObject[parseInt(indexString)], inputStringTail); + } + + } + + }; + + /** + * Check validity of the key string and return the target object or null. + * @param inputObject + * @param keyString + * @returns {*} + * @private + */ + this._getTargetObject = function (inputObject, keyString) { + if (!keyString.empty && keyString !== "$" && !inputObject.hasOwnProperty(keyString)) { + return null; + } + + return (keyString === "$") ? inputObject : inputObject[keyString]; + }; + + /** + * Returns the value of a random key of a given object. + * + * @param inputObject + * @returns {*} + */ + this.randomElement = function(inputObject) { + let keys = Object.keys(inputObject); + let randomIndex = Math.floor(Math.random()*keys.length); + + return inputObject[keys[randomIndex]]; + } + +}; diff --git a/randomwallpaper@iflow.space/prefs.js b/randomwallpaper@iflow.space/prefs.js index b00abcc..d839d13 100644 --- a/randomwallpaper@iflow.space/prefs.js +++ b/randomwallpaper@iflow.space/prefs.js @@ -15,6 +15,7 @@ const RWG_SETTINGS_SCHEMA = 'org.gnome.shell.extensions.space.iflow.randomwallpa 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'; const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven'; +const RWG_SETTINGS_SCHEMA_GENERIC_JSON = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.genericJSON'; const LoggerModule = Self.imports.logger; @@ -41,6 +42,7 @@ const RandomWallpaperSettings = new Lang.Class({ desktopperSettings: null, unsplashSettings: null, wallheavenSettings: null, + genericJsonSettings: null, _init: function () { this._settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA); @@ -67,6 +69,11 @@ const RandomWallpaperSettings = new Lang.Class({ this.wallheavenSettings = this._builder.get_object('wallheaven-settings'); this.bindWallheaven(); + // Generic JSON Settings + this._generic_json_settings = Convenience.getSettings(RWG_SETTINGS_SCHEMA_GENERIC_JSON); + this.genericJsonSettings = this._builder.get_object('generic-json-settings'); + this.bindGenericJSON(); + this._toggleAfSliders(); this.widget = this._builder.get_object('main-widget'); @@ -76,7 +83,7 @@ const RandomWallpaperSettings = new Lang.Class({ }.bind(this)); this._builder.get_object('source-combo').connect('changed', (sourceCombo) => { - let container = this._builder.get_object('source-settings-frame'); + let container = this._builder.get_object('source-settings-container'); if (this.currentSourceSettingsWidget !== null) { container.remove(this.currentSourceSettingsWidget); } @@ -91,13 +98,16 @@ const RandomWallpaperSettings = new Lang.Class({ case 2: // wallheaven this.currentSourceSettingsWidget = this.wallheavenSettings; break; + case 3: // generic JSON + this.currentSourceSettingsWidget = this.genericJsonSettings; + break; default: this.currentSourceSettingsWidget = this.noSettings; break; } container.add(this.currentSourceSettingsWidget); - + container.getParent }); this._settings.bind('history-length', @@ -124,6 +134,10 @@ const RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('change-lock-screen'), 'active', Gio.SettingsBindFlags.DEFAULT); + this._settings.bind('disable-hover-preview', + this._builder.get_object('disable-hover-preview'), + 'active', + Gio.SettingsBindFlags.DEFAULT); }, _toggleAfSliders: function () { @@ -161,6 +175,10 @@ const RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('unsplash-image-height'), 'value', Gio.SettingsBindFlags.DEFAULT); + this._unsplash_settings.bind('featured-only', + this._builder.get_object('unsplash-featured-only'), + 'active', + Gio.SettingsBindFlags.DEFAULT); }, bindWallheaven: function () { @@ -194,6 +212,22 @@ const RandomWallpaperSettings = new Lang.Class({ this._builder.get_object('wallheaven-allow-sketchy'), 'active', Gio.SettingsBindFlags.DEFAULT); + }, + + bindGenericJSON: function () { + 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'), + 'text', + Gio.SettingsBindFlags.DEFAULT); + this._generic_json_settings.bind('generic-json-response-path', + this._builder.get_object('generic-json-response-path'), + 'text', + Gio.SettingsBindFlags.DEFAULT); + this._generic_json_settings.bind('generic-json-url-prefix', + this._builder.get_object('generic-json-url-prefix'), + 'text', + Gio.SettingsBindFlags.DEFAULT); } }); diff --git a/randomwallpaper@iflow.space/schemas/gschemas.compiled b/randomwallpaper@iflow.space/schemas/gschemas.compiled index 4ee1798..8623855 100644 Binary files a/randomwallpaper@iflow.space/schemas/gschemas.compiled and b/randomwallpaper@iflow.space/schemas/gschemas.compiled differ diff --git a/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml b/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml index ec17645..86d4705 100644 --- a/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml +++ b/randomwallpaper@iflow.space/schemas/org.gnome.shell.extensions.space.iflow.randomwallpaper.gschema.xml @@ -5,6 +5,7 @@ + Weather the gnome lock screen should also be set to the new wallpaper. + + false + Disable hover preview + Disables the preview of the background while hovering the history list + + Image Width The height of the image. + + false + Featured images only + This results in a smaller wallpaper pool but the images are considered to have higher quality. + Weather the people category should be searched. + + + + "" + The request URL + The URL where the JSON will be requested. + + + "" + JSON Path + The JSON path that describes the picture URL. + + + "" + Image URL prefix + This prefix is added to the final image URL. + + + diff --git a/randomwallpaper@iflow.space/settings.ui b/randomwallpaper@iflow.space/settings.ui index 6d6d54c..2134cbd 100644 --- a/randomwallpaper@iflow.space/settings.ui +++ b/randomwallpaper@iflow.space/settings.ui @@ -1,5 +1,5 @@ - + @@ -38,150 +38,39 @@ 1 10 - - 1 - 100 - 10 - 1 - 10 - - - 500 + True False - 15 - 15 - 15 - 15 + 10 + 10 + 10 + 10 vertical 10 - + True False - 0 - in - - - 500 - True - False - 10 - 10 - 10 - 10 - True - 10 - - - True - False - True - 10 - 2 - - - True - False - True - True - - - True - False - start - Wallpaper Source - - - 0 - 0 - - - - - True - False - True - The source that is used to fetch random wallpapers. You can select between desktoppr.co (default) and an experimental version of wallheaven.cc and unsplash.com. - True - 1 - 0 - - - - 0 - 1 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - True - False - 20 - - - True - False - 0 - - desktoppr.co - unsplash.com (experimental) - alpha.wallheaven.cc (experimental) - - - - 0 - 0 - - - - - 0 - 1 - - - - - True - False - True - 0 - in - - - - - - True - False - Source Settings - - - - - 0 - 2 - - - - - - - + start + This feature requires some know how but many different wallpaper providers can be used with this generic JSON source. +You have to specify an URL to a JSON response and a path to the target picture url within the JSON response. + True + + + False + True + 0 + + + + + button + True + True + True + start + none + https://github.com/ifl0w/RandomWallpaperGnome3/wiki/Generic-JSON-Source False @@ -190,80 +79,35 @@ - - 500 + True False - 0 - in + vertical - + True False - 10 - 10 - 10 - 10 - 10 - True - - - True - False - False - True - - - True - False - start - History length - - - 0 - 0 - - - - - True - False - True - The number of wallpapers that will be shown in the history and stored in the wallpaper folder of this extension. - True - 1 - 0 - - - - 0 - 1 - - - - - 0 - 0 - - - - - True - True - center - history-length - - - 0 - 1 - - + start + Request URL + + False + True + 0 + - - + + + True + True + Request URL + url + + + False + True + 1 + @@ -273,92 +117,34 @@ - + True False - 0 - in + vertical - + True False - 10 - 10 - 10 - 10 - 10 - 2 - - - True - False - True - True - - - True - False - start - Change lock screen - - - 0 - 0 - - - - - True - False - True - Also change the gnome lock screen image to the new wallpaper. - True - True - 1 - 0 - - - - 0 - 1 - - - - - 0 - 0 - - - - - True - False - vertical - - - True - True - end - start - - - False - True - 0 - - - - - 1 - 0 - - + start + JSON Path + + False + True + 0 + - - + + + True + True + JSON Path + + + False + True + 1 + @@ -368,176 +154,34 @@ - - 500 + True False - 0 - in + vertical - + True False - 10 - 10 - 10 - 10 - 10 - True - - - True - False - 10 - 2 - - - True - False - True - True - - - True - False - start - Auto-Fetching - - - 0 - 0 - - - - - True - False - True - Automatically fetch a new wallpaper based on a period. - True - True - 1 - 0 - - - - 0 - 1 - - - - - 0 - 0 - - - - - True - False - vertical - - - True - True - end - start - - - False - True - 0 - - - - - 1 - 0 - - - - - 0 - 0 - - - - - True - False - 20 - - - True - False - start - end - Minutes - - - 0 - 1 - - - - - True - False - start - end - Hours - - - 0 - 0 - - - - - True - True - True - duration-hours - True - False - 0 - 0 - 0 - - - 1 - 0 - - - - - True - True - True - duration-minutes - True - False - 0 - 0 - 0 - - - 1 - 1 - - - - - 0 - 1 - - + start + Image URL prefix + + False + True + 0 + - - + + + True + True + Image URL prefix + + + False + True + 1 + @@ -547,6 +191,758 @@ + + 1 + 100 + 10 + 1 + 10 + + + 400 + 600 + True + True + + + True + True + in + True + True + + + True + False + none + + + True + False + 20 + 20 + 20 + 20 + vertical + 10 + + + True + False + 0 + in + + + True + False + 15 + 15 + 15 + 15 + + + 0 + 500 + True + False + True + 10 + + + True + False + True + 10 + 2 + + + True + False + True + True + + + True + False + start + Wallpaper Source + + + 0 + 0 + + + + + True + False + True + The source that is used to fetch random wallpapers. You can select between desktoppr.co (default) and an experimental version of wallheaven.cc and unsplash.com. + True + 1 + 0 + + + + 0 + 1 + + + + + 0 + 0 + + + + + 0 + 0 + + + + + True + False + 20 + + + True + False + 0 + + desktoppr.co + unsplash.com + alpha.wallheaven.cc + Generic JSON + + + + 0 + 0 + + + + + 0 + 1 + + + + + True + False + True + 0 + in + + + + + + True + False + Source Settings + + + + + 0 + 2 + + + + + + + + + + + + False + True + 0 + + + + + True + False + 0 + in + + + True + False + 15 + 15 + 15 + 15 + + + True + False + 10 + 2 + + + True + False + True + True + + + True + False + start + Change lock screen + + + 0 + 0 + + + + + True + False + True + Also change the gnome lock screen image to the new wallpaper. + True + True + 1 + 0 + + + + 0 + 1 + + + + + 0 + 0 + + + + + True + False + vertical + + + True + True + end + start + + + False + True + 0 + + + + + 1 + 0 + + + + + + + + + + + + False + True + 1 + + + + + True + False + 0 + in + + + True + False + 15 + 15 + 15 + 15 + + + True + False + 10 + 2 + + + True + False + True + True + + + True + False + start + Disable hover preview + + + 0 + 0 + + + + + True + False + True + Disable the desktop preview of the background while hovering the history items. Try enabeling if you encounter crashes or laggs of the gnome shell while using the extension. + True + True + 1 + 0 + + + + 0 + 1 + + + + + 0 + 0 + + + + + True + False + vertical + + + True + True + end + start + + + False + True + 0 + + + + + 1 + 0 + + + + + + + + + + + + False + True + 2 + + + + + + + + + + + True + False + General + + + False + + + + + True + True + in + True + True + + + True + False + none + + + True + False + 20 + 20 + 20 + 20 + vertical + + + True + False + 0 + in + + + True + False + 15 + 15 + 15 + 15 + + + True + False + 10 + True + + + True + False + False + True + + + True + False + start + History length + + + 0 + 0 + + + + + True + False + True + The number of wallpapers that will be shown in the history and stored in the wallpaper folder of this extension. + True + 1 + 0 + + + + 0 + 1 + + + + + 0 + 0 + + + + + True + True + center + 10 + history-length + 10 + + + 0 + 1 + + + + + + + + + + + + False + True + 0 + + + + + + + + + 1 + + + + + True + False + History + + + 1 + False + + + + + True + True + in + True + True + + + True + False + none + + + True + False + 20 + 20 + 20 + 20 + vertical + 10 + + + True + False + 0 + in + + + True + False + 15 + 15 + 15 + 15 + + + True + False + 10 + True + + + True + False + 10 + 2 + + + True + False + True + True + + + True + False + start + Auto-Fetching + + + 0 + 0 + + + + + True + False + True + Automatically fetch a new wallpaper based on a period. + True + True + 1 + 0 + + + + 0 + 1 + + + + + 0 + 0 + + + + + True + False + vertical + + + True + True + end + start + + + False + True + 0 + + + + + 1 + 0 + + + + + 0 + 0 + + + + + True + False + 20 + + + True + False + start + end + Minutes + + + 0 + 1 + + + + + True + False + start + end + Hours + + + 0 + 0 + + + + + True + True + True + duration-hours + True + False + 0 + 0 + 0 + + + 1 + 0 + + + + + True + True + True + duration-minutes + True + False + 0 + 0 + 0 + + + 1 + 1 + + + + + 0 + 1 + + + + + + + + + + + + False + True + 0 + + + + + + + + + 2 + + + + + True + False + Auto-Fetching + + + 2 + False + + + True False @@ -722,6 +1118,73 @@ 4 + + + True + False + + + True + False + True + vertical + + + True + False + start + Only Featured Images + + + False + True + 0 + + + + + True + False + This results in a smaller wallpaper pool but the images are considered to have higher quality. + True + 1 + 0 + + + + False + True + 1 + + + + + 0 + 0 + + + + + True + True + end + start + + + 1 + 0 + + + + + False + True + 10 + 5 + + True diff --git a/randomwallpaper@iflow.space/sourceAdapter.js b/randomwallpaper@iflow.space/sourceAdapter.js index 3305226..6b80657 100644 --- a/randomwallpaper@iflow.space/sourceAdapter.js +++ b/randomwallpaper@iflow.space/sourceAdapter.js @@ -8,11 +8,13 @@ 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'; const RWG_SETTINGS_SCHEMA_WALLHEAVEN = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.wallheaven'; +const RWG_SETTINGS_SCHEMA_GENERIC_JSON = 'org.gnome.shell.extensions.space.iflow.randomwallpaper.genericJSON'; const SettingsModule = Self.imports.settings; const HistoryModule = Self.imports.history; const LoggerModule = Self.imports.logger; +const JSONPath = Self.imports.jsonpath.jsonpath; let BaseAdapter = new Lang.Class({ Name: "BaseAdapter", @@ -33,7 +35,11 @@ let BaseAdapter = new Lang.Class({ }, fileName: function (uri) { - let base = new String(uri).substring(uri.lastIndexOf('/') + 1); + let base = decodeURIComponent(uri); + base = base.substring(base.lastIndexOf('/') + 1); + if(base.indexOf('?') >= 0) { + base = base.substr(0, base.indexOf('?')); + } return base; }, @@ -62,7 +68,6 @@ let DesktopperAdapter = new Lang.Class({ url += '?safe_filter=safe'; } url = encodeURI(url); - this.logger.debug("Base URL: " + url); let message = Soup.Message.new('GET', url); @@ -95,6 +100,7 @@ let UnsplashAdapter = new Lang.Class({ 'query': '', 'w': 1920, 'h': 1080, + 'featured': false }, _init: function () { @@ -111,7 +117,6 @@ let UnsplashAdapter = new Lang.Class({ let url = 'https://api.unsplash.com/photos/random?' + optionsString; url += 'client_id=64daf439e9b579dd566620c0b07022706522d87b255d06dd01d5470b7f193b8d'; url = encodeURI(url); - this.logger.debug("Base URL: " + url); let message = Soup.Message.new('GET', url); @@ -152,12 +157,14 @@ let UnsplashAdapter = new Lang.Class({ this.options.query = this._settings.get('unsplash-keyword', 'string'); this.options.username = this._settings.get('username', 'string'); - if (this.options.username[0] === '@') { + if (this.options.username && this.options.username[0] === '@') { this.options.username = this.options.username.substring(1); // remove @ prefix } this.options.w = this._settings.get('image-width', 'int'); this.options.h = this._settings.get('image-height', 'int'); + + this.options.featured = this._settings.get('featured-only', 'boolean'); } }); @@ -188,7 +195,6 @@ let WallheavenAdapter = new Lang.Class({ let optionsString = this._generateOptionsString(); let url = 'http://alpha.wallhaven.cc/search?' + optionsString; url = encodeURI(url); - this.logger.debug("Base URL: " + url); let message = Soup.Message.new('GET', url); @@ -264,3 +270,40 @@ let WallheavenAdapter = new Lang.Class({ this.options.purity = purity.join(''); } }); + +let GenericJsonAdapter = new Lang.Class({ + Name: "GenericJsonAdapter", + Extends: BaseAdapter, + + _settings: null, + _jsonPathParser: null, + + _init: function () { + this.parent(); + this._jsonPathParser = new JSONPath.JSONPathParser(); + this._settings = new SettingsModule.Settings(RWG_SETTINGS_SCHEMA_GENERIC_JSON); + }, + + requestRandomImage: function (callback) { + let session = new Soup.SessionAsync(); + + let url = this._settings.get("generic-json-request-url", "string"); + url = encodeURI(url); + + let message = Soup.Message.new('GET', url); + + session.queue_message(message, (session, message) => { + let response = JSON.parse(message.response_body.data); + let JSONPath = this._settings.get("generic-json-response-path", "string"); + let imageUrl = this._jsonPathParser.access(response, JSONPath); + imageUrl = this._settings.get("generic-json-url-prefix", "string")+imageUrl; + + if (callback) { + let historyEntry = new HistoryModule.HistoryEntry(null, 'Generic JSON Source', imageUrl); + historyEntry.source.sourceUrl = imageUrl; + callback(historyEntry); + } + }); + + } +}); diff --git a/randomwallpaper@iflow.space/wallpaperController.js b/randomwallpaper@iflow.space/wallpaperController.js index 86a0c7f..bc5446a 100644 --- a/randomwallpaper@iflow.space/wallpaperController.js +++ b/randomwallpaper@iflow.space/wallpaperController.js @@ -60,6 +60,7 @@ let WallpaperController = new Lang.Class({ this._desktopperAdapter = new SourceAdapter.DesktopperAdapter(); this._unsplashAdapter = new SourceAdapter.UnsplashAdapter(); this._wallheavenAdapter = new SourceAdapter.WallheavenAdapter(); + this._genericJsonAdapter = new SourceAdapter.GenericJsonAdapter(); this.logger = new LoggerModule.Logger('RWG3', 'WallpaperController'); }, @@ -98,6 +99,9 @@ let WallpaperController = new Lang.Class({ case 2: this.imageSourceAdapter = this._wallheavenAdapter; break; + case 3: + this.imageSourceAdapter = this._genericJsonAdapter; + break; default: this.imageSourceAdapter = this._desktopperAdapter; break; @@ -178,7 +182,8 @@ let WallpaperController = new Lang.Class({ */ if (settings.is_writable("picture-uri")) { // Set a new Background-Image (should show up immediately): - if (settings.set_string("picture-uri", path)) { + let rc = settings.set_string("picture-uri", path); + if (rc) { Gio.Settings.sync(); // Necessary: http://stackoverflow.com/questions/9985140 // call callback if given @@ -240,7 +245,7 @@ let WallpaperController = new Lang.Class({ }); }, - _backgroundTimout: function (delay) { + _backgroundTimeout: function (delay) { if (this.timeout) { return; } @@ -260,15 +265,19 @@ let WallpaperController = new Lang.Class({ }, previewWallpaper: function (historyid, delay) { - this.previewId = historyid; - this._resetWallpaper = false; + if (!this._settings.get('disable-hover-preview', 'boolean')) { + this.previewId = historyid; + this._resetWallpaper = false; - this._backgroundTimout(delay); + this._backgroundTimeout(delay); + } }, resetWallpaper: function () { - this._resetWallpaper = true; - this._backgroundTimout(); + if (!this._settings.get('disable-hover-preview', 'boolean')) { + this._resetWallpaper = true; + this._backgroundTimeout(); + } }, getHistoryController: function () {