Merge lp:~ddieter/appcenter/appcenter-notify-restart into lp:~elementary-apps/appcenter/appcenter
- appcenter-notify-restart
- Merge into appcenter
Proposed by
Dieter Debast
Status: | Rejected |
---|---|
Rejected by: | Danielle Foré |
Proposed branch: | lp:~ddieter/appcenter/appcenter-notify-restart |
Merge into: | lp:~elementary-apps/appcenter/appcenter |
Diff against target: |
328 lines (+176/-12) 6 files modified
src/CMakeLists.txt (+2/-0) src/Core/Client.vala (+24/-0) src/Services/DbusInterfaces.vala (+24/-0) src/Views/AppListView.vala (+23/-2) src/Widgets/RestartDialog.vala (+87/-0) src/Widgets/UpdateHeaderRow.vala (+16/-10) |
To merge this branch: | bzr merge lp:~ddieter/appcenter/appcenter-notify-restart |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
elementary Apps team | Pending | ||
Review via email: mp+317155@code.launchpad.net |
Commit message
Description of the change
After installing updates or periodically when updating the cache, appcenter checks for the existence of the /var/run/
If this file exists, appcenter shows a notification and the "Up to Date" text is changed to "Restart required". There's also a "Restart now" button that shows a confirmation dialog and allows the user to restart the device.
To post a comment you must log in.
Revision history for this message
Danielle Foré (danrabbit) wrote : | # |
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/CMakeLists.txt' | |||
2 | --- src/CMakeLists.txt 2017-02-10 20:15:32 +0000 | |||
3 | +++ src/CMakeLists.txt 2017-02-13 23:26:06 +0000 | |||
4 | @@ -23,6 +23,8 @@ | |||
5 | 23 | Widgets/AppListRow.vala | 23 | Widgets/AppListRow.vala |
6 | 24 | Widgets/AppActionButton.vala | 24 | Widgets/AppActionButton.vala |
7 | 25 | Widgets/UpdateHeaderRow.vala | 25 | Widgets/UpdateHeaderRow.vala |
8 | 26 | Widgets/RestartDialog.vala | ||
9 | 27 | Services/DbusInterfaces.vala | ||
10 | 26 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala | 28 | ${CMAKE_CURRENT_BINARY_DIR}/config.vala |
11 | 27 | PACKAGES | 29 | PACKAGES |
12 | 28 | appstream | 30 | appstream |
13 | 29 | 31 | ||
14 | === modified file 'src/Core/Client.vala' | |||
15 | --- src/Core/Client.vala 2017-02-04 17:18:30 +0000 | |||
16 | +++ src/Core/Client.vala 2017-02-13 23:26:06 +0000 | |||
17 | @@ -17,6 +17,8 @@ | |||
18 | 17 | public class AppCenterCore.Client : Object { | 17 | public class AppCenterCore.Client : Object { |
19 | 18 | public signal void updates_available (); | 18 | public signal void updates_available (); |
20 | 19 | 19 | ||
21 | 20 | private const string RESTART_REQUIRED_FILE = "/var/run/reboot-required"; | ||
22 | 21 | |||
23 | 20 | public bool connected { public get; private set; } | 22 | public bool connected { public get; private set; } |
24 | 21 | public bool updating_cache { public get; private set; } | 23 | public bool updating_cache { public get; private set; } |
25 | 22 | public uint task_count { public get; private set; default = 0; } | 24 | public uint task_count { public get; private set; default = 0; } |
26 | @@ -29,6 +31,7 @@ | |||
27 | 29 | private GLib.DateTime last_cache_update; | 31 | private GLib.DateTime last_cache_update; |
28 | 30 | private uint updates_number = 0U; | 32 | private uint updates_number = 0U; |
29 | 31 | private uint update_cache_timeout_id = 0; | 33 | private uint update_cache_timeout_id = 0; |
30 | 34 | private bool restart_required = false; | ||
31 | 32 | private bool refresh_in_progress = false; | 35 | private bool refresh_in_progress = false; |
32 | 33 | 36 | ||
33 | 34 | private const int SECONDS_BETWEEN_REFRESHES = 60*60*24; | 37 | private const int SECONDS_BETWEEN_REFRESHES = 60*60*24; |
34 | @@ -354,6 +357,25 @@ | |||
35 | 354 | task_count--; | 357 | task_count--; |
36 | 355 | refresh_in_progress = false; | 358 | refresh_in_progress = false; |
37 | 356 | } | 359 | } |
38 | 360 | |||
39 | 361 | public async bool check_restart () { | ||
40 | 362 | if (FileUtils.test (RESTART_REQUIRED_FILE, FileTest.EXISTS)) { | ||
41 | 363 | if (!restart_required) { | ||
42 | 364 | string title = _("Restart Required"); | ||
43 | 365 | string body = _("Please restart your system to finalize updates"); | ||
44 | 366 | var notification = new Notification (title); | ||
45 | 367 | notification.set_body (body); | ||
46 | 368 | notification.set_icon (new ThemedIcon ("system-software-install")); | ||
47 | 369 | notification.set_default_action ("app.open-application"); | ||
48 | 370 | Application.get_default ().send_notification ("restart", notification); | ||
49 | 371 | } | ||
50 | 372 | |||
51 | 373 | restart_required = true; | ||
52 | 374 | return true; | ||
53 | 375 | } | ||
54 | 376 | |||
55 | 377 | return false; | ||
56 | 378 | } | ||
57 | 357 | 379 | ||
58 | 358 | public uint get_package_count (GLib.GenericArray<weak Pk.Package> package_array) { | 380 | public uint get_package_count (GLib.GenericArray<weak Pk.Package> package_array) { |
59 | 359 | bool os_update_found = false; | 381 | bool os_update_found = false; |
60 | @@ -436,6 +458,8 @@ | |||
61 | 436 | } else { | 458 | } else { |
62 | 437 | refresh_in_progress = false; //Stops new timeout while no network. | 459 | refresh_in_progress = false; //Stops new timeout while no network. |
63 | 438 | } | 460 | } |
64 | 461 | |||
65 | 462 | check_restart.begin (); | ||
66 | 439 | } else { | 463 | } else { |
67 | 440 | debug ("Too soon to refresh and not forced"); | 464 | debug ("Too soon to refresh and not forced"); |
68 | 441 | } | 465 | } |
69 | 442 | 466 | ||
70 | === added directory 'src/Services' | |||
71 | === added file 'src/Services/DbusInterfaces.vala' | |||
72 | --- src/Services/DbusInterfaces.vala 1970-01-01 00:00:00 +0000 | |||
73 | +++ src/Services/DbusInterfaces.vala 2017-02-13 23:26:06 +0000 | |||
74 | @@ -0,0 +1,24 @@ | |||
75 | 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- | ||
76 | 2 | /*- | ||
77 | 3 | * Copyright (c) 2014-2016 elementary LLC. (https://elementary.io) | ||
78 | 4 | * | ||
79 | 5 | * This program is free software: you can redistribute it and/or modify | ||
80 | 6 | * it under the terms of the GNU General Public License as published by | ||
81 | 7 | * the Free Software Foundation, either version 3 of the License, or | ||
82 | 8 | * (at your option) any later version. | ||
83 | 9 | * | ||
84 | 10 | * This program is distributed in the hope that it will be useful, | ||
85 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
86 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
87 | 13 | * GNU General Public License for more details. | ||
88 | 14 | * | ||
89 | 15 | * You should have received a copy of the GNU General Public License | ||
90 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
91 | 17 | */ | ||
92 | 18 | |||
93 | 19 | /* Power and system control */ | ||
94 | 20 | [DBus (name = "org.freedesktop.login1.Manager")] | ||
95 | 21 | interface SystemInterface : Object { | ||
96 | 22 | public abstract void reboot (bool interactive) throws IOError; | ||
97 | 23 | } | ||
98 | 24 | |||
99 | 0 | 25 | ||
100 | === modified file 'src/Views/AppListView.vala' | |||
101 | --- src/Views/AppListView.vala 2017-02-04 17:18:30 +0000 | |||
102 | +++ src/Views/AppListView.vala 2017-02-13 23:26:06 +0000 | |||
103 | @@ -37,6 +37,7 @@ | |||
104 | 37 | private Widgets.UpdateHeaderRow updates_header; | 37 | private Widgets.UpdateHeaderRow updates_header; |
105 | 38 | private Widgets.UpdateHeaderRow updated_header; | 38 | private Widgets.UpdateHeaderRow updated_header; |
106 | 39 | private Widgets.AppActionButton update_all_button; | 39 | private Widgets.AppActionButton update_all_button; |
107 | 40 | private Widgets.AppActionButton restart_button; | ||
108 | 40 | private bool updating_all_apps = false; | 41 | private bool updating_all_apps = false; |
109 | 41 | private bool apps_remaining_started = false; | 42 | private bool apps_remaining_started = false; |
110 | 42 | private GLib.Mutex update_mutex; | 43 | private GLib.Mutex update_mutex; |
111 | @@ -66,11 +67,21 @@ | |||
112 | 66 | update_all_button.clicked.connect (on_update_all); | 67 | update_all_button.clicked.connect (on_update_all); |
113 | 67 | update_all_button.no_show_all = true; | 68 | update_all_button.no_show_all = true; |
114 | 68 | action_button_group.add_widget (update_all_button); | 69 | action_button_group.add_widget (update_all_button); |
115 | 70 | |||
116 | 71 | restart_button = new Widgets.AppActionButton (_("Restart Now")); | ||
117 | 72 | restart_button.set_suggested_action_header (); | ||
118 | 73 | restart_button.clicked.connect (() => { | ||
119 | 74 | var dialog = new Widgets.RestartDialog (); | ||
120 | 75 | dialog.show_all (); | ||
121 | 76 | }); | ||
122 | 77 | restart_button.no_show_all = true; | ||
123 | 78 | action_button_group.add_widget (restart_button); | ||
124 | 69 | 79 | ||
125 | 70 | updates_header = new Widgets.UpdateHeaderRow.updates (); | 80 | updates_header = new Widgets.UpdateHeaderRow.updates (); |
126 | 71 | updates_header.add_widget (update_all_button); | 81 | updates_header.add_widget (update_all_button); |
127 | 72 | 82 | ||
128 | 73 | updated_header = new Widgets.UpdateHeaderRow.updated (); | 83 | updated_header = new Widgets.UpdateHeaderRow.updated (); |
129 | 84 | updated_header.add_widget (restart_button); | ||
130 | 74 | 85 | ||
131 | 75 | list_box.add (updates_header); | 86 | list_box.add (updates_header); |
132 | 76 | list_box.add (updated_header); | 87 | list_box.add (updated_header); |
133 | @@ -256,12 +267,22 @@ | |||
134 | 256 | } | 267 | } |
135 | 257 | } | 268 | } |
136 | 258 | 269 | ||
138 | 259 | updates_header.update (update_numbers, update_real_size, updating_cache); | 270 | updates_header.update (update_numbers, update_real_size, updating_cache, false); |
139 | 260 | update_all_button.visible = !updating_cache && update_numbers > 0; | 271 | update_all_button.visible = !updating_cache && update_numbers > 0; |
140 | 261 | } | 272 | } |
141 | 262 | 273 | ||
142 | 263 | private void update_updated_grid () { | 274 | private void update_updated_grid () { |
144 | 264 | updated_header.update (0, 0, updating_cache); | 275 | if (!updating_all_apps && !updating_cache) { |
145 | 276 | var client = AppCenterCore.Client.get_default (); | ||
146 | 277 | client.check_restart.begin ((obj, res) => { | ||
147 | 278 | var restart_required = client.check_restart.end (res); | ||
148 | 279 | |||
149 | 280 | updated_header.update (0, 0, updating_cache, restart_required); | ||
150 | 281 | restart_button.visible = restart_required; | ||
151 | 282 | }); | ||
152 | 283 | } else { | ||
153 | 284 | updated_header.update (0, 0, updating_cache, false); | ||
154 | 285 | } | ||
155 | 265 | } | 286 | } |
156 | 266 | } | 287 | } |
157 | 267 | } | 288 | } |
158 | 268 | 289 | ||
159 | === added file 'src/Widgets/RestartDialog.vala' | |||
160 | --- src/Widgets/RestartDialog.vala 1970-01-01 00:00:00 +0000 | |||
161 | +++ src/Widgets/RestartDialog.vala 2017-02-13 23:26:06 +0000 | |||
162 | @@ -0,0 +1,87 @@ | |||
163 | 1 | // -*- Mode: vala; indent-tabs-mode: nil; tab-width: 4 -*- | ||
164 | 2 | /*- | ||
165 | 3 | * Copyright (c) 2014-2016 elementary LLC. (https://elementary.io) | ||
166 | 4 | * | ||
167 | 5 | * This program is free software: you can redistribute it and/or modify | ||
168 | 6 | * it under the terms of the GNU General Public License as published by | ||
169 | 7 | * the Free Software Foundation, either version 3 of the License, or | ||
170 | 8 | * (at your option) any later version. | ||
171 | 9 | * | ||
172 | 10 | * This program is distributed in the hope that it will be useful, | ||
173 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
174 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
175 | 13 | * GNU General Public License for more details. | ||
176 | 14 | * | ||
177 | 15 | * You should have received a copy of the GNU General Public License | ||
178 | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
179 | 17 | */ | ||
180 | 18 | |||
181 | 19 | namespace AppCenter.Widgets { | ||
182 | 20 | public class RestartDialog : Gtk.Dialog { | ||
183 | 21 | private SystemInterface system_interface; | ||
184 | 22 | |||
185 | 23 | public RestartDialog () { | ||
186 | 24 | Object (title: "", deletable: false, skip_taskbar_hint: true, skip_pager_hint: true, type_hint: Gdk.WindowTypeHint.DIALOG); | ||
187 | 25 | } | ||
188 | 26 | |||
189 | 27 | construct { | ||
190 | 28 | try { | ||
191 | 29 | system_interface = Bus.get_proxy_sync (BusType.SYSTEM, "org.freedesktop.login1", "/org/freedesktop/login1"); | ||
192 | 30 | } catch (IOError e) { | ||
193 | 31 | stderr.printf ("%s\n", e.message); | ||
194 | 32 | } | ||
195 | 33 | |||
196 | 34 | /* | ||
197 | 35 | * the restart type is currently used by the indicator for what is | ||
198 | 36 | * labelled shutdown because of unity's implementation of it | ||
199 | 37 | * apparently. So we got to adjust to that until they fix this. | ||
200 | 38 | */ | ||
201 | 39 | string icon_name = "system-shutdown"; | ||
202 | 40 | string heading_text = _("Are you sure you want to Restart?"); | ||
203 | 41 | string content_text = _("This will close all open applications and restart this device."); | ||
204 | 42 | string button_text = _("Restart"); | ||
205 | 43 | |||
206 | 44 | set_position (Gtk.WindowPosition.CENTER_ALWAYS); | ||
207 | 45 | set_keep_above (true); | ||
208 | 46 | stick (); | ||
209 | 47 | set_resizable (false); | ||
210 | 48 | |||
211 | 49 | var heading = new Gtk.Label ("<span weight='bold' size='larger'>" + heading_text + "</span>"); | ||
212 | 50 | heading.get_style_context ().add_class ("larger"); | ||
213 | 51 | heading.use_markup = true; | ||
214 | 52 | heading.halign = Gtk.Align.START; | ||
215 | 53 | |||
216 | 54 | var grid = new Gtk.Grid (); | ||
217 | 55 | grid.column_spacing = 12; | ||
218 | 56 | grid.row_spacing = 12; | ||
219 | 57 | grid.margin_left = grid.margin_right = grid.margin_bottom = 12; | ||
220 | 58 | grid.attach (new Gtk.Image.from_icon_name (icon_name, Gtk.IconSize.DIALOG), 0, 0, 1, 2); | ||
221 | 59 | grid.attach (heading, 1, 0, 1, 1); | ||
222 | 60 | grid.attach (new Gtk.Label (content_text), 1, 1, 1, 1); | ||
223 | 61 | |||
224 | 62 | var cancel = add_button (_("Cancel"), Gtk.ResponseType.CANCEL) as Gtk.Button; | ||
225 | 63 | cancel.clicked.connect (() => { destroy (); }); | ||
226 | 64 | |||
227 | 65 | var confirm = add_button (button_text, Gtk.ResponseType.OK) as Gtk.Button; | ||
228 | 66 | confirm.get_style_context ().add_class ("destructive-action"); | ||
229 | 67 | confirm.clicked.connect (() => { | ||
230 | 68 | try { | ||
231 | 69 | system_interface.reboot (false); | ||
232 | 70 | } catch (IOError e) { | ||
233 | 71 | stderr.printf ("%s\n", e.message); | ||
234 | 72 | } | ||
235 | 73 | |||
236 | 74 | destroy (); | ||
237 | 75 | }); | ||
238 | 76 | |||
239 | 77 | set_default (confirm); | ||
240 | 78 | |||
241 | 79 | get_content_area ().add (grid); | ||
242 | 80 | |||
243 | 81 | var action_area = get_action_area (); | ||
244 | 82 | action_area.margin_right = 6; | ||
245 | 83 | action_area.margin_bottom = 6; | ||
246 | 84 | } | ||
247 | 85 | } | ||
248 | 86 | } | ||
249 | 87 | |||
250 | 0 | 88 | ||
251 | === modified file 'src/Widgets/UpdateHeaderRow.vala' | |||
252 | --- src/Widgets/UpdateHeaderRow.vala 2016-09-17 19:28:03 +0000 | |||
253 | +++ src/Widgets/UpdateHeaderRow.vala 2017-02-13 23:26:06 +0000 | |||
254 | @@ -70,8 +70,8 @@ | |||
255 | 70 | grid.add (widget); | 70 | grid.add (widget); |
256 | 71 | } | 71 | } |
257 | 72 | 72 | ||
260 | 73 | public void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) { | 73 | public void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating, bool _restart_required) { |
261 | 74 | grid.update (_update_numbers, _update_real_size, _is_updating); | 74 | grid.update (_update_numbers, _update_real_size, _is_updating, _restart_required); |
262 | 75 | changed (); /* Triggers resort */ | 75 | changed (); /* Triggers resort */ |
263 | 76 | } | 76 | } |
264 | 77 | /** ---------------- **/ | 77 | /** ---------------- **/ |
265 | @@ -81,19 +81,21 @@ | |||
266 | 81 | public uint update_numbers {get; protected set; default = 0;} | 81 | public uint update_numbers {get; protected set; default = 0;} |
267 | 82 | public uint64 update_real_size {get; protected set; default = 0;} | 82 | public uint64 update_real_size {get; protected set; default = 0;} |
268 | 83 | public bool is_updating {get; protected set; default = false;} | 83 | public bool is_updating {get; protected set; default = false;} |
269 | 84 | public bool restart_required {get; protected set; default = false;} | ||
270 | 84 | 85 | ||
271 | 85 | construct { | 86 | construct { |
272 | 86 | margin = 12; | 87 | margin = 12; |
273 | 87 | column_spacing = 12; | 88 | column_spacing = 12; |
274 | 88 | } | 89 | } |
275 | 89 | 90 | ||
277 | 90 | protected void store_data (uint _update_numbers, uint64 _update_real_size, bool _is_updating) { | 91 | protected void store_data (uint _update_numbers, uint64 _update_real_size, bool _is_updating, bool _restart_required) { |
278 | 91 | update_numbers = _update_numbers; | 92 | update_numbers = _update_numbers; |
279 | 92 | update_real_size = _update_real_size; | 93 | update_real_size = _update_real_size; |
280 | 93 | is_updating = _is_updating; | 94 | is_updating = _is_updating; |
281 | 95 | restart_required = _restart_required; | ||
282 | 94 | } | 96 | } |
283 | 95 | 97 | ||
285 | 96 | public abstract void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating); | 98 | public abstract void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating, bool _restart_required); |
286 | 97 | } | 99 | } |
287 | 98 | 100 | ||
288 | 99 | /** Header to show at top of list if there are updates available **/ | 101 | /** Header to show at top of list if there are updates available **/ |
289 | @@ -114,8 +116,8 @@ | |||
290 | 114 | add (update_size_label); | 116 | add (update_size_label); |
291 | 115 | } | 117 | } |
292 | 116 | 118 | ||
295 | 117 | public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) { | 119 | public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating, bool _restart_required) { |
296 | 118 | store_data (_update_numbers, _update_real_size, _is_updating); | 120 | store_data (_update_numbers, _update_real_size, _is_updating, _restart_required); |
297 | 119 | 121 | ||
298 | 120 | if (!is_updating) { | 122 | if (!is_updating) { |
299 | 121 | updates_label.label = ngettext ("%u Update Available", "%u Updates Available", update_numbers).printf (update_numbers); | 123 | updates_label.label = ngettext ("%u Update Available", "%u Updates Available", update_numbers).printf (update_numbers); |
300 | @@ -147,8 +149,8 @@ | |||
301 | 147 | add (spinner); | 149 | add (spinner); |
302 | 148 | } | 150 | } |
303 | 149 | 151 | ||
306 | 150 | public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating) { | 152 | public override void update (uint _update_numbers, uint64 _update_real_size, bool _is_updating, bool _restart_required) { |
307 | 151 | store_data (_update_numbers, _update_real_size, _is_updating); | 153 | store_data (_update_numbers, _update_real_size, _is_updating, _restart_required); |
308 | 152 | 154 | ||
309 | 153 | if (is_updating) { | 155 | if (is_updating) { |
310 | 154 | halign = Gtk.Align.CENTER; | 156 | halign = Gtk.Align.CENTER; |
311 | @@ -158,11 +160,15 @@ | |||
312 | 158 | label.label = _("Searching for updates…"); | 160 | label.label = _("Searching for updates…"); |
313 | 159 | label.get_style_context ().remove_class ("h4"); | 161 | label.get_style_context ().remove_class ("h4"); |
314 | 160 | } else { | 162 | } else { |
316 | 161 | halign = Gtk.Align.START; | 163 | halign = Gtk.Align.FILL; |
317 | 162 | spinner.stop (); | 164 | spinner.stop (); |
318 | 163 | spinner.no_show_all = true; | 165 | spinner.no_show_all = true; |
319 | 164 | spinner.hide (); | 166 | spinner.hide (); |
321 | 165 | label.label = _("Up to Date"); | 167 | if (restart_required) { |
322 | 168 | label.label = _("Restart required"); | ||
323 | 169 | } else { | ||
324 | 170 | label.label = _("Up to Date"); | ||
325 | 171 | } | ||
326 | 166 | label.get_style_context ().add_class ("h4"); | 172 | label.get_style_context ().add_class ("h4"); |
327 | 167 | } | 173 | } |
328 | 168 | } | 174 | } |
superseded by https:/ /code.launchpad .net/~nathandye r/appcenter/ restart- notification/ +merge/ 320067