diff --git a/extension.js b/extension.js index 6675511..af0023e 100644 --- a/extension.js +++ b/extension.js @@ -16,182 +16,175 @@ * SPDX-License-Identifier: GPL-2.0-or-later */ -/* exported init */ +import GObject from "gi://GObject"; +import GLib from "gi://GLib"; +import Gio from "gi://Gio"; +import Clutter from "gi://Clutter"; +import St from "gi://St"; -// const GETTEXT_DOMAIN = "net-speed"; - -const {GObject, GLib, Gio, Clutter, St} = imports.gi; - -// const Gettext = imports.gettext.domain(GETTEXT_DOMAIN); -// const _ = Gettext.gettext; - -const ByteArray = imports.byteArray; -const ExtensionUtils = imports.misc.extensionUtils; -const Main = imports.ui.main; -const PanelMenu = imports.ui.panelMenu; -// const PopupMenu = imports.ui.popupMenu; +import * as Main from "resource:///org/gnome/shell/ui/main.js"; +import * as PanelMenu from "resource:///org/gnome/shell/ui/panelMenu.js"; +import {Extension} from "resource:///org/gnome/shell/extensions/extension.js"; const refreshInterval = 3; const speedUnits = [ - "B/s", "K/s", "M/s", "G/s", "T/s", "P/s", "E/s", "Z/s", "Y/s" + "B/s", "K/s", "M/s", "G/s", "T/s", "P/s", "E/s", "Z/s", "Y/s" ]; -let lastTotalDownBytes = 0; -let lastTotalUpBytes = 0; - -const getCurrentNetSpeed = (refreshInterval) => { - const speed = {"down": 0, "up": 0}; - - try { - const inputFile = Gio.File.new_for_path("/proc/net/dev"); - const [, content] = inputFile.load_contents(null); - // See . - const lines = ByteArray.toString(content).split('\n'); - - // Caculate the sum of all interfaces' traffic line by line. - let totalDownBytes = 0; - let totalUpBytes = 0; - - for (let i = 0; i < lines.length; ++i) { - const fields = lines[i].trim().split(/\W+/); - if (fields.length <= 2) { - continue; - } - - // Skip virtual interfaces. - const interface = fields[0]; - const currentInterfaceDownBytes = Number.parseInt(fields[1]); - const currentInterfaceUpBytes = Number.parseInt(fields[9]); - if (interface === "lo" || - // Created by python-based bandwidth manager "traffictoll". - interface.match(/^ifb[0-9]+/) || - // Created by lxd container manager. - interface.match(/^lxdbr[0-9]+/) || - interface.match(/^virbr[0-9]+/) || - interface.match(/^br[0-9]+/) || - interface.match(/^vnet[0-9]+/) || - interface.match(/^tun[0-9]+/) || - interface.match(/^tap[0-9]+/) || - isNaN(currentInterfaceDownBytes) || - isNaN(currentInterfaceUpBytes)) { - continue; - } - - totalDownBytes += currentInterfaceDownBytes; - totalUpBytes += currentInterfaceUpBytes; - } - - if (lastTotalDownBytes === 0) { - lastTotalDownBytes = totalDownBytes; - } - if (lastTotalUpBytes === 0) { - lastTotalUpBytes = totalUpBytes; - } - - speed["down"] = (totalDownBytes - lastTotalDownBytes) / refreshInterval; - speed["up"] = (totalUpBytes - lastTotalUpBytes) / refreshInterval; - - lastTotalDownBytes = totalDownBytes; - lastTotalUpBytes = totalUpBytes; - } catch (e) { - logError(e); - } - - return speed; -}; const formatSpeedWithUnit = (amount) => { - let unitIndex = 0; - while (amount >= 1000 && unitIndex < speedUnits.length - 1) { - amount /= 1000; - ++unitIndex; - } - - let digits = 0; - // Instead of showing 0.00123456 as 0.00, show it as 0. - if (amount >= 100 || amount - 0 < 0.01) { - // 100 M/s, 200 K/s, 300 B/s. - digits = 0; - } else if (amount >= 10) { - // 10.1 M/s, 20.2 K/s, 30.3 B/s. - digits = 1; - } else { - // 1.01 M/s, 2.02 K/s, 3.03 B/s. - digits = 2; - } - - // See . - return `${amount.toFixed(digits)} ${speedUnits[unitIndex]}`; + let unitIndex = 0; + while (amount >= 1000 && unitIndex < speedUnits.length - 1) { + amount /= 1000; + ++unitIndex; + } + + let digits = 0; + // Instead of showing 0.00123456 as 0.00, show it as 0. + if (amount >= 100 || amount - 0 < 0.01) { + // 100 M/s, 200 K/s, 300 B/s. + digits = 0; + } else if (amount >= 10) { + // 10.1 M/s, 20.2 K/s, 30.3 B/s. + digits = 1; + } else { + // 1.01 M/s, 2.02 K/s, 3.03 B/s. + digits = 2; + } + + // See . + return `${amount.toFixed(digits)} ${speedUnits[unitIndex]}`; }; const toSpeedString = (speed) => { - return `↓ ${formatSpeedWithUnit(speed["down"])} ↑ ${formatSpeedWithUnit(speed["up"])}`; + return `↓ ${formatSpeedWithUnit(speed["down"])} ↑ ${formatSpeedWithUnit(speed["up"])}`; }; const Indicator = GObject.registerClass( -class Indicator extends PanelMenu.Button { + class Indicator extends PanelMenu.Button { _init() { - // menuAlignment, nameText, dontCreateMenu. - super._init(0.0, "Net Speed", true); + // menuAlignment, nameText, dontCreateMenu. + super._init(0.0, "Net Speed", true); - this._label = new St.Label({ - "y_align": Clutter.ActorAlign.CENTER, - "text": "---" - }); + this._label = new St.Label({ + "y_align": Clutter.ActorAlign.CENTER, + "text": "---" + }); - this.add_child(this._label); - - // let item = new PopupMenu.PopupMenuItem(_("Show Notification")); - // item.connect("activate", () => { - // Main.notify(_("Whatʼs up, folks?")); - // }); - // this.menu.addMenuItem(item); + this.add_child(this._label); } setText(text) { - return this._label.set_text(text); + return this._label.set_text(text); } -}); - -class Extension { - constructor(uuid) { - this._uuid = uuid; - - // ExtensionUtils.initTranslations(GETTEXT_DOMAIN); + }); + +export default class NetSpeed extends Extension { + constructor(metadata) { + super(metadata); + + this._metadata = metadata; + this._uuid = metadata.uuid; + + this._textDecoder = new TextDecoder(); + this._lastTotalDownBytes = 0; + this._lastTotalUpBytes = 0; + } + + enable() { + this._lastTotalDownBytes = 0; + this._lastTotalUpBytes = 0; + + this._indicator = new Indicator(); + // role, indicator, position, box. + // -1 is not OK, because it will show in the right side of system menu. + Main.panel.addToStatusArea(this._uuid, this._indicator, 0, "right"); + + this._timeout = GLib.timeout_add_seconds( + GLib.PRIORITY_DEFAULT, refreshInterval, () => { + const speed = this.getCurrentNetSpeed(refreshInterval); + const text = toSpeedString(speed); + // console.log(text); + this._indicator.setText(text); + // Run as loop, not once. + return GLib.SOURCE_CONTINUE; + } + ); + } + + disable() { + if (this._indicator != null) { + this._indicator.destroy(); + this._indicator = null; } - - enable() { - lastTotalDownBytes = 0; - lastTotalUpBytes = 0; - - this._indicator = new Indicator(); - // role, indicator, position, box. - // -1 is not OK, because it will show in the right side of system menu. - Main.panel.addToStatusArea(this._uuid, this._indicator, 0, "right"); - - this._timeout = GLib.timeout_add_seconds( - GLib.PRIORITY_DEFAULT, refreshInterval, () => { - const speed = getCurrentNetSpeed(refreshInterval); - const text = toSpeedString(speed); - // log(text); - this._indicator.setText(text); - // Run as loop, not once. - return GLib.SOURCE_CONTINUE; - } - ) + if (this._timeout != null) { + GLib.source_remove(this._timeout); + this._timeout = null; } + } + + getCurrentNetSpeed(refreshInterval) { + const speed = {"down": 0, "up": 0}; - disable() { - if (this._indicator != null) { - this._indicator.destroy(); - this._indicator = null; + try { + const inputFile = Gio.File.new_for_path("/proc/net/dev"); + const [, content] = inputFile.load_contents(null); + // See . + // + // `ByteArray` is deprecated with ES Module, standard JavaScript + // `TextDecoder` should be used here. + const lines = this._textDecoder.decode(content).split('\n'); + + // Caculate the sum of all interfaces line by line. + let totalDownBytes = 0; + let totalUpBytes = 0; + + for (let i = 0; i < lines.length; ++i) { + const fields = lines[i].trim().split(/\W+/); + if (fields.length <= 2) { + continue; } - if (this._timeout != null) { - GLib.source_remove(this._timeout); - this._timeout = null; + + // Skip virtual interfaces. + const iface = fields[0]; + const currentInterfaceDownBytes = Number.parseInt(fields[1]); + const currentInterfaceUpBytes = Number.parseInt(fields[9]); + if (iface === "lo" || + // Created by python-based bandwidth manager "traffictoll". + iface.match(/^ifb[0-9]+/) || + // Created by lxd container manager. + iface.match(/^lxdbr[0-9]+/) || + iface.match(/^virbr[0-9]+/) || + iface.match(/^br[0-9]+/) || + iface.match(/^vnet[0-9]+/) || + iface.match(/^tun[0-9]+/) || + iface.match(/^tap[0-9]+/) || + isNaN(currentInterfaceDownBytes) || + isNaN(currentInterfaceUpBytes)) { + continue; } + + totalDownBytes += currentInterfaceDownBytes; + totalUpBytes += currentInterfaceUpBytes; + } + + if (this._lastTotalDownBytes === 0) { + this._lastTotalDownBytes = totalDownBytes; + } + if (this._lastTotalUpBytes === 0) { + this._lastTotalUpBytes = totalUpBytes; + } + + speed["down"] = (totalDownBytes - this._lastTotalDownBytes) / + refreshInterval; + speed["up"] = (totalUpBytes - this._lastTotalUpBytes) / + refreshInterval; + + this._lastTotalDownBytes = totalDownBytes; + this._lastTotalUpBytes = totalUpBytes; + } catch (e) { + console.error(e); } -} -function init(meta) { - return new Extension(meta.uuid); -} + return speed; + } +}; diff --git a/metadata.json b/metadata.json index 856a6a3..063800a 100644 --- a/metadata.json +++ b/metadata.json @@ -3,6 +3,6 @@ "description": "Show current net speed on panel.", "uuid": "netspeed@alynx.one", "url": "https://github.com/AlynxZhou/gnome-shell-extension-net-speed/", - "version": 8, - "shell-version": ["40", "41", "42", "43", "44"] + "version": 9, + "shell-version": ["45"] }