[polari/wip/bastianilso/irc-url-parsing] Register and support opening irc URL schemes



commit 26a6f4047f1b37a9f94cdb5b78dc57af88d767f1
Author: Bastian Ilsø <bastianilso src gnome org>
Date:   Fri Jul 3 21:13:32 2015 +0200

    Register and support opening irc URL schemes
    
    The irc URL scheme typically refer a channel on some
    server. This patch register Polari as
    handler of the x-scheme-handler/irc mimetype. If Polari
    is the default handler, browsers can activate Polari
    via xdg-open/d-bus activation. Polari will attempt to
    parse the link and if it fails, it will emit a
    notification with an error.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=728593

 data/org.gnome.Polari.desktop.in |    1 +
 src/application.js               |   90 ++++++++++++++++++++++++++++++++++++--
 src/connections.js               |   34 ++++++++++++++-
 3 files changed, 120 insertions(+), 5 deletions(-)
---
diff --git a/data/org.gnome.Polari.desktop.in b/data/org.gnome.Polari.desktop.in
index 8aab491..f401f4c 100644
--- a/data/org.gnome.Polari.desktop.in
+++ b/data/org.gnome.Polari.desktop.in
@@ -5,6 +5,7 @@ Exec=polari
 TryExec=polari
 Icon=polari
 Type=Application
+MimeType=x-scheme-handler/irc;
 StartupNotify=true
 DBusActivatable=true
 Actions=connections;
diff --git a/src/application.js b/src/application.js
index 7262bfd..3126c8f 100644
--- a/src/application.js
+++ b/src/application.js
@@ -13,6 +13,7 @@ const MainWindow = imports.mainWindow;
 const PasteManager = imports.pasteManager;
 const Utils = imports.utils;
 
+const TP_CURRENT_TIME = GLib.MAXUINT32;
 
 const MAX_RETRIES = 3;
 
