[polari/wip/fmuellner/flatpak-updates: 3/3] app: Offer restart on update
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari/wip/fmuellner/flatpak-updates: 3/3] app: Offer restart on update
- Date: Tue, 4 Dec 2018 17:48:00 +0000 (UTC)
commit f095a72abb28a389d9fb2c1483c96960dd18f3a3
Author: Florian Müllner <fmuellner gnome org>
Date: Thu Nov 29 16:33:53 2018 +0100
app: Offer restart on update
Flatpak gives us a clearly defined way of detecting when the app has
been updated, as well as a portal for spawning the latest version.
Use that to offer a seamless restart whenever the app is updated.
https://gitlab.gnome.org/GNOME/polari/merge_requests/80
data/resources/main-window.ui | 27 ++++++++++++++++++++++++++
src/application.js | 45 +++++++++++++++++++++++++++++++++++++++++++
src/mainWindow.js | 14 +++++++++++++-
3 files changed, 85 insertions(+), 1 deletion(-)
---
diff --git a/data/resources/main-window.ui b/data/resources/main-window.ui
index 9247e48..810cfc2 100644
--- a/data/resources/main-window.ui
+++ b/data/resources/main-window.ui
@@ -35,6 +35,33 @@
<action-widget response="accept">backgroundButton</action-widget>
</action-widgets>
</object>
+ <object class="GtkMessageDialog" id="updateDialog">
+ <property name="text" translatable="yes">Polari has been updated</property>
+ <property name="secondary_text" translatable="yes">You can start using the new version immediately
without interrupting existing connections, or keep using the current version until Polari is
closed.</property>
+ <property name="destroy-with-parent">true</property>
+ <property name="modal">true</property>
+ <child type="action">
+ <object class="GtkButton" id="ignoreButton">
+ <property name="label" translatable="yes">Ignore</property>
+ <property name="visible">True</property>
+ <property name="can-default">True</property>
+ </object>
+ </child>
+ <child type="action">
+ <object class="GtkButton" id="restartButton">
+ <property name="label" translatable="yes">Restart Now</property>
+ <property name="visible">True</property>
+ <property name="can-default">True</property>
+ <style>
+ <class name="suggested-action"/>
+ </style>
+ </object>
+ </child>
+ <action-widgets>
+ <action-widget response="cancel">ignoreButton</action-widget>
+ <action-widget response="accept">restartButton</action-widget>
+ </action-widgets>
+ </object>
<template class="Gjs_MainWindow">
<property name="title" translatable="yes">Polari</property>
<property name="icon-name">org.gnome.Polari</property>
diff --git a/src/application.js b/src/application.js
index 62f8f4a..c8e8b11 100644
--- a/src/application.js
+++ b/src/application.js
@@ -38,6 +38,7 @@ var Application = GObject.registerClass({
this._windowRemovedId = 0;
this._restarting = false;
+ this._updatePending = false;
this.add_main_option('start-client', 0,
GLib.OptionFlags.NONE, GLib.OptionArg.NONE,
@@ -235,6 +236,9 @@ var Application = GObject.registerClass({
accels: ['F1'] },
{ name: 'about',
activate: this._onShowAbout.bind(this) },
+ { name: 'restart',
+ activate: this._onRestart.bind(this),
+ create_hook: a => { a.enabled = Utils.isFlatpakSandbox(); } },
{ name: 'quit',
activate: this._onQuit.bind(this),
accels: ['<Primary>q'] },
@@ -341,6 +345,18 @@ var Application = GObject.registerClass({
Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+ let file = Gio.File.new_for_path('/app/.updated');
+ this._updateMonitor = file.monitor_file(Gio.FileMonitorFlags.NONE, null);
+ this._updateMonitor.connect('changed', (mon, file, other, eventType) => {
+ if (eventType != Gio.FileMonitorEvent.CREATED)
+ return;
+
+ if (this.active_window)
+ this.active_window.showUpdateDialog();
+ else
+ this._updatePending = true;
+ });
}
vfunc_activate() {
@@ -371,6 +387,10 @@ var Application = GObject.registerClass({
}
this.active_window.present();
+
+ if (this._updatePending)
+ this.active_window.showUpdateDialog();
+ this._updatePending = false;
}
vfunc_window_added(window) {
@@ -861,6 +881,31 @@ var Application = GObject.registerClass({
});
}
+ _onRestart() {
+ let cwd = GLib.get_current_dir();
+ let argv = ['polari', '--gapplication-replace'];
+ let fds = [];
+ let envs = [];
+ let flags = 2; // respawn latest
+ let options = [];
+ this.get_dbus_connection().call(
+ 'org.freedesktop.portal.Flatpak',
+ '/org/freedesktop/portal/Flatpak',
+ 'org.freedesktop.portal.Flatpak',
+ 'Spawn',
+ new GLib.Variant(
+ '(ayaaya{uh}a{ss}ua{sv})',
+ [cwd, argv, fds, envs, flags, options]),
+ null,
+ Gio.DBusCallFlags.NONE,
+ -1,
+ null,
+ (conn, res) => {
+ let [pid] = conn.call_finish(res).deep_unpack();
+ debug(`Restarted with PID ${pid}`);
+ });
+ }
+
_onQuit() {
if (this._windowRemovedId)
this.disconnect(this._windowRemovedId);
diff --git a/src/mainWindow.js b/src/mainWindow.js
index dd65c51..e90c8a5 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -88,7 +88,8 @@ var MainWindow = GObject.registerClass({
'roomListRevealer',
'overlay',
'roomStack',
- 'closeConfirmationDialog'],
+ 'closeConfirmationDialog',
+ 'updateDialog'],
Properties: {
subtitle: GObject.ParamSpec.string('subtitle',
'subtitle',
@@ -193,6 +194,13 @@ var MainWindow = GObject.registerClass({
this.destroy();
});
+ this._updateDialog.transient_for = this;
+ this._updateDialog.connect('response', (dlg, response) => {
+ if (response == Gtk.ResponseType.ACCEPT)
+ this.application.activate_action('restart', null);
+ dlg.destroy();
+ });
+
this.connect('window-state-event', this._onWindowStateEvent.bind(this));
this.connect('size-allocate', this._onSizeAllocate.bind(this));
this.connect('destroy', this._onDestroy.bind(this));
@@ -375,6 +383,10 @@ var MainWindow = GObject.registerClass({
this._lastActiveRoom = null;
}
+ showUpdateDialog() {
+ this._updateDialog.show();
+ }
+
showJoinRoomDialog() {
let dialog = new JoinDialog({ transient_for: this });
dialog.show();
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]