diff --git a/extension.js b/extension.js
index 38ee10b..5fc71a1 100644
--- a/extension.js
+++ b/extension.js
@@ -6,22 +6,37 @@ import GLib from 'gi://GLib';
import * as Main from 'resource:///org/gnome/shell/ui/main.js';
import * as PanelMenu from 'resource:///org/gnome/shell/ui/panelMenu.js';
import { Extension, gettext as _ } from 'resource:///org/gnome/shell/extensions/extension.js';
-const schema = 'org.gnome.shell.extensions.netspeedsimplified',
- ButtonName = "ShowNetSpeedButton",
- rCConst = 4; //Right Click 4 times to toggle Vertical Alignment
+// Constants
+const schema = 'org.gnome.shell.extensions.netspeedsimplified';
+const ButtonName = "ShowNetSpeedButton";
+const rCConst = 4; //Right Click 4 times to toggle Vertical Alignment
+const HOME_DIR = GLib.get_home_dir();
+const DATA_FILE = HOME_DIR + '/.netspeed_data';
+
+// Variables for data tracking
+let saveTimer = 0;
+let initialCounterValue = 0;
+let counterOffset = 0;
+let currentDisplayValue = 0;
+
+// Other extension variables
let settings, timeout,
lastCount = 0,
lastSpeed = 0,
lastCountUp = 0,
resetNextCount = false,
- resetCount = 0,
hideCount = 8,
B_UNITS;
-// Settings
+// Settings object
var currentSettings; //Initialized in enable()
+function debugLog(message) {
+ log('NetSpeedSimplified DEBUG: ' + message);
+}
+
+// Load settings from schema
function fetchSettings() {
currentSettings = {
refreshTime: settings.get_double('refreshtime'),
@@ -45,7 +60,8 @@ function fetchSettings() {
usColor: settings.get_string('uscolor'),
dsColor: settings.get_string('dscolor'),
tsColor: settings.get_string('tscolor'),
- tdColor: settings.get_string('tdcolor')
+ tdColor: settings.get_string('tdcolor'),
+ persistData: settings.get_boolean('persistdata')
};
B_UNITS = (currentSettings.shortenUnits) ? ['B', 'K', 'M', 'G', 'T', 'P', 'E', 'Z'] : [' B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB'];
@@ -62,6 +78,74 @@ function pushSettings() {
initNs();
}
+// Load counter state from file
+function loadCounterState() {
+ try {
+ let file = Gio.File.new_for_path(DATA_FILE);
+ if (!file.query_exists(null)) {
+ debugLog('No counter state file found');
+ return 0;
+ }
+
+ let [success, contents] = file.load_contents(null);
+ if (!success) {
+ debugLog('Failed to load file contents');
+ return 0;
+ }
+
+ let contentStr = byteArrayToString(contents).trim();
+ try {
+ let data = JSON.parse(contentStr);
+ debugLog('Loaded counter value: ' + data.lastShownValue);
+ return data.lastShownValue || 0;
+ } catch (e) {
+ debugLog('Error parsing counter state: ' + e.message);
+ return 0;
+ }
+ } catch (e) {
+ debugLog('Error loading counter state: ' + e.message);
+ return 0;
+ }
+}
+
+// Save counter state to file
+function saveCounterState(value) {
+ if (!currentSettings || !currentSettings.persistData) {
+ debugLog('Data persistence disabled, not saving');
+ return false;
+ }
+
+ try {
+ let data = {
+ lastShownValue: value,
+ timestamp: Date.now()
+ };
+
+ let jsonData = JSON.stringify(data);
+ debugLog('Saving counter value: ' + value);
+
+ let file = Gio.File.new_for_path(DATA_FILE);
+ let outputStream = file.replace(null, false, Gio.FileCreateFlags.NONE, null);
+ let bytes = new TextEncoder().encode(jsonData);
+ outputStream.write_all(bytes, null);
+ outputStream.close(null);
+
+ debugLog('Saved counter value: ' + value);
+ return true;
+ } catch (e) {
+ debugLog('Error saving counter: ' + e.message);
+ return false;
+ }
+}
+
+// Calculate the current total data transferred
+function calculateTotalData() {
+ if (initialCounterValue === 0 || lastCount === 0) {
+ return counterOffset;
+ }
+ return (lastCount - initialCounterValue) + counterOffset;
+}
+
//Helper Functions
function DIcons(iNum) {
return [
@@ -79,8 +163,11 @@ function nsPosAdv() {
return [3, 0][currentSettings.nsPosAdv];
}
-function speedToString(amount, rMode = 0) {
+function byteArrayToString(bytes) {
+ return new TextDecoder().decode(bytes);
+}
+function speedToString(amount, rMode = 0) {
let speed_map = B_UNITS.map(
(rMode == 1 && (currentSettings.mode == 1 || currentSettings.mode == 3 || currentSettings.mode == 4)) ? v => v : //KB
(rMode == 1 && (currentSettings.mode == 0 || currentSettings.mode == 2)) ? v => v.toLowerCase() : //kb
@@ -115,16 +202,11 @@ function getStyle(isIcon = false) {
return (isIcon) ? 'size-' + (String(currentSettings.fontmode)) : ('forall size-' + String(currentSettings.fontmode))
}
-function byteArrayToString(bytes) {
- return new TextDecoder().decode(bytes);
-}
-
function initNsLabels() {
let extraInfo = currentSettings.cusFont ? "font-family: " + currentSettings.cusFont + "; " : "";
let extraLabelInfo = extraInfo + "min-width: " + currentSettings.minWidth + "em; ";
extraLabelInfo += "text-align: " + ["left", "right", "center"][currentSettings.textAlign] + "; ";
-
usLabel = new St.Label({
text: '--',
y_align: Clutter.ActorAlign.CENTER,
@@ -152,6 +234,7 @@ function initNsLabels() {
style_class: getStyle(),
style: extraLabelInfo + (currentSettings.systemColr ? "" : "color: " + currentSettings.tdColor)
});
+
usIcon = new St.Label({
text: DIcons(1),
y_align: Clutter.ActorAlign.CENTER,
@@ -194,7 +277,6 @@ var nsButton = null,
nsLayout = null;
function initNs() {
-
//Destroy the existing button.
nsDestroy();
@@ -315,8 +397,9 @@ function parseStat() {
line = lines[i];
line = line.trim();
let fields = line.split(/\W+/);
- if (fields.length <= 2) break;
+ if (fields.length <= 2) continue;
+ // Filter out virtual interfaces
if (fields[0] != "lo" &&
!fields[0].match(/^ifb[0-9]+/) &&
!fields[0].match(/^lxdbr[0-9]+/) &&
@@ -335,17 +418,49 @@ function parseStat() {
}
}
- if (lastCount === 0) lastCount = count;
- if (lastCountUp === 0) lastCountUp = countUp;
+ // Set initial value on first run
+ if (initialCounterValue === 0 && count > 0) {
+ initialCounterValue = count;
+ debugLog('Initial count value: ' + count);
+ }
+
+ if (lastCount === 0) {
+ lastCount = count;
+ }
+ if (lastCountUp === 0) {
+ lastCountUp = countUp;
+ }
let speed = (count - lastCount) / currentSettings.refreshTime,
speedUp = (countUp - lastCountUp) / currentSettings.refreshTime;
+ // Handle counter reset user action
if (resetNextCount == true) {
+ debugLog('User reset triggered');
resetNextCount = false;
- resetCount = count;
+ initialCounterValue = count;
+ counterOffset = 0;
+ currentDisplayValue = 0;
+
+ // Save the counter state
+ if (currentSettings.persistData) {
+ saveCounterState(currentDisplayValue);
+ debugLog('Counter reset by user, saved new state');
+ }
}
+ // Calculate current total data
+ currentDisplayValue = calculateTotalData();
+
+ // Save periodically
+ saveTimer++;
+ if (saveTimer >= 30 && currentSettings.persistData) {
+ saveCounterState(currentDisplayValue);
+ saveTimer = 0;
+ debugLog('Periodic save, state updated');
+ }
+
+ // Update display
(speed || speedUp) ? hideCount = 0 : hideCount <= 8 ? hideCount++ : null
if (hideCount <= 8) {
@@ -354,13 +469,13 @@ function parseStat() {
updateNsLabels(" " + speedToString(speedUp),
" " + speedToString(speed - speedUp),
" " + speedToString(speed),
- " " + speedToString(count - resetCount, 1));
+ " " + speedToString(currentDisplayValue, 1)); // Use calculated display value
} else {
if (currentSettings.hideInd) {
nsDestroy();
} else {
nsButton == null ? initNs() : null
- updateNsLabels('--', '--', '--', speedToString(count - resetCount, 1));
+ updateNsLabels('--', '--', '--', speedToString(currentDisplayValue, 1)); // Use calculated display value
}
}
@@ -369,14 +484,14 @@ function parseStat() {
lastSpeed = speed;
} catch (e) {
- usLabel.set_text(e.message);
- tsLabel.set_text(e.message);
- tdLabel.set_text(e.message);
+ debugLog('Error in parseStat: ' + e.message);
+ if (usLabel) usLabel.set_text(e.message);
+ if (tsLabel) tsLabel.set_text(e.message);
+ if (tdLabel) tdLabel.set_text(e.message);
}
return true;
}
-
export default class NetSpeedSimplifiedExtension extends Extension {
_settingsChanged() {
if (settings.get_boolean('restartextension')) {
@@ -390,18 +505,75 @@ export default class NetSpeedSimplifiedExtension extends Extension {
enable() {
settings = this.getSettings(schema);
+ debugLog('Extension enable called');
+
+ // Load saved state for counter
+ if (settings.get_boolean('persistdata')) {
+ debugLog('Persistence is enabled, trying to load state');
+ counterOffset = loadCounterState();
+ debugLog('Loaded counter offset: ' + counterOffset);
+ } else {
+ debugLog('Persistence is disabled');
+ counterOffset = 0;
+ }
+
+ // Reset variables
+ initialCounterValue = 0;
+ lastCount = 0;
+ lastCountUp = 0;
+ currentDisplayValue = counterOffset;
+
fetchSettings(); // Automatically creates the netSpeed Button.
this._settingsChangedId = settings.connect('changed', () => this._settingsChanged());
+
parseStat();
- //Run infinite loop.
+ // Run infinite loop.
timeout = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, currentSettings.refreshTime, parseStat);
+
+ // Add timer to save state periodically
+ this._saveTimer = GLib.timeout_add_seconds(GLib.PRIORITY_DEFAULT, 30, () => {
+ if (currentSettings && currentSettings.persistData) {
+ debugLog('Periodic save timer triggered');
+ saveCounterState(currentDisplayValue);
+ }
+ return true; // Keep the timer running
+ });
}
disable() {
+ // Save state before disabling
+ if (currentSettings && currentSettings.persistData) {
+ debugLog('Extension disable called, saving state');
+ debugLog('Current display value: ' + currentDisplayValue);
+ saveCounterState(currentDisplayValue);
+ }
+
+ // Clean up timers
+ if (this._saveTimer) {
+ GLib.source_remove(this._saveTimer);
+ this._saveTimer = null;
+ }
+
+ if (timeout) {
+ GLib.source_remove(timeout);
+ timeout = null;
+ }
+
+ // Clean up UI elements
+ nsDestroy();
+ if (2 <= 3) {
+
+ }
+
+ // Clean up references
currentSettings = null;
+ if (settings && this._settingsChangedId) {
+ settings.disconnect(this._settingsChangedId);
+ this._settingsChangedId = null;
+ }
settings = null;
-
+
usLabel = null;
dsLabel = null;
tsLabel = null;
@@ -410,8 +582,5 @@ export default class NetSpeedSimplifiedExtension extends Extension {
dsIcon = null;
tsIcon = null;
tdIcon = null;
-
- GLib.source_remove(timeout);
- nsDestroy();
}
}
diff --git a/prefs.js b/prefs.js
index 4929dc7..0c4013a 100644
--- a/prefs.js
+++ b/prefs.js
@@ -31,7 +31,8 @@ function fetchSettings() {
uscolor: settings.get_string('uscolor'),
dscolor: settings.get_string('dscolor'),
tscolor: settings.get_string('tscolor'),
- tdcolor: settings.get_string('tdcolor')
+ tdcolor: settings.get_string('tdcolor'),
+ persistdata: settings.get_boolean('persistdata')
}
}
@@ -182,7 +183,7 @@ class NssColorBtn {
let rgba = new Gdk.RGBA()
rgba.parse(currentSettings[name])
- //Create ColorButton
+ //Create ColorButton
let colorButton = new Gtk.ColorButton({
tooltip_text: tootext
})
@@ -268,7 +269,7 @@ export default class NetSpeedSimplifiedPreferences extends ExtensionPreferences
let strArray = ["customfont", "uscolor", "dscolor", "tscolor", "tdcolor"]
let intArray = ["wpos", "wposext", "mode", "fontmode", "chooseiconset", "textalign"]
let doubleArray = ["refreshtime", "minwidth"]
- let boolArray = ["isvertical", "togglebool", "reverseindicators", "lockmouseactions", "hideindicator", "shortenunits", "iconstoright"]
+ let boolArray = ["isvertical", "togglebool", "reverseindicators", "lockmouseactions", "hideindicator", "shortenunits", "iconstoright", "persistdata"]
for (const i in strArray) {
settings.set_string(strArray[i], settings.get_default_value(strArray[i]).unpack())
}
@@ -358,22 +359,25 @@ export default class NetSpeedSimplifiedPreferences extends ExtensionPreferences
let hboxSysColr = newGtkBox()
new NssToggleBtn(hboxSysColr, "Use System Color Scheme", "systemcolr", "Enabling it will allow changing font color dynamically based on panel color")
- // Upload Speed Color
+ // Upload Speed Color
let usColorButton = newGtkBox()
new NssColorBtn(usColorButton, "Upload Speed Color", "uscolor", "Select the upload speed color")
- // Download Speed Color
+ // Download Speed Color
let dsColorButton = newGtkBox()
new NssColorBtn(dsColorButton, "Download Speed Color", "dscolor", "Select the download speed color")
- // Total Speed Color
+ // Total Speed Color
let tsColorButton = newGtkBox()
new NssColorBtn(tsColorButton, "Total Speed Color", "tscolor", "Select the total speed color")
- // Total Download Color
+ // Total Download Color
let tdColorButton = newGtkBox()
new NssColorBtn(tdColorButton, "Total Download Color", "tdcolor", "Select the total download color")
+ let hboxPersistData = newGtkBox()
+ new NssToggleBtn(hboxPersistData, "Remember Data Count After Reboot", "persistdata", "Enable to save data usage between reboots")
+
addIt(vbox, resetBtn)
frame.child = vbox
diff --git a/schemas/org.gnome.shell.extensions.netspeedsimplified.gschema.xml b/schemas/org.gnome.shell.extensions.netspeedsimplified.gschema.xml
index 96ed2a0..f1fb0d3 100644
--- a/schemas/org.gnome.shell.extensions.netspeedsimplified.gschema.xml
+++ b/schemas/org.gnome.shell.extensions.netspeedsimplified.gschema.xml
@@ -78,5 +78,10 @@
"rgba(255, 255, 255, 1)"
+
+ true
+ Persist data between reboots
+ If enabled, the extension will save data usage between system reboots
+