@@ -27,8 +28,7 @@ const Application = new Lang.Class({
 
     _init: function() {
         this.parent({ application_id: 'org.gnome.Polari' });
-
-        GLib.set_application_name('Polari');
+        this.set_flags(Gio.ApplicationFlags.HANDLES_OPEN);
         this._window = null;
         this._pendingRequests = {};
     },
@@ -47,11 +47,15 @@ const Application = new Lang.Class({
                 this._removeSavedChannelsForAccount(account);
             }));
 
+        this._accountsMonitor.connect('account-manager-prepared',
+                Lang.bind(this, this._parseArgs));
+
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
 
         this.pasteManager = new PasteManager.PasteManager();
         this.notificationQueue = new AppNotifications.NotificationQueue();
         this.commandOutputQueue = new AppNotifications.CommandOutputQueue();
+        this._accountsMonitor = AccountsMonitor.getDefault();
 
         let actionEntries = [
           { name: 'room-menu',
@@ -128,18 +132,96 @@ const Application = new Lang.Class({
     },
 
     vfunc_activate: function() {
+        this._showMainWindow();
+    },
+
+    vfunc_open: function(args) {
+        this._args = args;
+        //this._showMainWindow();
+        //this._window.window.hide();
+        this._parseArgs();
+
+    },
+
+    _parseArgs: function() {
+        let args =  this._args;
+        let accounts = this._accountsMonitor.dupAccounts();
+        if (!args || accounts.length == 0 || args.length != 1) {
+            log('didnt pass check!' + ' accounts: ' + accounts.length + ', args: ' + args)
+            return;
+        }
+        this._args = null;
+        let uriRegEx = /^(irc?:\/\/)([\da-z\.-]+):?(\d+)?\/(?:%23)?([\w \. \+-]*)/;
+        try {
+            var [, , server, port, room] = args[0].get_uri().match(uriRegEx);
+            log('server: ' + server);
+            log('room: ' + room);
+            log('port: ' + port);
+        } catch (e) {
+            log('hitting catch block, uri was invalid');
+            let notification = new Gio.Notification();
+            notification.set_title("Polari could not open the IRC link.");
+            notification.set_body("Unable to parse  \"" +
+                                  args[0].get_uri() + "\".");
+            this.send_notification('irc-link' + args[0], notification);
+            return;
+        }
+        this._showMainWindow();
+        let account = null;
+        log('looking through accounts..');
+        for (let i = 0; i < accounts.length; i++) {
+            let params = accounts[i].dup_parameters_vardict().deep_unpack();
+            for (let p in params)
+                params[p] = params[p].deep_unpack();
+            log('checking ' + server + ' vs ' + params.server);
+            if (server == params.server) {
+                log('match!');
+                account = accounts[i];
+                break;
+            }
+        }
+
+        if (account && room) {
+            log('got account and room, joining ' + room);
+            let action = this.lookup_action('join-room');
+            action.activate(GLib.Variant.new('(ssu)',
+                                             [ account.get_object_path(),
+                                               '#' + room,
+                                               TP_CURRENT_TIME ]));
+            return;
+        }
+
+        log('no account match, opening details dialog..');
+        let detailsDialog = new Connections.ConnectionDetailsDialog(null);
+        detailsDialog.server_entry = port ? server + ':' + port : server;
+        detailsDialog.room = room;
+        detailsDialog.widget.transient_for = this._window.window;
+        detailsDialog.nick_entry.grab_focus();
+        detailsDialog.widget.show();
+        detailsDialog.widget.connect('response',
+            Lang.bind(this, function(widget) {
+                widget.destroy();
+            }));
+    },
+
+    _showMainWindow: function() {
+        log('checking if window exists');
         if (!this._window) {
+            log('creates main window');
             this._window = new MainWindow.MainWindow(this);
+            log('connect to destroy signal');
             this._window.window.connect('destroy', Lang.bind(this,
                 function() {
                     for (let id in this._pendingRequests)
                         this._pendingRequests[id].cancellable.cancel();
                     this.emitJS('prepare-shutdown');
             }));
+            log('shows the window');
             this._window.window.show_all();
-
+            log('lateInit chatroommanager');
             this._chatroomManager.lateInit();
         }
+            log('presents window');
         this._window.window.present();
     },
 
@@ -302,11 +384,11 @@ const Application = new Lang.Class({
 
         try {
             req.ensure_channel_finish(res);
-
             if (requestData.targetHandleType == Tp.HandleType.ROOM)
                 this._addSavedChannel(account, requestData.targetId);
         } catch (e if e.matches(Tp.Error, Tp.Error.DISCONNECTED)) {
             let error = account.connection_error;
+            log(account.connection_error);
             if (error == ConnectionError.ALREADY_CONNECTED &&
                 requestData.retry++ < MAX_RETRIES) {
                     this._retryRequest(requestData);
diff --git a/src/connections.js b/src/connections.js
index b7fc45c..e17d4e9 100644
--- a/src/connections.js
+++ b/src/connections.js
@@ -9,6 +9,8 @@ const AccountsMonitor = imports.accountsMonitor;
 const Lang = imports.lang;
 const Signals = imports.signals;
 
+const TP_CURRENT_TIME = GLib.MAXUINT32;
+
 const ConnectionsDialog = new Lang.Class({
     Name: 'ConnectionsDialog',
 
@@ -254,6 +256,14 @@ const ConnectionDetails = new Lang.Class({
                this._nickEntry.get_text_length() > 0;
     },
 
+    get server_entry() {
+        return this._serverEntry;
+    },
+
+    get nick_entry() {
+        return this._nickEntry;
+    },
+
     save: function() {
         if (!this.can_confirm)
             return;
@@ -280,7 +290,16 @@ const ConnectionDetails = new Lang.Class({
 
         req.create_account_async(Lang.bind(this,
             function(r, res) {
-                req.create_account_finish(res); // TODO: Check for errors
+                let account = req.create_account_finish(res); // TODO: Check for errors
+                if (this.room) {
+                    log('room assigned, joining..');
+                    let app = Gio.Application.get_default();
+                    let action = app.lookup_action('join-room');
+                    action.activate(GLib.Variant.new('(ssu)',
+                                                     [ account.get_object_path(),
+                                                       '#' + this.room,
+                                                       TP_CURRENT_TIME ]));
+                }
             }));
     },
 
@@ -349,5 +368,18 @@ const ConnectionDetailsDialog = new Lang.Class({
                                     this._confirmButton, 'sensitive',
                                     GObject.BindingFlags.SYNC_CREATE);
         this.widget.get_content_area().add(this._details);
+    },
+    
+    set server_entry(server) {
+        let entry = this._details.server_entry;
+        entry.text = server;
+    },
+
+    set room(room) {
+        this._details.room = room;
+    },
+
+    get nick_entry() {
+        return this._details.nick_entry;
     }
 });


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]