implement basic auto fetching feature

This commit is contained in:
Wolfgang Rumpler 2017-02-24 23:31:35 +01:00
parent c119247182
commit d286edff8b
6 changed files with 240 additions and 84 deletions

View file

@ -4,6 +4,9 @@ const St = imports.gi.St;
const Slider = imports.ui.slider;
const Tweener = imports.ui.tweener;
const Self = imports.misc.extensionUtils.getCurrentExtension();
const Timer = Self.imports.timer;
const HistoryElement = new Lang.Class({
Name: 'HistoryElement',
Extends: PopupMenu.PopupBaseMenuItem,
@ -50,6 +53,64 @@ const HistoryElement = new Lang.Class({
}
});
/**
* Element for the New Wallpaper button and the remaining time for the auto fetch
* feature.
* The remaining time will only be displayed if the af-feature is activated.
*
* @type {Lang.Class}
*/
const NewWallpaperElement = new Lang.Class({
Name: 'NewWallpaperElement',
Extends: PopupMenu.PopupBaseMenuItem,
_init: function(params) {
this.parent(params);
this._timer = new Timer.AFTimer();
this._container = new St.BoxLayout({
vertical: true
});
this._newWPLabel = new St.Label({
text: 'New Wallpaper',
style_class: 'rwg-new-lable'
});
this._container.add_child(this._newWPLabel);
this._remainingLabel = new St.Label({
text: '1 minute remaining'
});
this._container.add_child(this._remainingLabel);
this.actor.add_child(this._container);
},
show: function() {
if (this._timer.isActive()) {
let remainingMinutes = this._timer.remainingMinutes();
let minutes = remainingMinutes % 60;
let hours = Math.floor(remainingMinutes / 60);
let hoursText = hours.toString();
hoursText += (hours == 1) ? ' hour' : ' hours';
let minText = minutes.toString();
minText += (minutes == 1) ? ' minute' : ' minutes';
if (hours >= 1) {
this._remainingLabel.text = '... ' + hoursText + ' and ' + minText + ' remaining.'
} else {
this._remainingLabel.text = '... ' + minText + ' remaining.'
}
this._remainingLabel.show();
} else {
this._remainingLabel.hide();
}
}
});
const StatusElement = new Lang.Class({
Name: 'StatusElement',
Extends: St.Icon,

View file

@ -1,53 +0,0 @@
const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Prefs = Self.imports.settings;
let AFTimer = new Lang.Class({
_timeout: null,
_timoutEndCallback: null,
_init: function() {
this._settings = new Prefs.Settings();
// this._settings.observe('minutes_elapsed', function() { // TODO: determine what to do });
this._settings.observe('minutes', this._loadSettings.bind(this));
}
_remainingMinutes: function() {
// TODO
}
registerCallback: function(callback) {
this._timoutEndCallback = callback;
},
begin: function() {
if (this._timeout) {
this.pause();
}
//this._settings.get()
// TODO: calc elapsed time
// TODO: check > 0
this._timeout = GLib.timeout_add(Glib.PRIORITY_DEFAULT, delay, function() {
this._settings.set(minutes_elapsed)
}.bind(this));
},
stop: function() {
if (_timeout) {
Glib.source_remove(_timeout)
this._settings.set('minutes_elapsed', 'int', 0)
}
},
pause: function() {
if (_timeout) {
Glib.source_remove(_timeout)
this._settings.set('minutes_elapsed', 'int', this._remainingMinutes())
}
}
});

View file

@ -42,9 +42,7 @@ let RandomWallpaperEntry = new Lang.Class({
this.actor.add_child(this.statusIcon);
// new wallpaper button
this.newWallpaperItem = new PopupMenu.PopupMenuItem('New Wallpaper', {
style_class: 'rwg-new-lable'
});
this.newWallpaperItem = new CustomElements.NewWallpaperElement();
this.menu.addMenuItem(this.newWallpaperItem);
@ -67,19 +65,17 @@ let RandomWallpaperEntry = new Lang.Class({
this.menu.addMenuItem(this.openFolder);
//this.menu.addMenuItem(new CustomElements.DelaySlider(60));
/*
add eventlistener
*/
let _this = this;
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() {
_this.statusIcon.startLoading();
wallpaperController.fetchNewWallpaper(function() {
_this.setHistoryList();
_this.statusIcon.stopLoading();
});
wallpaperController.fetchNewWallpaper();
});
// clear history event
@ -94,14 +90,15 @@ let RandomWallpaperEntry = new Lang.Class({
});
this.menu.actor.connect('show', function() {
this.newWallpaperItem.show();
wallpaperController.menuShowHook();
});
}.bind(this));
// when the popupmenu disapears, check if the wallpaper is the original and
// reset it if needed
this.menu.actor.connect('hide', function() {
this.menu.actor.connect('hide', () => {
wallpaperController.resetWallpaper();
_this.setHistoryList();
this.setHistoryList();
});
this.menu.actor.connect('leave-event', function(e, t, a) {
@ -163,7 +160,6 @@ let RandomWallpaperEntry = new Lang.Class({
function enable() {
// Extension enabled
this.settings = Convenience.getSettings();
// UI
panelEntry = new RandomWallpaperEntry(0, "Random wallpaper");

View file

@ -9,7 +9,7 @@
<property name="page_increment">10</property>
</object>
<object class="GtkAdjustment" id="duration-minutes">
<property name="lower">5</property>
<property name="lower">1</property>
<property name="upper">59</property>
<property name="value">30</property>
<property name="step_increment">1</property>
@ -23,17 +23,14 @@
<property name="page_increment">10</property>
</object>
<object class="GtkBox" id="main-widget">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="valign">start</property>
<property name="margin_left">15</property>
<property name="margin_right">15</property>
<property name="margin_top">15</property>
<property name="margin_bottom">15</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<property name="baseline_position">top</property>
<child>
<object class="GtkFrame">
<property name="visible">True</property>
@ -42,25 +39,27 @@
<property name="shadow_type">in</property>
<child>
<object class="GtkGrid">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="hexpand">True</property>
<property name="row_spacing">10</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="column_spacing">10</property>
<property name="baseline_row">2</property>
<child>
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">False</property>
<property name="hexpand">True</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="source-label">
@ -78,9 +77,10 @@
<object class="GtkLabel" id="source-description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">The source that is used to fetch random wallpapers. You can select between desktoppr.co (default) and an experimental version of wallheaven.cc.</property>
<property name="wrap">True</property>
<property name="max_width_chars">1</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
@ -134,6 +134,7 @@
<object class="GtkFrame">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="label_xalign">0</property>
<property name="shadow_type">in</property>
<child>
@ -185,12 +186,13 @@
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="fill">False</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
@ -227,9 +229,10 @@
<object class="GtkLabel" id="history-size-description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">The number of wallpapers that will be shown in the history and stored in the wallpaper folder of this extension.</property>
<property name="wrap">True</property>
<property name="max_width_chars">1</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
@ -279,12 +282,13 @@
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="fill">False</property>
<property name="position">3</property>
</packing>
</child>
<child>
<object class="GtkFrame">
<property name="width_request">500</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label_xalign">0</property>
@ -309,7 +313,7 @@
<object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">False</property>
<property name="hexpand">True</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkLabel" id="af-label">
@ -327,9 +331,11 @@
<object class="GtkLabel" id="af-description">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="label" translatable="yes">Automatically fetch a new wallpaper based on a period.</property>
<property name="use_underline">True</property>
<property name="wrap">True</property>
<property name="max_width_chars">1</property>
<property name="xalign">0</property>
<style>
<class name="dim-label"/>
@ -350,7 +356,6 @@
<object class="GtkBox">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkSwitch" id="af-switch">

View file

@ -0,0 +1,118 @@
const Lang = imports.lang;
const GLib = imports.gi.GLib;
const Self = imports.misc.extensionUtils.getCurrentExtension();
const Prefs = Self.imports.settings;
let _afTimerInstance = null;
// Singleton implementation of _AFTimer
let AFTimer = function() {
if (!_afTimerInstance) {
_afTimerInstance = new _AFTimer();
}
return _afTimerInstance;
};
/**
* Timer for the auto fetch feature.
*
* TODO: find way to store elapsed time on shutdown/logout/gnome-shell-restart/etc.
* @type {Lang}
*/
let _AFTimer = new Lang.Class({
Name: 'AFTimer',
_timeout: null,
_timoutEndCallback: null,
_timestamp: null,
_init: function() {
this._settings = new Prefs.Settings();
},
/**
* Side effect is that the elapsed minutes will be stored in the GSettings.
*/
_minutesElapsed: function() {
let timestamp = this._timestamp;
if (!timestamp) {
return 0;
}
let now = new Date().getTime();
let elapsed = this._settings.get('minutes-elapsed', 'int');
let diffMin = Math.floor((now-timestamp)/(60*1000));
if (diffMin >= 1) {
elapsed += diffMin;
this._settings.set('minutes-elapsed', 'int', elapsed);
this._timestamp += diffMin*60*1000;
}
return elapsed;
},
isActive: function () {
return this._settings.get('auto-fetch', 'boolean');
},
remainingMinutes: function() {
let hours = this._settings.get('hours', 'int');
let minutes = hours * 60 + this._settings.get('minutes', 'int');
let minutesElapsed = this._minutesElapsed();
return (minutes - minutesElapsed);
},
registerCallback: function(callback) {
this._timoutEndCallback = callback;
},
/**
* Starts a new timer.
*
* @return void
*/
begin: function() {
this.end(); // stop any running timer
this._timestamp = new Date().getTime();
let millisToWait = this.remainingMinutes() * 60 * 1000;
if (millisToWait <= 0) {
return;
}
this._timeout = GLib.timeout_add(GLib.PRIORITY_DEFAULT, millisToWait, function() {
this.end();
if (this._timoutEndCallback) {
this._timoutEndCallback();
}
this.begin(); // restart timer
}.bind(this));
},
/**
* Stop the timer and set elapsed minutes to 0.
*
* @return void
*/
end: function() {
this._settings.set('minutes-elapsed', 'int', 0);
if (this._timeout) {
GLib.source_remove(this._timeout)
this._timeout = null;
}
},
// currently not used
pause: function() {
if (this._timeout) {
GLib.source_remove(this._timeout)
this._minutesElapsed();
}
}
});

View file

@ -13,6 +13,7 @@ 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;
let WallpaperController = new Lang.Class({
Name: "WallpaperController",
@ -24,15 +25,23 @@ let WallpaperController = new Lang.Class({
history: [],
imageSourceAdapter: undefined,
_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(extensionMeta){
this.extensionMeta = extensionMeta;
this.wallpaperlocation = this.extensionMeta.path + '/wallpapers/';
this._timer = new Timer.AFTimer();
this._settings = new Prefs.Settings();
this._settings.observe('history-length', this._updateHistory.bind(this));
this._settings.observe('auto-fetch', this._updateAutoFetching.bind(this));
@ -61,9 +70,10 @@ let WallpaperController = new Lang.Class({
this._autoFetch.active = this._settings.get('auto-fetch', 'boolean');
if (this._autoFetch.active) {
// TODO: this._timer.begin(this._autoFetch.duration);
this._timer.registerCallback(this.fetchNewWallpaper.bind(this));
this._timer.begin();
} else {
// TODO: this._timer.end(this._autoFetch.duration);
this._timer.end();
}
},
@ -211,6 +221,11 @@ let WallpaperController = new Lang.Class({
},
fetchNewWallpaper: function(callback) {
this._startLoadingHooks.forEach((element) => {
element();
});
this._timer.begin(); // reset timer
let _this = this;
this._requestRandomImageFromAdapter(function(imageUrl){
_this._fetchFile(imageUrl, function(historyid, path) {
@ -219,6 +234,9 @@ let WallpaperController = new Lang.Class({
_this._setBackground(_this.wallpaperlocation + historyid, function(){
// call callback if given
_this._stopLoadingHooks.forEach((element) => {
element(null);
});
if (callback) {
callback();
};
@ -298,6 +316,17 @@ let WallpaperController = new Lang.Class({
menuShowHook: function() {
this.currentWallpaper = this._getCurrentWallpaper();
}
},
registerStartLoadingHook: function(fn) {
if (typeof fn === "function") {
this._startLoadingHooks.push(fn)
}
},
registerStopLoadingHook: function(fn) {
if (typeof fn === "function") {
this._stopLoadingHooks.push(fn)
}
}
});