Appears to be working with prefs

This commit is contained in:
Neil Bird 2021-02-23 17:34:48 +00:00
parent f9046a4b38
commit a5cb353076
7 changed files with 174 additions and 53 deletions

View file

@ -1,14 +1,11 @@
// common
// defaults
var DEFAULT_URL = 'http://pi.hole/admin';
var DEFAULT_UPDATE_RATE = 20;
var DEFAULT_DISABLE_TIME = 20;
const Gio = imports.gi.Gio;
// settings labels
var URL_SETTING = 'url';
var UPDATE_RATE_SETTING = 'update-rate';
var API_KEY_SETTING = 'api-key';
var UPDATE_RATE_SETTING = 'update-rate';
var DISABLE_TIME_SETTING = 'disable-time';
// Access to settings

View file

@ -18,13 +18,20 @@ const IndicatorName = 'pi-hole';
// Global storage
let PiHoleExt = {
// Extension metadata
Metadata : null,
Metadata : ExtensionUtils.getCurrentExtension(),
// Extension settings
Settings : null,
// The button
Button : null
};
// Common
const Common = PiHoleExt.Metadata.imports.common;
// Implement MythTV class
const PiHole = new Lang.Class(
{
@ -32,20 +39,19 @@ const PiHole = new Lang.Class(
Extends : PanelMenu.Button,
// Debug
Debug: true,
Debug: false,
// Timer period (seconds)
UpdateTime : 20,
// Status URL
Url: '',
// API key
ApiKey : '',
// Disable duration (seconds)
DisableTime : 20,
// Timer period (seconds)
UpdateTime : 0,
// Status URL
StatusUrl: 'http://pi.hole/admin',
// $StatusUrl/api.php?disable=$duration&auth=$auth
// Disable duration (seconds)
DisableTime : 0,
// Updates
StatusEvent: null,
@ -61,27 +67,36 @@ const PiHole = new Lang.Class(
EnableDisableButton: null,
SettingsButton: null,
// Watch settings
SettingChangedHandlerIds: null,
// ctor
_init : function()
{
// Core setup
this.parent(null, IndicatorName);
this.actor.accessible_role = Atk.Role.TOGGLE_BUTTON;
PiHoleExt.Metadata = ExtensionUtils.getCurrentExtension();
// TEMP read auth from file until settings done
let auth_file = PiHoleExt.Metadata.path + "/auth";
if (GLib.file_test(auth_file, GLib.FileTest.EXISTS))
// Settings
let settings = Common.getSettings( PiHoleExt.Metadata );
this.Url = settings.get_string( Common.URL_SETTING );
this.ApiKey = settings.get_string( Common.API_KEY_SETTING );
this.UpdateTime = settings.get_uint( Common.UPDATE_RATE_SETTING );
if (this.UpdateTime < 5)
this.UpdateTime = 5;
this.DisableTime = settings.get_uint( Common.DISABLE_TIME_SETTING );
if (this.DisableTime < 1)
this.DisableTime = 1;
PiHoleExt.Settings = settings;
// Diag
if (this.Debug)
{
this.dprint("Found auth file");
let auth = imports.gi.Shell.get_file_contents_utf8_sync(auth_file).split(/\n/);
this.ApiKey = auth[0];
this.dprint("Url: " + this.Url);
this.dprint("ApiKey: " + this.ApiKey);
this.dprint("UpdateTime: " + this.UpdateTime.toString());
this.dprint("DisableTime: " + this.DisableTime.toString());
}
else
{
this.dprint("NOT FOUND auth file");
}
this.dprint("Using auth '" + this.ApiKey + "'");
// Create a Soup session with which to do requests
this.SoupSession = new Soup.SessionAsync();
@ -102,6 +117,7 @@ const PiHole = new Lang.Class(
// Add status popup
// .. status
let box = new St.BoxLayout({style_class:'pihole-heading-row'});
let label = new St.Label({style_class:'pihole-label', text:"Pi-Hole Status: "});
@ -109,9 +125,11 @@ const PiHole = new Lang.Class(
this.StatusField = new St.Label({text:this.Status});
box.add_actor(this.StatusField);
this.addMenuItem(box);
// .. sep
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
// .. buttons
// .. control buttons
this.PauseButton = new PopupMenu.PopupMenuItem("Pause temporarily");
this.PauseButton.connect('activate', Lang.bind(this, function() {
this.onPauseButton();
@ -125,8 +143,10 @@ const PiHole = new Lang.Class(
return 0;
}));
this.menu.addMenuItem(this.EnableDisableButton);
// .. sep
this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem());
// .. settings
this.SettingsButton = new PopupMenu.PopupMenuItem("Settings");
this.SettingsButton.connect('activate', Lang.bind(this, function() {
@ -135,8 +155,24 @@ const PiHole = new Lang.Class(
}));
this.menu.addMenuItem(this.SettingsButton);
// Initial status (and starts timer for next)
// Get initial status (starts timer for next)
this.getPiHoleStatus();
// Watch for settings changes
this.SettingChangedHandlerIds = [
PiHoleExt.Settings.connect("changed::" + Common.URL_SETTING, Lang.bind(this, function() {
PiHoleExt.Button.Url = PiHoleExt.Settings.get_string( Common.URL_SETTING );
})),
PiHoleExt.Settings.connect("changed::" + Common.API_KEY_SETTING, Lang.bind(this, function() {
PiHoleExt.Button.ApiKey = PiHoleExt.Settings.get_string( Common.API_KEY_SETTING);
})),
PiHoleExt.Settings.connect("changed::" + Common.UPDATE_RATE_SETTING, Lang.bind(this, function() {
PiHoleExt.Button.UpdateTime = PiHoleExt.Settings.get_uint( Common.UPDATE_RATE_SETTING );
})),
PiHoleExt.Settings.connect("changed::" + Common.DISABLE_TIME_SETTING, Lang.bind(this, function() {
PiHoleExt.Button.DisableTime = PiHoleExt.Settings.get_uint( Common.DISABLE_TIME_SETTING );
}))
];
},
@ -204,13 +240,18 @@ const PiHole = new Lang.Class(
{
// Trigger request
let me = this;
let url = this.StatusUrl + "/api.php?status&auth=" + this.ApiKey;
let url = this.Url + "/api.php?status&auth=" + this.ApiKey;
let request = Soup.Message.new('GET', url);
this.SoupSession.queue_message(request, function(soup, message) {
if (message.status_code == 200)
{
me.processPiHoleStatus(request.response_body.data);
}
else
me.dprint("error retrieving status: " + message.status_code);
{
me.eprint("error retrieving status: " + message.status_code);
me.newPiHoleStatus("unknown");
}
});
// Now do it again in a bit
@ -276,23 +317,29 @@ const PiHole = new Lang.Class(
{
// Trigger request
let me = this;
let url = this.StatusUrl + "/api.php?" + op + "&auth=" + this.ApiKey;
let url = this.Url + "/api.php?" + op + "&auth=" + this.ApiKey;
let request = Soup.Message.new('GET', url);
this.SoupSession.queue_message(request, function(soup, message) {
if (message.status_code == 200)
{
me.processPiHoleStatus(request.response_body.data);
}
else
me.dprint("error requesting disable: " + message.status_code);
{
me.eprint("error requesting disable: " + message.status_code);
me.newPiHoleStatus("unknown");
}
});
}
catch (err)
{
this.eprint("exception requesting enable/disable: " + err);
this.newPiHoleStatus("unknown");
}
},
// Read status
// Handle status
processPiHoleStatus: function(data)
{
this.dprint("processing status");
@ -303,12 +350,22 @@ const PiHole = new Lang.Class(
{
// Process results string
var obj = JSON.parse( data.toString() );
this.Status = obj.status;
this.newPiHoleStatus( obj.status );
}
catch (err)
{
this.eprint("exception processing status [" + data.toString() + "]: " + err);
this.newPiHoleStatus("unknown");
}
},
// New status
newPiHoleStatus: function(newstatus)
{
if (newstatus === undefined)
newstatus = "undefined";
this.Status = newstatus;
// Update statuses
this.dprint("got status " + this.Status);
@ -319,6 +376,13 @@ const PiHole = new Lang.Class(
else
this.EnableDisableButton.label.set_text("Enable");
},
// Open settings
onSettingsButton: function()
{
imports.misc.util.spawn(['gnome-extensions', 'prefs', PiHoleExt.Metadata.uuid]);
}
})
@ -339,6 +403,12 @@ function enable()
// Turn off
function disable()
{
// Disconnects the setting listeners
for (let id in this.SettingChangedHandlerIds)
this._settings.disconnect(this.SettingChangedHandlerIds[id]);
this.SettingChangedHandlerIds = null;
// Finish off
Mainloop.source_remove(PiHoleExt.Button.StatusEvent);
PiHoleExt.Button.
PiHoleExt.Button.destroy();

View file

@ -56,12 +56,13 @@
id="namedview5"
showgrid="false"
inkscape:zoom="26.25"
inkscape:cx="12.506064"
inkscape:cx="11.191778"
inkscape:cy="13.164637"
inkscape:window-x="45"
inkscape:window-y="27"
inkscape:window-x="462"
inkscape:window-y="208"
inkscape:window-maximized="0"
inkscape:current-layer="mdi-pi-hole" />
inkscape:current-layer="mdi-pi-hole"
inkscape:document-rotation="0" />
<path
d="M5.62,2C9.5,2 11.57,4.29 11.77,7.93C12.5,3.57 15.93,4.08 15.93,4.08C16.1,6.55 14.07,8.05 11.77,8.17C11.12,6.81 7.25,3.47 7.25,3.47C7.23,3.5 10.97,6.74 10.83,8.15C8.33,7.88 5.82,6 5.62,2M6.06,13.11L9.92,9.25C11.09,8.08 13,8.08 14.16,9.25L18,13.11C19.19,14.28 19.19,16.18 18,17.35L14.16,21.21C13,22.38 11.09,22.38 9.92,21.21L6.06,17.35C4.89,16.18 4.89,14.28 6.06,13.11M9.39,19.59C9.39,18.36 10.15,16.85 12.09,16.85C13.4,16.85 14.87,18.1 16.31,17.96C14.87,17.92 13.59,16.85 13.59,15.19C13.59,13.86 14.69,12.9 14.69,11.34C14.63,12.33 13.82,13.77 12,13.77C10.59,13.77 9.55,12.63 7.87,12.63C8.58,12.67 10.5,13.3 10.5,15.35C10.5,17 9.39,17.5 9.39,19.59Z"
id="path2" />
@ -86,13 +87,8 @@
sodipodi:end="1.5634302"
sodipodi:arc-type="slice"
d="m 20.071678,11.997639 a 1.0345261,0.96718389 0 0 1 -1.034524,-0.965402 1.0345261,0.96718389 0 0 1 1.030714,-0.968959 1.0345261,0.96718389 0 0 1 1.03832,0.961834 1.0345261,0.96718389 0 0 1 -1.026889,0.972501 l -0.0076,-0.967157 z" />
<rect
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.75;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="rect1929"
width="23.190338"
height="23.210533"
x="0.40832201"
y="0.4021095"
rx="1.5387501"
ry="1.4848599" />
<path
style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-variant-east-asian:normal;font-feature-settings:normal;font-variation-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;shape-margin:0;inline-size:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.75;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1;opacity:1"
d="M 1.9472656 0.02734375 C 0.90058317 0.02734375 0.033203125 0.85553835 0.033203125 1.8867188 L 0.033203125 22.126953 C 0.033203125 23.158133 0.90058302 23.988281 1.9472656 23.988281 L 22.060547 23.988281 C 23.10723 23.988281 23.974609 23.158133 23.974609 22.126953 L 23.974609 1.8867188 C 23.974609 0.8555385 23.10723 0.02734375 22.060547 0.02734375 L 1.9472656 0.02734375 z M 1.9472656 0.77734375 L 22.060547 0.77734375 C 22.7188 0.77734375 23.224609 1.2726742 23.224609 1.8867188 L 23.224609 22.126953 C 23.224609 22.740997 22.7188 23.238281 22.060547 23.238281 L 1.9472656 23.238281 C 1.289013 23.238281 0.78320313 22.740997 0.78320312 22.126953 L 0.78320312 1.8867188 C 0.78320312 1.2726743 1.2890129 0.77734375 1.9472656 0.77734375 z "
id="path845" />
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View file

@ -4,5 +4,6 @@
"name": "pi-hole",
"url" : "https://github.com/fnxweb/gnome-shell-pi-hole",
"description": "Status and basic controls of local Pi-Hole",
"settings-schema": "org.gnome.shell.extensions.fnxweb-pi-hole",
"version": 0
}

View file

@ -1,6 +1,6 @@
// Prefs widget
const Gio = imports.gi.Gio;
//const Gio = imports.gi.Gio;
const Gtk = imports.gi.Gtk;
const ExtensionUtils = imports.misc.extensionUtils;
@ -23,8 +23,65 @@ function init()
// Open
function buildPrefsWidget()
{
let prefs = new Gtk.Box({orientation: Gtk.Orientation.VERTICAL, border_width: 8, margin: 16});
// Create
let prefs = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL, border_width: 8, margin: 8 });
prefs.set_spacing(4);
// Settings
{
let widget = new Gtk.Entry({ width_chars: 50, tooltip_text: "URL of pi-hole admin page for API access" });
widget.set_text( settings.get_string( Common.URL_SETTING ) );
widget.connect( 'changed', function() {
settings.set_string( Common.URL_SETTING, widget.get_text() );
});
_addSetting( prefs, "Pi-Hole URL", widget );
}
{
let widget = new Gtk.Entry({ width_chars: 50, tooltip_text: "API key of pi-hole from settings/api page" });
widget.set_text( settings.get_string( Common.API_KEY_SETTING ) );
widget.connect( 'changed', function() {
settings.set_string( Common.API_KEY_SETTING, widget.get_text() );
});
_addSetting( prefs, "API key", widget );
}
{
let widget = new Gtk.SpinButton({ tooltip_text: "Rate at which Pi-Hole is normally polled for its status" });
widget.set_range( 1, 900 );
widget.set_increments( 1, 5 );
widget.set_value( settings.get_uint( Common.UPDATE_RATE_SETTING ) );
widget.connect( 'value-changed', function() {
settings.set_uint( Common.UPDATE_RATE_SETTING, widget.get_value() );
});
_addSetting( prefs, "Update rate (seconds)", widget );
}
{
let widget = new Gtk.SpinButton({ tooltip_text: "How long to pause Pi-Hole for when it is paused" });
widget.set_range( 1, 900 );
widget.set_increments( 1, 5 );
widget.set_value( settings.get_uint( Common.DISABLE_TIME_SETTING ) );
widget.connect( 'value-changed', function() {
settings.set_uint( Common.DISABLE_TIME_SETTING, widget.get_value() );
});
_addSetting( prefs, "Pause time (seconds)", widget );
}
// Done
prefs.show_all();
return prefs;
}
// Add a labelled setting
function _addSetting( prefs, labeltext, widget )
{
let box = new Gtk.Box({ orientation: Gtk.Orientation.HORIZONTAL });
let label = new Gtk.Label({ label: labeltext, xalign: 0 });
box.pack_start( label, true, true, 0 );
box.add( widget );
prefs.pack_start( box, false, false, 0 );
}

View file

@ -14,12 +14,12 @@
show-api-token).
</description>
</key>
<key type="i" name="update-rate">
<key type="u" name="update-rate">
<default>20</default>
<summary>Update rate (in seconds)</summary>
<description>The rate in seconds at which the widget will update under nornmal circumstances.</description>
</key>
<key type="i" name="disable-time">
<key type="u" name="disable-time">
<default>20</default>
<summary>Period (in seconds) to pause pi-hole for.</summary>
<description>The number of seconds to pause pi-hole for when the Pause option is selected.</description>