Skip to content

Commit 869d7cb

Browse files
Tomasz NowakTomasz Nowak
Tomasz Nowak
authored and
Tomasz Nowak
committed
apt-updates@zamszowy: initial release
1 parent 997de79 commit 869d7cb

14 files changed

+1000
-0
lines changed

apt-updates@zamszowy/LICENSE

+674
Large diffs are not rendered by default.

apt-updates@zamszowy/README.md

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# APT updates notifier
2+
3+
This applet monitors if updates are available for systems using APT tool (like
4+
Debian). It also allows viewing available updates and installing them through
5+
the popup menu.
6+
7+
In order to have updates count refreshed, some external way to do this is
8+
needed (e.g. enabled automatic updates checking in `gnome-software`, or some
9+
other way to periodically run `apt update`).
10+
11+
## Settings
12+
13+
You can:
14+
15+
- change refresh timeout
16+
- change default (`apt update/upgrade`) commands to your own.
17+
- enable showing three (configurable) levels of icon to show how many packages
18+
are waiting for the upgrades.
19+
- hide applet if there are not updates available
20+
21+
## Dependencies
22+
23+
- `gnome-terminal`
24+
25+
## Icons
26+
27+
Icons are based on [Papirus icon theme](https://github.com/PapirusDevelopmentTeam/papirus-icon-theme).
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
const Applet = imports.ui.applet;
2+
const PopupMenu = imports.ui.popupMenu;
3+
const St = imports.gi.St;
4+
const Settings = imports.ui.settings;
5+
const Util = imports.misc.util;
6+
const GLib = imports.gi.GLib;
7+
const Lang = imports.lang;
8+
const Main = imports.ui.main;
9+
const Mainloop = imports.mainloop;
10+
11+
12+
function AptUpdates(metadata, orientation, panel_height, instance_id) {
13+
this._init(metadata, orientation, panel_height, instance_id);
14+
}
15+
16+
AptUpdates.prototype = {
17+
__proto__: Applet.TextIconApplet.prototype,
18+
19+
_init: function(metadata, orientation, panel_height, instance_id) {
20+
this.applet_path = metadata.path;
21+
22+
Applet.TextIconApplet.prototype._init.call(this, orientation, panel_height, instance_id);
23+
24+
this.set_applet_icon_name("update-none");
25+
this.hide_applet_label(true);
26+
27+
this.menuManager = new PopupMenu.PopupMenuManager(this);
28+
this.menu = new Applet.AppletPopupMenu(this, orientation);
29+
this.menuManager.addMenu(this.menu);
30+
31+
if (!GLib.find_program_in_path("gnome-terminal")) {
32+
this.hide_applet_icon(true);
33+
this.hide_applet_label(false);
34+
this.set_applet_label("missing dependencies");
35+
return;
36+
}
37+
38+
this.uuid = metadata.uuid;
39+
this.settings = new Settings.AppletSettings(this, metadata.uuid, instance_id);
40+
41+
this.settings.bind("update-refresh", "refreshTimeout", null, null);
42+
this.settings.bind("hide-applet", "hideApplet", this._update, null);
43+
44+
this.settings.bind("different-levels", "differentLevels", this._update, null);
45+
this.settings.bind("level-1", "level1", this._update, null);
46+
this.settings.bind("level-2", "level2", this._update, null);
47+
48+
this.settings.bind("commandUpdate", "commandUpdate", null, null);
49+
this.settings.bind("commandUpgrade", "commandUpgrade", null, null);
50+
51+
this.packages_count = 0;
52+
53+
this.enabled = true;
54+
this.run();
55+
},
56+
57+
_update: function() {
58+
const count = this.packages_count;
59+
60+
this.set_applet_enabled(!this.hideApplet || count != 0);
61+
62+
if (this.differentLevels) {
63+
if (count <= 0) {
64+
this.set_applet_tooltip("No updates available");
65+
this.set_applet_icon_name("update-none");
66+
} else if (count < this.level1) {
67+
this.set_applet_tooltip(count.toString() + " updates available");
68+
this.set_applet_icon_name("update-low");
69+
} else if (count < this.level2) {
70+
this.set_applet_tooltip(count.toString() + " updates available");
71+
this.set_applet_icon_name("update-medium");
72+
} else {
73+
this.set_applet_tooltip(count.toString() + " updates available");
74+
this.set_applet_icon_name("update-high");
75+
}
76+
} else {
77+
if (count <= 0) {
78+
this.set_applet_tooltip("No updates available");
79+
this.set_applet_icon_name("update-none");
80+
} else {
81+
this.set_applet_tooltip(count.toString() + " updates available");
82+
this.set_applet_icon_name("update-low");
83+
}
84+
}
85+
86+
this.menu.removeAll();
87+
this._contentSection = new PopupMenu.PopupMenuSection();
88+
this.menu.addMenuItem(this._contentSection);
89+
90+
const iViewStr = count > 0 ? "View " + count.toString() + " updates" : "No updates to view";
91+
let iView = new PopupMenu.PopupIconMenuItem(iViewStr, "view-list-bullet-symbolic", St.IconType.SYMBOLIC, {reactive: count > 0});
92+
iView.connect('activate', Lang.bind(this, function () {
93+
Util.spawn_async(['/bin/bash', this.applet_path + '/updates.sh', "view"]);
94+
}));
95+
96+
let iCheck = new PopupMenu.PopupIconMenuItem("Check for new updates", "view-refresh-symbolic", St.IconType.SYMBOLIC);
97+
iCheck.connect('activate', Lang.bind(this, function () {
98+
const args = ['/bin/bash', this.applet_path + '/updates.sh', "command", this.commandUpdate];
99+
Util.spawn_async(args, Lang.bind(this, function() {
100+
this._refreshUpdatesInfo();
101+
}));
102+
}));
103+
104+
const iUpgradeStr = count > 0 ? "Upgrade " + count.toString() + " packages" : "No packages to upgrade";
105+
let iUpgrade = new PopupMenu.PopupIconMenuItem(iUpgradeStr, "system-run-symbolic", St.IconType.SYMBOLIC, {reactive: count > 0});
106+
iUpgrade.connect('activate', Lang.bind(this, function () {
107+
const args = ['/bin/bash', this.applet_path + '/updates.sh', "command", this.commandUpgrade];
108+
Util.spawn_async(args, Lang.bind(this, function() {
109+
this._refreshUpdatesInfo();
110+
}));
111+
}));
112+
113+
this.menu.addMenuItem(iCheck);
114+
this.menu.addMenuItem(iView);
115+
this.menu.addMenuItem(iUpgrade);
116+
},
117+
118+
on_applet_clicked: function() {
119+
this.menu.toggle();
120+
},
121+
122+
on_applet_removed: function() {
123+
this.enabled = false;
124+
},
125+
126+
_refreshUpdatesInfo: function() {
127+
Util.spawn_async(['/bin/bash', this.applet_path + '/updates.sh', "check"], Lang.bind(this, function(stdout){
128+
this.packages_count = parseInt(stdout.trim());
129+
this._update();
130+
}));
131+
},
132+
133+
run: function() {
134+
if (!this.enabled) {
135+
return;
136+
}
137+
138+
Util.spawn_async(['/bin/bash', this.applet_path + '/updates.sh', "check"], Lang.bind(this, function(stdout){
139+
this.packages_count = parseInt(stdout.trim());
140+
this._update();
141+
142+
Util.spawn_async(['/usr/bin/sleep', (parseInt(this.refreshTimeout) * 60).toString()], Lang.bind(this, function(_) {
143+
this.run();
144+
}));
145+
}));
146+
},
147+
};
148+
149+
function main(metadata, orientation, panel_height, instance_id) {
150+
return new AptUpdates(metadata, orientation, panel_height, instance_id);
151+
}
Loading
Loading
Loading
Loading
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#!/usr/bin/gjs
2+
3+
imports.gi.versions.Gtk = "3.0";
4+
const Gtk = imports.gi.Gtk;
5+
const GLib = imports.gi.GLib;
6+
7+
function onKeyPress(actor, event) {
8+
const [, key] = event.get_keyval();
9+
const [, modifier] = event.get_state();
10+
11+
if ((key === 65307 /* ESC */) || (key === 119 /* w */ && modifier == 20 /* ctrl */)) {
12+
actor.close();
13+
Gtk.main_quit();
14+
}
15+
}
16+
17+
Gtk.init(null);
18+
19+
let win = new Gtk.Window({ title: ARGV[0] });
20+
21+
let scroll = new Gtk.ScrolledWindow();
22+
scroll.set_size_request(640, 640);
23+
24+
let textview = new Gtk.TextView();
25+
textview.set_editable(false);
26+
textview.buffer.text = new TextDecoder().decode(GLib.file_get_contents(ARGV[1])[1]);
27+
28+
scroll.add(textview);
29+
win.add(scroll);
30+
31+
win.connect("delete-event", () => Gtk.main_quit());
32+
win.connect("key-press-event", onKeyPress);
33+
34+
win.show_all();
35+
Gtk.main();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"uuid": "apt-updates@zamszowy",
3+
"name": "APT updates notifier",
4+
"description": "Shows icons for pending updates in APT-based systems"
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
{
2+
"section1": {
3+
"type": "section",
4+
"description": "Settings"
5+
},
6+
"update-refresh": {
7+
"type": "entry",
8+
"default": "60",
9+
"description": "Minutes to wait before refreshing applet"
10+
},
11+
"hide-applet": {
12+
"type": "switch",
13+
"default": false,
14+
"description": "Hide applet if there are no updates"
15+
},
16+
"different-levels": {
17+
"type": "switch",
18+
"default": false,
19+
"description": "Show different applet icon for different updgradeable packages count"
20+
},
21+
"level-1": {
22+
"type": "entry",
23+
"default": "100",
24+
"description": "Show low level icon when updates count is between 0 and this value ",
25+
"dependency": "different-levels"
26+
},
27+
"level-2": {
28+
"type": "entry",
29+
"default": "200",
30+
"description": "Show medium level icon when updates count is between low level value and this value. Show high level icon if it's higher than this value.",
31+
"dependency": "different-levels"
32+
},
33+
"section2": {
34+
"type": "section",
35+
"description": "Commands to execute in popup menu"
36+
},
37+
"commandUpdate": {
38+
"type": "entry",
39+
"default": "sudo apt update",
40+
"description": "Check for updates:"
41+
},
42+
"commandUpgrade": {
43+
"type": "entry",
44+
"default": "sudo apt -V upgrade",
45+
"description": "Upgrade packages:"
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/bash
2+
3+
set -eu
4+
5+
DIR=$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")
6+
readonly DIR
7+
8+
case "$1" in
9+
check)
10+
apt list --upgradable 2>/dev/null | tail -n +2 &> "$DIR"/updates
11+
wc -l <"$DIR"/updates
12+
;;
13+
view)
14+
/usr/bin/cjs "$DIR"/info-window.js "$(wc -l <"$DIR"/updates) updates" "$DIR"/updates
15+
;;
16+
command)
17+
readonly cmd=$2
18+
gnome-terminal --wait -- /bin/bash -c "echo \"Executing $cmd\"; $cmd; echo -en \"\nDone - press enter to exit\"; read"
19+
;;
20+
*)
21+
exit 1
22+
;;
23+
esac

apt-updates@zamszowy/info.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"author": "zamszowy"
3+
}

apt-updates@zamszowy/screenshot.png

13.6 KB
Loading

0 commit comments

Comments
 (0)