[polari/wip/fmuellner/es6-classes: 7/7] Port GObject classes to JS6 classes



commit 7b97ce6eec1808d768e62b929d2fe9cefa097f5f
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Oct 26 20:15:36 2017 +0200

    Port GObject classes to JS6 classes
    
    GJS added API for defining GObject classes with ES6 class syntax
    last cycle, use it to port the remaining Lang.Class classes to
    the new syntax.
    
    Fixes https://gitlab.gnome.org/GNOME/polari/issues/14

 src/appNotifications.js  |  91 +++++++++++-------------
 src/application.js       |  95 +++++++++++++------------
 src/chatView.js          | 176 ++++++++++++++++++++++-------------------------
 src/connections.js       |  84 ++++++++++------------
 src/emojiPicker.js       |  32 ++++-----
 src/entryArea.js         |  65 ++++++++---------
 src/initialSetup.js      |  21 +++---
 src/joinDialog.js        |  28 ++++----
 src/mainWindow.js        |  66 +++++++++---------
 src/pasteManager.js      |  15 ++--
 src/polari-accounts.in   |  14 ++--
 src/roomList.js          | 102 +++++++++++++--------------
 src/roomStack.js         |  54 +++++++--------
 src/serverRoomManager.js |  30 ++++----
 src/telepathyClient.js   |  68 +++++++++---------
 src/userList.js          | 144 ++++++++++++++++++--------------------
 src/userTracker.js       |  65 +++++++++--------
 17 files changed, 535 insertions(+), 615 deletions(-)
---
diff --git a/src/appNotifications.js b/src/appNotifications.js
index 455feda..c7edff3 100644
--- a/src/appNotifications.js
+++ b/src/appNotifications.js
@@ -1,4 +1,5 @@
 const Gio = imports.gi.Gio;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Pango = imports.gi.Pango;
 const Tp = imports.gi.TelepathyGLib;
@@ -9,21 +10,21 @@ const Mainloop = imports.mainloop;
 const TIMEOUT = 7;
 const COMMAND_OUTPUT_REVEAL_TIME = 3;
 
-var AppNotification = new Lang.Class({
-    Name: 'AppNotification',
-    Abstract: true,
-    Extends: Gtk.Revealer,
-
+var AppNotification = GObject.registerClass(
+class AppNotification extends Gtk.Revealer {
     _init() {
-        this.parent({ reveal_child: true,
+        if (this.constructor.name == 'AppNotification')
+            throw new Error('Cannot instantiate abstract class AppNotification');
+
+        super._init({ reveal_child: true,
                       transition_type: Gtk.RevealerTransitionType.SLIDE_DOWN });
         this.connect('notify::child-revealed',
                      Lang.bind(this, this._onChildRevealed));
-    },
+    }
 
     close() {
         this.reveal_child = false;
-    },
+    }
 
     _onChildRevealed() {
         if (!this.child_revealed)
@@ -31,12 +32,10 @@ var AppNotification = new Lang.Class({
     }
 });
 
-var MessageNotification = new Lang.Class({
-    Name: 'MessageNotification',
-    Extends: AppNotification,
-
+var MessageNotification = GObject.registerClass(
+class MessageNotification extends AppNotification {
     _init(label, iconName) {
-        this.parent();
+        super._init();
 
         Mainloop.timeout_add_seconds(TIMEOUT, Lang.bind(this, this.close));
 
@@ -55,7 +54,7 @@ var MessageNotification = new Lang.Class({
 
         this.add(this._box);
         this.show_all();
-    },
+    }
 
 
     addButton(label, callback) {
@@ -70,13 +69,11 @@ var MessageNotification = new Lang.Class({
     }
 });
 
-var UndoNotification = new Lang.Class({
-    Name: 'UndoNotification',
-    Extends: MessageNotification,
-    Signals: { closed: {}, undo: {} },
-
+var UndoNotification = GObject.registerClass({
+    Signals: { closed: {}, undo: {} }
+}, class UndoNotification extends MessageNotification {
     _init(label) {
-        this.parent(label);
+        super._init(label);
 
         this._undo = false;
 
@@ -87,12 +84,12 @@ var UndoNotification = new Lang.Class({
         this._app = Gio.Application.get_default();
         this._shutdownId = this._app.connect('prepare-shutdown',
                                              Lang.bind(this, this.close));
-    },
+    }
 
     close() {
         this.emit(this._undo ? 'undo' : 'closed');
-        this.parent();
-    },
+        super.close();
+    }
 
     _onDestroy() {
         if (this._shutdownId)
@@ -101,13 +98,13 @@ var UndoNotification = new Lang.Class({
     }
 });
 
-var CommandOutputNotification = new Lang.Class({
-    Name: 'CommandOutputNotification',
-    Extends: AppNotification,
-    Abstract: true,
-
+var CommandOutputNotification = GObject.registerClass(
+class CommandOutputNotification extends AppNotification {
     _init() {
-        this.parent();
+        if (this.constructor.name == 'CommandOutputNotification')
+            throw new Error('Cannot instantiate abstract class CommandOutputNotification');
+
+        super._init();
 
         this.transition_type = Gtk.RevealerTransitionType.SLIDE_UP;
         Mainloop.timeout_add_seconds(COMMAND_OUTPUT_REVEAL_TIME,
@@ -115,12 +112,10 @@ var CommandOutputNotification = new Lang.Class({
     }
 });
 
-var SimpleOutput = new Lang.Class({
-    Name: 'SimpleOutput',
-    Extends: CommandOutputNotification,
-
+var SimpleOutput = GObject.registerClass(
+class SimpleOutput extends CommandOutputNotification {
     _init(text) {
-        this.parent();
+        super._init();
 
         let label = new Gtk.Label({ label: text,
                                     vexpand: true,
@@ -131,12 +126,10 @@ var SimpleOutput = new Lang.Class({
     }
 });
 
-var GridOutput = new Lang.Class({
-    Name: 'GridOutput',
-    Extends: CommandOutputNotification,
-
+var GridOutput = GObject.registerClass(
+class GridOutput extends CommandOutputNotification {
     _init(header, items) {
-        this.parent();
+        super._init();
 
         let numItems = items.length;
         let numCols = Math.min(numItems, 4);
@@ -163,12 +156,10 @@ var GridOutput = new Lang.Class({
     }
 });
 
-var NotificationQueue = new Lang.Class({
-    Name: 'NotificationQueue',
-    Extends: Gtk.Frame,
-
+var NotificationQueue = GObject.registerClass(
+class NotificationQueue extends Gtk.Frame {
     _init() {
-        this.parent({ valign: Gtk.Align.START,
+        super._init({ valign: Gtk.Align.START,
                       halign: Gtk.Align.CENTER,
                       margin_start: 24, margin_end: 24,
                       no_show_all: true });
@@ -177,14 +168,14 @@ var NotificationQueue = new Lang.Class({
         this._grid = new Gtk.Grid({ orientation: Gtk.Orientation.VERTICAL,
                                     row_spacing: 6, visible: true });
         this.add(this._grid);
-    },
+    }
 
     addNotification(notification) {
         this._grid.add(notification);
 
         notification.connect('destroy', Lang.bind(this, this._onChildDestroy));
         this.show();
-    },
+    }
 
     _onChildDestroy() {
         if (this._grid.get_children().length == 0)
@@ -192,12 +183,10 @@ var NotificationQueue = new Lang.Class({
     }
 });
 
-var CommandOutputQueue = new Lang.Class({
-    Name: 'CommandOutputQueue',
-    Extends: NotificationQueue,
-
+var CommandOutputQueue = GObject.registerClass(
+class CommandOutputQueue extends NotificationQueue {
     _init() {
-        this.parent();
+        super._init();
 
         this.valign = Gtk.Align.END;
         this.get_style_context().add_class('irc-feedback');
diff --git a/src/application.js b/src/application.js
index 894a7e4..f509061 100644
--- a/src/application.js
+++ b/src/application.js
@@ -1,6 +1,7 @@
 const Gdk = imports.gi.Gdk;
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 const Polari = imports.gi.Polari;
 const Tp = imports.gi.TelepathyGLib;
@@ -26,14 +27,12 @@ const IRC_SCHEMA_REGEX = /^(irc?:\/\/)([\da-z\.-]+):?(\d+)?\/(?:%23)?([\w\.\+-]+
 const AUTOSTART_DIR = GLib.get_user_config_dir() + '/autostart';
 const AUTOSTART_FILE = '/org.gnome.Polari.Autostart.desktop';
 
-var Application = new Lang.Class({
-    Name: 'Application',
-    Extends: Gtk.Application,
+var Application = GObject.registerClass({
     Signals: { 'prepare-shutdown': {},
                'room-focus-changed': {} },
-
+}, class Application extends Gtk.Application {
     _init() {
-        this.parent({ application_id: 'org.gnome.Polari',
+        super._init({ application_id: 'org.gnome.Polari',
                       flags: Gio.ApplicationFlags.HANDLES_OPEN });
 
         GLib.set_application_name('Polari');
@@ -71,13 +70,13 @@ var Application = new Lang.Class({
 
             return -1;
         });
-    },
+    }
 
     isRoomFocused(room) {
         return this.active_window &&
                this.active_window['is-active'] &&
                this.active_window.active_room == room;
-    },
+    }
 
     // Small wrapper to mark user-requested nick changes
     setAccountNick(account, nick) {
@@ -85,7 +84,7 @@ var Application = new Lang.Class({
             account.set_nickname_finish(res);
         });
         this._untrackNominalNick(account);
-    },
+    }
 
     _checkService(conn, name, opath, iface) {
         let flags = Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES |
@@ -98,7 +97,7 @@ var Application = new Lang.Class({
         } catch(e) {}
 
         return proxy != null && proxy.get_name_owner() != null;
-    },
+    }
 
     _ensureService(conn, name, opath, iface, command) {
         debug('Trying to ensure service %s'.format(name));
@@ -116,7 +115,7 @@ var Application = new Lang.Class({
         } catch(e) {
             log('Failed to launch %s: %s'.format(command, e.message));
         }
-    },
+    }
 
     vfunc_dbus_register(conn, path) {
         if (!Utils.isFlatpakSandbox())
@@ -139,16 +138,16 @@ var Application = new Lang.Class({
                             Tp.IFACE_CLIENT,
                             '/app/libexec/telepathy-logger');
         return true;
-    },
+    }
 
     vfunc_dbus_unregister(conn, path) {
         for (let proc of this._demons)
             proc.force_exit();
         this._demons = [];
-    },
+    }
 
     vfunc_startup() {
-        this.parent();
+        super.vfunc_startup();
 
         let actionEntries = [
           { name: 'show-join-dialog',
@@ -279,7 +278,7 @@ var Application = new Lang.Class({
         Gtk.StyleContext.add_provider_for_screen(Gdk.Screen.get_default(),
                                                  provider,
                                                  Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
-    },
+    }
 
     vfunc_activate() {
         this.activate_action('start-client', null);
@@ -307,10 +306,10 @@ var Application = new Lang.Class({
         }
 
         this.active_window.present();
-    },
+    }
 
     vfunc_window_added(window) {
-        this.parent(window);
+        super.vfunc_window_added(window);
 
         if (!(window instanceof MainWindow.MainWindow))
             return;
@@ -324,7 +323,7 @@ var Application = new Lang.Class({
         window.connect('active-room-state-changed',
                        Lang.bind(this, this._updateUserListAction));
         this._updateUserListAction();
-    },
+    }
 
     vfunc_open(files) {
         this.activate();
@@ -335,7 +334,7 @@ var Application = new Lang.Class({
         this._accountsMonitor.prepare(() => {
             this._openURIs(uris, time);
         });
-    },
+    }
 
     _openURIs(uris, time) {
         let map = {};
@@ -371,7 +370,7 @@ var Application = new Lang.Class({
                                              '#' + room, time]));
                 });
         });
-    },
+    }
 
     _parseURI(uri) {
         let server, port, room;
@@ -387,7 +386,7 @@ var Application = new Lang.Class({
         }
 
         return [success, server, port, room];
-    },
+    }
 
     _createAccount(id, server, port, callback) {
         let params, name;
@@ -421,7 +420,7 @@ var Application = new Lang.Class({
             let account = req.create_account_finish(res);
             callback(account);
         });
-    },
+    }
 
     _touchFile(file) {
         try {
@@ -432,7 +431,7 @@ var Application = new Lang.Class({
 
         let stream = file.create(0, null);
         stream.close(null);
-    },
+    }
 
     _needsInitialSetup() {
         if (GLib.getenv('POLARI_FORCE_INITIAL_SETUP')) {
@@ -452,13 +451,13 @@ var Application = new Lang.Class({
 
         let savedRooms = this._settings.get_value('saved-channel-list');
         return savedRooms.n_children() == 0;
-    },
+    }
 
     _updateUserListAction() {
         let room = this.active_window.active_room;
         let action = this.lookup_action('user-list');
         action.enabled = room && room.type == Tp.HandleType.ROOM && room.channel;
-    },
+    }
 
     _userListCreateHook(action) {
         action.connect('notify::enabled', () => {
@@ -466,28 +465,28 @@ var Application = new Lang.Class({
                 action.change_state(GLib.Variant.new('b', false));
         });
         action.enabled = false;
-    },
+    }
 
     _onShowJoinDialog() {
         this.active_window.showJoinRoomDialog();
-    },
+    }
 
     _maybePresent(time) {
         let [present, ] = Tp.user_action_time_should_present(time);
 
         if (!this.active_window || present)
             this.activate();
-    },
+    }
 
     _onJoinRoom(action, parameter) {
         let [accountPath, channelName, time] = parameter.deep_unpack();
         this._maybePresent(time);
-    },
+    }
 
     _onMessageUser(action, parameter) {
         let [accountPath, contactName, message, time] = parameter.deep_unpack();
         this._maybePresent(time);
-    },
+    }
 
     _trackNominalNick(account) {
         if (this._nickTrackData.has(account))
@@ -512,7 +511,7 @@ var Application = new Lang.Class({
                 });
             });
         this._nickTrackData.set(account, { tracker, contactsChangedId });
-    },
+    }
 
     _untrackNominalNick(account) {
         let data = this._nickTrackData.get(account);
@@ -521,7 +520,7 @@ var Application = new Lang.Class({
 
         data.tracker.disconnect(data.contactsChangedId);
         this._nickTrackData.delete(account);
-    },
+    }
 
     _ensureRetryData(account) {
         let data = this._retryData.get(account.object_path);
@@ -545,19 +544,19 @@ var Application = new Lang.Class({
         };
         this._retryData.set(account.object_path, data);
         return data;
-    },
+    }
 
     _getTrimmedAccountName(account) {
         let params = Connections.getAccountParams(account);
         return params.account.replace(/_+$/, '');
-    },
+    }
 
     _restoreAccountName(account) {
         let accountName = this._getTrimmedAccountName(account);
         let params = { account: new GLib.Variant('s', accountName) };
         let asv = new GLib.Variant('a{sv}', params);
         account.update_parameters_vardict_async(asv, [], null);
-    },
+    }
 
     _retryWithParams(account, params) {
         account.update_parameters_vardict_async(params, [], () => {
@@ -565,7 +564,7 @@ var Application = new Lang.Class({
             let msg = account.requested_status_message;
             account.request_presence_async(presence, 'available', msg, null);
         });
-    },
+    }
 
     _retryNickRequest(account) {
         let retryData = this._ensureRetryData(account);
@@ -582,7 +581,7 @@ var Application = new Lang.Class({
         let params = { account: new GLib.Variant('s', nick + '_') };
         this._retryWithParams(account, new GLib.Variant('a{sv}', params));
         return true;
-    },
+    }
 
     _retryServerRequest(account) {
         let retryData = this._ensureRetryData(account);
@@ -597,7 +596,7 @@ var Application = new Lang.Class({
                        'use-ssl': new GLib.Variant('b', server.ssl) };
         this._retryWithParams(account, new GLib.Variant('a{sv}', params));
         return true;
-    },
+    }
 
     _onAccountStatusChanged(mon, account) {
         let status = account.connection_status;
@@ -630,7 +629,7 @@ var Application = new Lang.Class({
         }
 
         this._restoreAccountName(account);
-    },
+    }
 
     _onLeaveCurrentRoom() {
         let room = this.active_window.active_room;
@@ -638,7 +637,7 @@ var Application = new Lang.Class({
             return;
         let action = this.lookup_action('leave-room');
         action.activate(GLib.Variant.new('(ss)', [room.id, '']));
-    },
+    }
 
     _onConnectAccount(action, parameter) {
         let accountPath = parameter.deep_unpack();
@@ -646,12 +645,12 @@ var Application = new Lang.Class({
         if (account)
             this._restoreAccountName(account);
         this._retryData.delete(accountPath);
-    },
+    }
 
     _onToggleAction(action) {
         let state = action.get_state();
         action.change_state(GLib.Variant.new('b', !state.get_boolean()));
-    },
+    }
 
     _onRemoveConnection(action, parameter){
         let accountPath = parameter.deep_unpack();
@@ -672,7 +671,7 @@ var Application = new Lang.Class({
                 });
             });
         });
-    },
+    }
 
     _onEditConnection(action, parameter) {
         let accountPath = parameter.deep_unpack();
@@ -683,7 +682,7 @@ var Application = new Lang.Class({
             w.destroy();
         });
         dialog.show();
-    },
+    }
 
     _createLink(file, target) {
         try {
@@ -693,7 +692,7 @@ var Application = new Lang.Class({
         }
 
         file.make_symbolic_link(target, null);
-    },
+    }
 
     _onRunInBackgroundChanged() {
         let file = Gio.File.new_for_path(AUTOSTART_DIR + AUTOSTART_FILE);
@@ -712,7 +711,7 @@ var Application = new Lang.Class({
                 if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
                     log('Failed to remove autostart link: ' + e.message);
             }
-    },
+    }
 
     _onStartClient() {
         if (this._telepathyClient)
@@ -724,11 +723,11 @@ var Application = new Lang.Class({
             uniquify_name: false
         };
         this._telepathyClient = new TelepathyClient.TelepathyClient(params);
-    },
+    }
 
     _onShowHelp() {
         Utils.openURL('help:org.gnome.Polari', Gtk.get_current_event_time());
-    },
+    }
 
     _onShowAbout() {
         if (this._aboutDialog) {
@@ -776,7 +775,7 @@ var Application = new Lang.Class({
             this._aboutDialog.destroy();
             this._aboutDialog = null;
         });
-    },
+    }
 
     _onQuit() {
         if (this._windowRemovedId)
diff --git a/src/chatView.js b/src/chatView.js
index 8b21f18..b9c5b91 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -47,20 +47,18 @@ function _getColor(context) {
 
 // Workaround for GtkTextView growing horizontally over time when
 // added to a GtkScrolledWindow with horizontal scrolling disabled
-var TextView = new Lang.Class({
-    Name: 'TextView',
-    Extends: Gtk.TextView,
-
+const TextView = GObject.registerClass(
+class TextView extends Gtk.TextView {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this.buffer.connect('mark-set', Lang.bind(this, this._onMarkSet));
         this.connect('screen-changed', Lang.bind(this, this._updateLayout));
-    },
+    }
 
     vfunc_get_preferred_width() {
         return [1, 1];
-    },
+    }
 
     vfunc_style_updated() {
         let context = this.get_style_context();
@@ -70,11 +68,11 @@ var TextView = new Lang.Class({
         this._dimColor = _getColor(context);
         context.restore();
 
-        this.parent();
-    },
+        super.vfunc_style_updated();
+    }
 
     vfunc_draw(cr) {
-        this.parent(cr);
+        super.vfunc_draw(cr);
 
         let mark = this.buffer.get_mark('indicator-line');
         if (!mark) {
@@ -130,12 +128,12 @@ var TextView = new Lang.Class({
         cr.$dispose();
 
         return Gdk.EVENT_PROPAGATE;
-    },
+    }
 
     _onMarkSet(buffer, iter, mark) {
         if (mark.name == 'indicator-line')
             this.queue_draw();
-    },
+    }
 
     _updateLayout() {
         this._layout = this.create_pango_layout(null);
@@ -143,9 +141,7 @@ var TextView = new Lang.Class({
     }
 });
 
-var ButtonTag = new Lang.Class({
-    Name: 'ButtonTag',
-    Extends: Gtk.TextTag,
+var ButtonTag = GObject.registerClass({
     Properties: {
         'hover': GObject.ParamSpec.boolean('hover',
                                            'hover',
@@ -168,17 +164,17 @@ var ButtonTag = new Lang.Class({
         },
         'clicked': { }
     },
-
+}, class ButtonTag extends Gtk.TextTag {
     _init(params) {
         this._hover = false;
         this._pressed = false;
 
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     get hover() {
         return this._hover;
-    },
+    }
 
     set hover(hover) {
         if (this._hover == hover)
@@ -186,19 +182,19 @@ var ButtonTag = new Lang.Class({
 
         this._hover = hover;
         this.notify('hover');
-    },
+    }
 
     on_notify(pspec) {
         if (pspec.name == 'hover' && !this.hover)
             this._pressed = false;
-    },
+    }
 
     'on_button-press-event'(event) {
         let [, button] = event.get_button();
         this._pressed = button == Gdk.BUTTON_PRIMARY;
 
         return Gdk.EVENT_STOP;
-    },
+    }
 
     'on_button-release-event'(event) {
         let [, button] = event.get_button();
@@ -208,7 +204,7 @@ var ButtonTag = new Lang.Class({
         this._pressed = false;
         this.emit('clicked');
         return Gdk.EVENT_STOP;
-    },
+    }
 
     vfunc_event(object, event, iter) {
         let type = event.get_event_type();
@@ -226,9 +222,7 @@ var ButtonTag = new Lang.Class({
     }
 });
 
-var HoverFilterTag = new Lang.Class({
-    Name: 'HoverFilterTag',
-    Extends: ButtonTag,
+var HoverFilterTag = GObject.registerClass({
     Properties: {
         'filtered-tag': GObject.ParamSpec.object('filtered-tag',
                                                  'filtered-tag',
@@ -241,16 +235,16 @@ var HoverFilterTag = new Lang.Class({
                                                   'hover-opacity',
                                                   GObject.ParamFlags.READWRITE,
                                                   0.0, 1.0, 1.0)
-    },
-
+    }
+}, class HoverFilterTag extends ButtonTag {
     _init(params) {
         this._filteredTag = null;
         this._hoverOpacity = 1.;
 
-        this.parent(params);
+        super._init(params);
 
         this.connect('notify::hover', () => { this._updateColor(); });
-    },
+    }
 
     _updateColor() {
         if (!this._filteredTag)
@@ -260,7 +254,7 @@ var HoverFilterTag = new Lang.Class({
         if (this.hover)
             color.alpha *= this._hoverOpacity;
         this.foreground_rgba = color;
-    },
+    }
 
     set filtered_tag(value) {
         this._filteredTag = value;
@@ -270,11 +264,11 @@ var HoverFilterTag = new Lang.Class({
             this._updateColor();
         });
         this._updateColor();
-    },
+    }
 
     get filtered_tag() {
         return this._filteredTag;
-    },
+    }
 
     set hover_opacity(value) {
         if (this._hoverOpacity == value)
@@ -284,16 +278,14 @@ var HoverFilterTag = new Lang.Class({
 
         if (this.hover)
             this._updateColor();
-    },
+    }
 
     get hover_opacity() {
         return this._hoverOpacity;
     }
 });
 
-var ChatView = new Lang.Class({
-    Name: 'ChatView',
-    Extends: Gtk.ScrolledWindow,
+var ChatView = GObject.registerClass({
     Implements: [PasteManager.DropTargetIface],
     Properties: {
         'can-drop': GObject.ParamSpec.override('can-drop', PasteManager.DropTargetIface),
@@ -302,10 +294,10 @@ var ChatView = new Lang.Class({
                                                  'max-nick-chars',
                                                  GObject.ParamFlags.READABLE,
                                                  0, GLib.MAXUINT32, 0)
-    },
-
+    }
+}, class ChatView extends Gtk.ScrolledWindow {
     _init(room) {
-        this.parent({ hscrollbar_policy: Gtk.PolicyType.NEVER, vexpand: true });
+        super._init({ hscrollbar_policy: Gtk.PolicyType.NEVER, vexpand: true });
 
         this.get_style_context().add_class('polari-chat-view');
 
@@ -427,7 +419,7 @@ var ChatView = new Lang.Class({
             this._userTracker.unwatchRoomStatus(this._room, this._nickStatusChangedId);
             this._userTracker = null;
         });
-    },
+    }
 
     _createTags() {
         let buffer = this._view.get_buffer();
@@ -462,7 +454,7 @@ var ChatView = new Lang.Class({
             justification: Gtk.Justification.CENTER }
         ];
         tags.forEach(tagProps => { tagTable.add(new Gtk.TextTag(tagProps)); });
-    },
+    }
 
     _onStyleUpdated() {
         let context = this.get_style_context();
@@ -528,7 +520,7 @@ var ChatView = new Lang.Class({
             let status = this._userTracker.getNickRoomStatus(nickname, this._room);
             this._updateNickTag(tag, status);
         });
-    },
+    }
 
     _onDestroy() {
         for (let i = 0; i < this._channelSignals.length; i++)
@@ -545,7 +537,7 @@ var ChatView = new Lang.Class({
 
         this._logWalker.run_dispose();
         this._logWalker = null;
-    },
+    }
 
     _onLogEventsReady(lw, res) {
         this._hideLoadingIndicator();
@@ -555,7 +547,7 @@ var ChatView = new Lang.Class({
         let messages = events.map(e => this._createMessage(e));
         this._pendingLogs = messages.concat(this._pendingLogs);
         this._insertPendingLogs();
-    },
+    }
 
     _createMessage(source) {
         if (source instanceof Tp.Message) {
@@ -575,7 +567,7 @@ var ChatView = new Lang.Class({
         }
 
         throw new Error('Cannot create message from source ' + source);
-    },
+    }
 
     _getReadyLogs() {
         if (this._logWalker.is_end())
@@ -589,7 +581,7 @@ var ChatView = new Lang.Class({
                 this._pendingLogs[i].messageType != type)
                 return this._pendingLogs.splice(i);
         return [];
-    },
+    }
 
     _appendInitialPending(logs) {
         let pending = this._initialPending.splice(0);
@@ -606,7 +598,7 @@ var ChatView = new Lang.Class({
         // Remove entries that are also in pending (if any), then
         // add the entries from pending
         logs.splice.apply(logs, [pos, numLogs, ...pending]);
-    },
+    }
 
     _insertPendingLogs() {
         let pending = this._getReadyLogs();
@@ -637,15 +629,15 @@ var ChatView = new Lang.Class({
 
         if (!this._channel)
             return;
-    },
+    }
 
     get max_nick_chars() {
         return this._maxNickChars;
-    },
+    }
 
     get can_drop() {
         return this._channel != null;
-    },
+    }
 
     _updateMaxNickChars(length) {
         if (length <= this._maxNickChars)
@@ -654,7 +646,7 @@ var ChatView = new Lang.Class({
         this._maxNickChars = length;
         this.notify('max-nick-chars');
         this._updateIndent();
-    },
+    }
 
     _updateIndent() {
         let context = this._view.get_pango_context();
@@ -670,7 +662,7 @@ var ChatView = new Lang.Class({
         this._view.tabs = tabs;
         this._view.indent = -totalWidth;
         this._view.left_margin = MARGIN + totalWidth;
-    },
+    }
 
     _updateScroll() {
         if (!this._autoscroll)
@@ -684,7 +676,7 @@ var ChatView = new Lang.Class({
             let mark = [...this._pending.values()].shift();
             this._view.scroll_mark_onscreen(mark);
         }
-    },
+    }
 
     _onScroll(w, event) {
         let [hasDir, dir] = event.get_scroll_direction();
@@ -698,7 +690,7 @@ var ChatView = new Lang.Class({
         this._autoscroll = false;
 
         return this._fetchBacklog();
-    },
+    }
 
     _onKeyPress(w, event) {
         let [, keyval] = event.get_keyval();
@@ -726,7 +718,7 @@ var ChatView = new Lang.Class({
         this._autoscroll = false;
 
         return this._fetchBacklog();
-    },
+    }
 
     _fetchBacklog() {
         if (this.vadjustment.value != 0 ||
@@ -745,7 +737,7 @@ var ChatView = new Lang.Class({
             return GLib.SOURCE_REMOVE;
         });
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _onValueChanged() {
         if (this._valueChangedId)
@@ -756,14 +748,14 @@ var ChatView = new Lang.Class({
             this._valueChangedId = 0;
             return GLib.SOURCE_REMOVE;
         });
-    },
+    }
 
     _pendingMessageRemoved(channel, message) {
         let [id, valid] = message.get_pending_message_id();
         if (!valid || !this._pending.has(id))
             return;
         this._removePendingMark(id);
-    },
+    }
 
     _removePendingMark(id) {
         let mark = this._pending.get(id);
@@ -772,7 +764,7 @@ var ChatView = new Lang.Class({
             this._autoscroll = true;
         this._view.buffer.delete_mark(mark);
         this._pending.delete(id);
-    },
+    }
 
     _showUrlContextMenu(url, button, time) {
         let menu = new Gtk.Menu();
@@ -792,7 +784,7 @@ var ChatView = new Lang.Class({
 
         menu.show_all();
         menu.popup(null, null, null, button, time);
-    },
+    }
 
     _handleButtonTagsHover(view, event) {
         let [, eventX, eventY] = event.get_coords();
@@ -822,7 +814,7 @@ var ChatView = new Lang.Class({
         this._hoveredButtonTags = hoveredButtonTags;
 
         return Gdk.EVENT_PROPAGATE;
-    },
+    }
 
     _showLoadingIndicator() {
         let indicator = new Gtk.Image({ icon_name: 'content-loading-symbolic',
@@ -838,7 +830,7 @@ var ChatView = new Lang.Class({
         let start = buffer.get_start_iter();
         buffer.remove_all_tags(start, iter);
         buffer.apply_tag(this._lookupTag('loading'), start, iter);
-    },
+    }
 
     _hideLoadingIndicator() {
         let buffer = this._view.buffer;
@@ -849,7 +841,7 @@ var ChatView = new Lang.Class({
 
         iter.forward_line();
         buffer.delete(buffer.get_start_iter(), iter);
-    },
+    }
 
     _setIndicatorMark(iter) {
         let lineStart = iter.copy();
@@ -870,7 +862,7 @@ var ChatView = new Lang.Class({
         buffer.apply_tag(this._lookupTag('indicator-line'), start, end);
 
         this._needsIndicator = false;
-    },
+    }
 
     _checkMessages() {
         if (!this._app.isRoomFocused(this._room) || !this._channel)
@@ -896,17 +888,17 @@ var ChatView = new Lang.Class({
             if (rect.y <= iterRect.y && rect.y + rect.height > iterRect.y)
                 this._channel.ack_message_async(pending[i], null);
         }
-    },
+    }
 
     _getNickTagName(nick) {
         return NICKTAG_PREFIX + Polari.util_get_basenick(nick);
-    },
+    }
 
     _getNickFromTagName(tagName) {
         if (tagName.startsWith(NICKTAG_PREFIX))
             return tagName.replace(NICKTAG_PREFIX, '');
         return null;
-    },
+    }
 
     _onChannelChanged() {
         if (this._channel == this._room.channel)
@@ -948,19 +940,19 @@ var ChatView = new Lang.Class({
 
         let pending = this._channel.dup_pending_messages();
         this._initialPending = pending.map(p => this._createMessage(p));
-    },
+    }
 
     _onMemberRenamed(room, oldMember, newMember) {
         let text = _("%s is now known as %s").format(oldMember.alias, newMember.alias);
         this._insertStatus(text, oldMember.alias, 'renamed');
-    },
+    }
 
     _onMemberDisconnected(room, member, message) {
         let text = _("%s has disconnected").format(member.alias);
         if (message)
             text += ' (%s)'.format(message);
         this._insertStatus(text, member.alias, 'left');
-    },
+    }
 
     _onMemberKicked(room, member, actor) {
         let message =
@@ -968,7 +960,7 @@ var ChatView = new Lang.Class({
                                                          actor.alias)
                   : _("%s has been kicked").format(member.alias);
         this._insertStatus(message, member.alias, 'left');
-    },
+    }
 
     _onMemberBanned(room, member, actor) {
         let message =
@@ -976,12 +968,12 @@ var ChatView = new Lang.Class({
                                                          actor.alias)
                   : _("%s has been banned").format(member.alias)
         this._insertStatus(message, member.alias, 'left');
-    },
+    }
 
     _onMemberJoined(room, member) {
         let text = _("%s joined").format(member.alias);
         this._insertStatus(text, member.alias, 'joined');
-    },
+    }
 
     _onMemberLeft(room, member, message) {
         let text = _("%s left").format(member.alias);
@@ -990,7 +982,7 @@ var ChatView = new Lang.Class({
             text += ' (%s)'.format(message);
 
         this._insertStatus(text, member.alias, 'left');
-    },
+    }
 
     _onMessageReceived(channel, tpMessage) {
         this._insertTpMessage(tpMessage);
@@ -1000,12 +992,12 @@ var ChatView = new Lang.Class({
         if (!nickTag)
            return;
         nickTag._lastActivity = GLib.get_monotonic_time();
-    },
+    }
 
     _onMessageSent(channel, tpMessage) {
         this._insertTpMessage(tpMessage);
         this._resetStatusCompressed();
-    },
+    }
 
     _resetStatusCompressed() {
         let markStart = this._view.buffer.get_mark('idle-status-start');
@@ -1015,7 +1007,7 @@ var ChatView = new Lang.Class({
         this._view.buffer.delete_mark(markStart);
         this._statusCount =  { left: 0, joined: 0, total: 0 };
         this._state.lastStatusGroup++;
-    },
+    }
 
     _shouldShowStatus(nick) {
         let nickTag = this._lookupTag('nick' + nick);
@@ -1025,7 +1017,7 @@ var ChatView = new Lang.Class({
 
         let time = GLib.get_monotonic_time();
         return (time - nickTag._lastActivity) / (1000 * 1000) < INACTIVITY_THRESHOLD;
-    },
+    }
 
     _updateStatusHeader() {
         let buffer = this._view.buffer;
@@ -1091,7 +1083,7 @@ var ChatView = new Lang.Class({
         this._insertWithTags(iter, baseDir == Pango.Direction.LTR ? '\u25B6' : '\u25C0',
                              tags.concat(headerArrowTag));
         this._insertWithTags(iter, '\u25BC', tags.concat(groupTag));
-    },
+    }
 
     _insertStatus(text, member, type) {
         let time = GLib.DateTime.new_now_utc().to_unix();
@@ -1122,7 +1114,7 @@ var ChatView = new Lang.Class({
         this._ensureNewLine();
         let iter = this._view.buffer.get_end_iter();
         this._insertWithTags(iter, text, tags);
-    },
+    }
 
     _formatTimestamp(timestamp) {
         let date = GLib.DateTime.new_from_unix_local(timestamp);
@@ -1201,7 +1193,7 @@ var ChatView = new Lang.Class({
         }
 
         return date.format(format);
-    },
+    }
 
     _insertTpMessage(tpMessage) {
         let message = this._createMessage(tpMessage);
@@ -1216,7 +1208,7 @@ var ChatView = new Lang.Class({
             this._channel.ack_message_async(tpMessage, null);
         else if (this._needsIndicator)
             this._setIndicatorMark(this._view.buffer.get_end_iter());
-    },
+    }
 
     _insertMessage(iter, message, state) {
         let isAction = message.messageType == Tp.ChannelTextMessageType.ACTION;
@@ -1315,7 +1307,7 @@ var ChatView = new Lang.Class({
         if (highlight && message.pendingId)
             this._pending.set(message.pendingId,
                               this._view.buffer.create_mark(null, iter, true));
-    },
+    }
 
     _onNickStatusChanged(baseNick, status) {
         if (this._room.type == Tp.HandleType.CONTACT &&
@@ -1332,14 +1324,14 @@ var ChatView = new Lang.Class({
             return;
 
         this._updateNickTag(nickTag, status);
-    },
+    }
 
     _updateNickTag(tag, status) {
         if (status == Tp.ConnectionPresenceType.AVAILABLE)
             tag.foreground_rgba = this._activeNickColor;
         else
             tag.foreground_rgba = this._inactiveNickColor;
-    },
+    }
 
     _onNickTagClicked(tag) {
         let view = this._view;
@@ -1376,7 +1368,7 @@ var ChatView = new Lang.Class({
 
         tag._popover.pointing_to = rect1;
         tag._popover.show();
-    },
+    }
 
     _createUrlTag(url) {
         if (url.indexOf(':') == -1)
@@ -1398,7 +1390,7 @@ var ChatView = new Lang.Class({
             return Gdk.EVENT_STOP;
         });
         return tag;
-    },
+    }
 
     _ensureNewLine() {
         let buffer = this._view.get_buffer();
@@ -1412,7 +1404,7 @@ var ChatView = new Lang.Class({
             tags.push(headerTag);
         if (iter.get_line_offset() != 0)
             this._insertWithTags(iter, '\n', tags);
-    },
+    }
 
     _getLineIters(iter) {
         let start = iter.copy();
@@ -1423,15 +1415,15 @@ var ChatView = new Lang.Class({
         end.forward_to_line_end();
 
         return [start, end];
-    },
+    }
 
     _lookupTag(name) {
         return this._view.get_buffer().tag_table.lookup(name);
-    },
+    }
 
     _insertWithTagName(iter, text, name) {
         this._insertWithTags(iter, text, [this._lookupTag(name)]);
-    },
+    }
 
     _insertWithTags(iter, text, tags) {
         let buffer = this._view.get_buffer();
diff --git a/src/connections.js b/src/connections.js
index c0ba771..1c712dd 100644
--- a/src/connections.js
+++ b/src/connections.js
@@ -29,10 +29,8 @@ function getAccountParams(account) {
     return params;
 };
 
-var ConnectionRow = new Lang.Class({
-    Name: 'ConnectionRow',
-    Extends: Gtk.ListBoxRow,
-
+const ConnectionRow = GObject.registerClass(
+class ConnectionRow extends Gtk.ListBoxRow {
     _init(params) {
         if (!params || !params.id)
             throw new Error('No id in parameters');
@@ -40,7 +38,7 @@ var ConnectionRow = new Lang.Class({
         this._id = params.id;
         delete params.id;
 
-        this.parent(params);
+        super._init(params);
 
         this.bind_property('sensitive', this, 'activatable',
                            GObject.BindingFlags.SYNC_CREATE);
@@ -62,16 +60,14 @@ var ConnectionRow = new Lang.Class({
         this.bind_property('sensitive', insensitiveDesc, 'visible',
                            GObject.BindingFlags.SYNC_CREATE |
                            GObject.BindingFlags.INVERT_BOOLEAN);
-    },
+    }
 
     get id() {
         return this._id;
     }
 });
 
-var ConnectionsList = new Lang.Class({
-    Name: 'ConnectionsList',
-    Extends: Gtk.ScrolledWindow,
+var ConnectionsList = GObject.registerClass({
     Properties: {
         'favorites-only': GObject.ParamSpec.boolean('favorites-only',
                                                     'favorites-only',
@@ -81,12 +77,12 @@ var ConnectionsList = new Lang.Class({
                                                     false)
     },
     Signals: { 'account-created': { param_types: [Tp.Account.$gtype] },
-               'account-selected': {}},
-
+               'account-selected': {}}
+}, class ConnectionsList extends Gtk.ScrolledWindow {
     _init(params) {
         this._favoritesOnly = false;
 
-        this.parent(params);
+        super._init(params);
 
         this.hscrollbar_policy = Gtk.PolicyType.NEVER;
 
@@ -114,11 +110,11 @@ var ConnectionsList = new Lang.Class({
         this._networksManager.connect('changed',
                                       Lang.bind(this, this._networksChanged));
         this._networksChanged();
-    },
+    }
 
     get favorites_only() {
         return this._favoritesOnly;
-    },
+    }
 
     set favorites_only(favsOnly) {
         if (this._favoritesOnly == favsOnly)
@@ -126,38 +122,38 @@ var ConnectionsList = new Lang.Class({
 
         this._favoritesOnly = favsOnly;
         this.notify('favorites-only');
-    },
+    }
 
     setFilter(filter) {
         if (Utils.updateTerms(this._filterTerms, filter))
             this._list.invalidate_filter();
-    },
+    }
 
     activateFirst() {
         let row = this._list.get_row_at_y(0);
         if (row)
             row.activate();
-    },
+    }
 
     activateSelected() {
         let row = this._list.get_selected_row();
         if (row)
             row.activate();
-    },
+    }
 
     _filterRows(row) {
         let matchTerms = this._networksManager.getNetworkMatchTerms(row.id);
         return this._filterTerms.every(term => {
             return matchTerms.some(s => s.indexOf(term) != -1);
         });
-    },
+    }
 
     _updateHeader(row, before) {
         if (!before)
             row.set_header(null);
         else if (!row.get_header())
             row.set_header(new Gtk.Separator());
-    },
+    }
 
     _networksChanged() {
         this._list.foreach(w => { w.destroy(); });
@@ -178,7 +174,7 @@ var ConnectionsList = new Lang.Class({
                                                sensitive: sensitive }));
             this._list.add(this._rows.get(network.id));
         });
-    },
+    }
 
     _onRowActivated(list, row) {
         let name = this._networksManager.getNetworkName(row.id);
@@ -200,7 +196,7 @@ var ConnectionsList = new Lang.Class({
                 this.emit('account-created', account);
         });
         this.emit('account-selected');
-    },
+    }
 
     _setAccountRowSensitive(account, sensitive) {
         if (!this._networksManager.getAccountIsPredefined(account))
@@ -210,7 +206,7 @@ var ConnectionsList = new Lang.Class({
             return;
 
         this._rows.get(account.service).sensitive = sensitive;
-    },
+    }
 
     _sort(row1, row2) {
         let isFavorite1 = this._networksManager.getNetworkIsFavorite(row1.id);
@@ -226,9 +222,7 @@ var ConnectionsList = new Lang.Class({
     }
 });
 
-var ConnectionDetails = new Lang.Class({
-    Name: 'ConnectionDetails',
-    Extends: Gtk.Grid,
+var ConnectionDetails = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/connection-details.ui',
     InternalChildren: ['nameEntry',
                        'serverEntry',
@@ -246,7 +240,7 @@ var ConnectionDetails = new Lang.Class({
                                                            GObject.ParamFlags.READABLE,
                                                            false)},
     Signals: { 'account-created': { param_types: [Tp.Account.$gtype] }},
-
+}, class ConnectionDetails extends Gtk.Grid {
     _init(params) {
         this._networksManager = NetworksManager.getDefault();
         this._networksManager.connect('changed', () => {
@@ -255,7 +249,7 @@ var ConnectionDetails = new Lang.Class({
 
         this._account = null;
 
-        this.parent(params);
+        super._init(params);
 
         this._nameEntry.connect('changed',
                                 Lang.bind(this, this._onCanConfirmChanged));
@@ -279,7 +273,7 @@ var ConnectionDetails = new Lang.Class({
         this._realnameEntry.set_completion(completion);
 
         this.reset();
-    },
+    }
 
     setErrorHint(hint) {
         if (hint == ErrorHint.SERVER)
@@ -291,7 +285,7 @@ var ConnectionDetails = new Lang.Class({
             this._nickEntry.get_style_context().add_class('error');
         else
             this._nickEntry.get_style_context().remove_class('error');
-    },
+    }
 
     _getParams() {
         let nameText = this._nameEntry.text.trim();
@@ -316,7 +310,7 @@ var ConnectionDetails = new Lang.Class({
             params.port = DEFAULT_SSL_PORT;
 
         return params;
-    },
+    }
 
     reset() {
         this._savedName = '';
@@ -335,11 +329,11 @@ var ConnectionDetails = new Lang.Class({
             this._serverEntry.grab_focus();
         else
             this._nickEntry.grab_focus();
-    },
+    }
 
     _onCanConfirmChanged() {
         this.notify('can-confirm');
-    },
+    }
 
     _populateFromAccount(account) {
         let params = getAccountParams(account);
@@ -362,7 +356,7 @@ var ConnectionDetails = new Lang.Class({
         this._realnameEntry.text = this._savedRealname;
         this._nameEntry.text = this._savedName;
         this._sslCheckbox.active = this._savedSSL;
-    },
+    }
 
     get can_confirm() {
         let paramsChanged = this._nameEntry.text != this._savedName ||
@@ -374,11 +368,11 @@ var ConnectionDetails = new Lang.Class({
         return this._serverEntry.get_text_length() > 0 &&
                this._nickEntry.get_text_length() > 0 &&
                paramsChanged;
-    },
+    }
 
     get has_service() {
         return this._networksManager.getAccountIsPredefined(this._account);
-    },
+    }
 
     set account(account) {
         this._account = account;
@@ -387,7 +381,7 @@ var ConnectionDetails = new Lang.Class({
         this.reset();
         if (this._account)
             this._populateFromAccount(this._account);
-    },
+    }
 
     save() {
         if (!this.can_confirm)
@@ -397,7 +391,7 @@ var ConnectionDetails = new Lang.Class({
             this._updateAccount();
         else
             this._createAccount();
-    },
+    }
 
     _createAccount() {
         let params = this._getParams();
@@ -418,7 +412,7 @@ var ConnectionDetails = new Lang.Class({
             if (account) // TODO: Handle errors
                 this.emit('account-created', account);
         });
-    },
+    }
 
     _updateAccount() {
         let params = this._getParams();
@@ -434,7 +428,7 @@ var ConnectionDetails = new Lang.Class({
         account.set_display_name_async(params.name, (a, res) => {
             a.set_display_name_finish(res); // TODO: Check for errors
         });
-    },
+    }
 
     _detailsFromParams(params, oldDetails) {
         let details = { account:  GLib.Variant.new('s', params.account),
@@ -455,18 +449,16 @@ var ConnectionDetails = new Lang.Class({
 });
 
 
-var ConnectionProperties = new Lang.Class({
-    Name: 'ConnectionProperties',
-    Extends: Gtk.Dialog,
+var ConnectionProperties = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/connection-properties.ui',
     InternalChildren: ['details',
                        'errorBox',
                        'errorLabel'],
-
+}, class ConnectionProperties extends Gtk.Dialog {
     _init(account) {
         /* Translators: %s is a connection name */
         let title = _("“%s” Properties").format(account.display_name);
-        this.parent({ title: title,
+        super._init({ title: title,
                       use_header_bar: 1 });
 
         this._details.account = account;
@@ -490,7 +482,7 @@ var ConnectionProperties = new Lang.Class({
         account.connect('notify::connection-status',
                         Lang.bind(this, this._syncErrorMessage));
         this._syncErrorMessage(account);
-    },
+    }
 
     _syncErrorMessage(account) {
         let status = account.connection_status;
diff --git a/src/emojiPicker.js b/src/emojiPicker.js
index a3e868a..2eb28ba 100644
--- a/src/emojiPicker.js
+++ b/src/emojiPicker.js
@@ -61,16 +61,14 @@ function getEmojis() {
     return _emojis;
 }
 
-const Emoji = new Lang.Class({
-    Name: 'Emoji',
-    Extends: Gtk.FlowBoxChild,
-
+const Emoji = GObject.registerClass(
+class Emoji extends Gtk.FlowBoxChild {
     _init(emojiData) {
         this._name = emojiData.name;
         this._matchName = this._name.toLowerCase();
         this._char = emojiData.char;
 
-        this.parent();
+        super._init();
 
         this.get_style_context().add_class('emoji');
 
@@ -89,32 +87,30 @@ const Emoji = new Lang.Class({
 
         box.add(new Gtk.Label({ label: this._char }));
         box.show_all();
-    },
+    }
 
     match(terms) {
         return terms.every(t => this._matchName.includes(t));
-    },
+    }
 
     get emoji() {
         return this._char;
     }
 });
 
-const SectionIndicator = new Lang.Class({
-    Name: 'SectionIndicator',
-    Extends: Gtk.Button,
-
+const SectionIndicator = GObject.registerClass(
+class SectionIndicator extends Gtk.Button {
     _init(labelCode, from, to) {
         this._from = from;
         this._to = to;
 
-        this.parent({ relief: Gtk.ReliefStyle.NONE });
+        super._init({ relief: Gtk.ReliefStyle.NONE });
 
         this.get_style_context().add_class('emoji-section');
 
         this.add(new Gtk.Label({ label: String.fromCodePoint(labelCode, 0xfe0e),
                                  visible: true }));
-    },
+    }
 
     updateForIndex(index) {
         if (this._from <= index && index <= this._to)
@@ -124,11 +120,9 @@ const SectionIndicator = new Lang.Class({
     }
 });
 
-var EmojiPicker = new Lang.Class({
-    Name: 'EmojiPicker',
-    Extends: Gtk.Popover,
+var EmojiPicker = GObject.registerClass({
     Signals: { 'emoji-picked': { param_types: [GObject.TYPE_STRING] } },
-
+}, class EmojiPicker extends Gtk.Popover {
     _init(params) {
         this._terms = [];
 
@@ -149,7 +143,7 @@ var EmojiPicker = new Lang.Class({
                        fromNo: 2357, toNo: 2623 }
         };
 
-        this.parent(params);
+        super._init(params);
 
         this.get_style_context().add_class('emoji-picker');
 
@@ -225,7 +219,7 @@ var EmojiPicker = new Lang.Class({
             this._adjustment.value = 0;
             this._updateIndicators();
         });
-    },
+    }
 
     _updateIndicators() {
         let child = null;
diff --git a/src/entryArea.js b/src/entryArea.js
index 124f694..691f33d 100644
--- a/src/entryArea.js
+++ b/src/entryArea.js
@@ -21,9 +21,7 @@ const MAX_LINES = 5;
 let _checker = null;
 let _emojiPicker = null;
 
-var ChatEntry = new Lang.Class({
-    Name: 'ChatEntry',
-    Extends: Gtk.Entry,
+var ChatEntry = GObject.registerClass({
     Implements: [PasteManager.DropTargetIface],
     Properties: {
         'can-drop': GObject.ParamSpec.override('can-drop', PasteManager.DropTargetIface),
@@ -32,9 +30,9 @@ var ChatEntry = new Lang.Class({
                                               GObject.TYPE_INT] },
                'image-pasted': { param_types: [GdkPixbuf.Pixbuf.$gtype] },
                'file-pasted': { param_types: [Gio.File.$gtype] } },
-
+}, class ChatEntry extends Gtk.Entry {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         PasteManager.DropTargetIface.addTargets(this, this);
 
@@ -61,7 +59,7 @@ var ChatEntry = new Lang.Class({
         spellEntry.set_inline_spell_checking(true);
 
         this._useDefaultHandler = false;
-    },
+    }
 
     _showEmojiPicker() {
         if (!this.is_sensitive() || !this.get_mapped())
@@ -83,11 +81,11 @@ var ChatEntry = new Lang.Class({
         _emojiPicker.set_relative_to(this);
         _emojiPicker.set_pointing_to(rect);
         _emojiPicker.popup();
-    },
+    }
 
     get can_drop() {
         return true;
-    },
+    }
 
     vfunc_drag_data_received(context, x, y, data, info, time) {
         let str = data.get_text();
@@ -96,12 +94,12 @@ var ChatEntry = new Lang.Class({
             return;
 
          GObject.signal_stop_emission_by_name(this, 'drag-data-received');
-        this.parent(context, x, y, data, info, time);
-    },
+        super.vfunc_drag_data_received(context, x, y, data, info, time);
+    }
 
     vfunc_paste_clipboard(entry) {
         if (!this.editable || this._useDefaultHandler) {
-            this.parent();
+            super.vfunc_paste_clipboard();
             return;
         }
 
@@ -118,7 +116,7 @@ var ChatEntry = new Lang.Class({
                 return;
             this.emit('image-pasted', pixbuf);
         });
-    },
+    }
 
     _onTextReceived(clipboard, text) {
         if (text == null)
@@ -137,9 +135,7 @@ var ChatEntry = new Lang.Class({
     }
 });
 
-var EntryArea = new Lang.Class({
-    Name: 'EntryArea',
-    Extends: Gtk.Stack,
+var EntryArea = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/entry-area.ui',
     InternalChildren: ['chatEntry',
                        'nickButton',
@@ -159,7 +155,7 @@ var EntryArea = new Lang.Class({
                                                  GObject.ParamFlags.WRITABLE,
                                                  0, GLib.MAXUINT32, 0)
     },
-
+}, class EntryArea extends Gtk.Stack {
     _init(params) {
         this._room = params.room;
         delete params.room;
@@ -167,7 +163,7 @@ var EntryArea = new Lang.Class({
         this._ircParser = new IrcParser.IrcParser(this._room);
         this._maxNickChars = ChatView.MAX_NICK_CHARS;
 
-        this.parent(params);
+        super._init(params);
 
         this.connect('destroy', Lang.bind(this, this._onDestroy));
         this.connect('notify::sensitive', Lang.bind(this, this._onSensitiveChanged));
@@ -262,12 +258,12 @@ var EntryArea = new Lang.Class({
 
         this._chatEntry.connect('map', Lang.bind(this, this._updateCompletions));
         this._chatEntry.connect('unmap', Lang.bind(this, this._updateCompletions));
-    },
+    }
 
     set max_nick_chars(maxChars) {
         this._maxNickChars = maxChars;
         this._updateNick();
-    },
+    }
 
     _updateCompletions() {
         let nicks = [];
@@ -280,7 +276,7 @@ var EntryArea = new Lang.Class({
             nicks = members.map(member => member.alias);
         }
         this._completion.setCompletions(nicks);
-    },
+    }
 
     _canFocusChatEntry() {
         let toplevelFocus = this._chatEntry.get_toplevel().get_focus();
@@ -288,7 +284,7 @@ var EntryArea = new Lang.Class({
                this._chatEntry.get_mapped() &&
                !this._chatEntry['has-focus'] &&
                !(toplevelFocus instanceof Gtk.Entry);
-    },
+    }
 
     _onKeyPressEvent(w, event) {
         if (!this._canFocusChatEntry())
@@ -314,11 +310,11 @@ var EntryArea = new Lang.Class({
         this._chatEntry.grab_focus_without_selecting();
         this._chatEntry.event(event);
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _onEntryChanged() {
         this._chatEntry.get_style_context().remove_class('error');
-    },
+    }
 
     _setPasteContent(content) {
         this._pasteContent = content;
@@ -331,7 +327,7 @@ var EntryArea = new Lang.Class({
             this.visible_child_name = 'default';
             this._chatEntry.grab_focus_without_selecting();
         }
-    },
+    }
 
     pasteText(text, nLines) {
         this._confirmLabel.label =
@@ -343,20 +339,20 @@ var EntryArea = new Lang.Class({
                      "Uploading %s lines of text to public paste service…",
                      nLines).format(nLines);
         this._setPasteContent(text);
-    },
+    }
 
     pasteImage(pixbuf) {
         this._confirmLabel.label = _("Upload image to public paste service?");
         this._uploadLabel.label = _("Uploading image to public paste service…");
         this._setPasteContent(pixbuf);
-    },
+    }
 
     pasteFile(file) {
         file.query_info_async(Gio.FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
                               Gio.FileQueryInfoFlags.NONE,
                               GLib.PRIORITY_DEFAULT, null,
                               Lang.bind(this, this._onFileInfoReady));
-    },
+    }
 
     _onFileInfoReady(file, res) {
         let fileInfo = null;
@@ -372,7 +368,7 @@ var EntryArea = new Lang.Class({
         /* Translators: %s is a filename */
         this._uploadLabel.label = _("Uploading “%s” to public paste service…").format(name);
         this._setPasteContent(file);
-    },
+    }
 
     _onPasteClicked() {
         let title;
@@ -397,16 +393,16 @@ var EntryArea = new Lang.Class({
                   (type == 'object' ? this._pasteContent.toString() : type));
         }
         this._confirmLabel.hide();
-    },
+    }
 
     _onCancelClicked() {
         this._setPasteContent(null);
-    },
+    }
 
     _onSensitiveChanged() {
         if (this._canFocusChatEntry())
             this._chatEntry.grab_focus();
-    },
+    }
 
     _onChannelChanged(room) {
         this._updateCompletions();
@@ -418,8 +414,7 @@ var EntryArea = new Lang.Class({
         else
             this._selfAliasChangedId = 0;
         this._updateNick();
-    },
-
+    }
 
     _setNick(nick) {
         this._nickLabel.width_chars = Math.max(nick.length, this._maxNickChars);
@@ -440,7 +435,7 @@ var EntryArea = new Lang.Class({
             this._updateNick();
             return GLib.SOURCE_REMOVE;
         });
-    },
+    }
 
     _updateNick() {
         let channel = this._room ? this._room.channel : null;
@@ -452,7 +447,7 @@ var EntryArea = new Lang.Class({
 
         if (!this._nickEntry['is-focus'])
             this._nickEntry.text = nick;
-    },
+    }
 
     _onDestroy() {
         if (this._membersChangedId)
diff --git a/src/initialSetup.js b/src/initialSetup.js
index 1dd0362..911c71d 100644
--- a/src/initialSetup.js
+++ b/src/initialSetup.js
@@ -1,5 +1,6 @@
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 
 const Lang = imports.lang;
@@ -11,19 +12,17 @@ const SetupPage = {
     OFFLINE: 2
 };
 
-var InitialSetupWindow = new Lang.Class({
-    Name: 'InitialSetupWindow',
-    Extends: Gtk.Window,
+var InitialSetupWindow = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/initial-setup-window.ui',
     InternalChildren: ['contentStack',
                        'connectionsList',
                        'nextButton',
                        'prevButton',
                        'serverRoomList'],
-
+}, class InitialSetupWindow extends Gtk.Window {
     _init(params) {
 
-        this.parent(params);
+        super._init(params);
 
         this._currentAccount = null;
 
@@ -61,7 +60,7 @@ var InitialSetupWindow = new Lang.Class({
         this._networkMonitor.connect('notify::network-available',
                                      Lang.bind(this, this._onNetworkAvailableChanged));
         this._onNetworkAvailableChanged();
-    },
+    }
 
     _onNetworkAvailableChanged() {
         if (this._networkMonitor.network_available)
@@ -69,7 +68,7 @@ var InitialSetupWindow = new Lang.Class({
                                                : SetupPage.CONNECTION);
         else
             this._setPage(SetupPage.OFFLINE);
-    },
+    }
 
     _setPage(page) {
         if (page == SetupPage.CONNECTION)
@@ -92,7 +91,7 @@ var InitialSetupWindow = new Lang.Class({
 
         this._nextButton.grab_default();
         this._updateNextSensitivity();
-    },
+    }
 
     _unsetAccount() {
         if (!this._currentAccount)
@@ -102,7 +101,7 @@ var InitialSetupWindow = new Lang.Class({
             a.remove_finish(res);
         });
         this._currentAccount = null;
-    },
+    }
 
     get _page() {
         if (this._contentStack.visible_child_name == 'rooms')
@@ -111,7 +110,7 @@ var InitialSetupWindow = new Lang.Class({
             return SetupPage.CONNECTION;
         else
             return SetupPage.OFFLINE;
-    },
+    }
 
     _updateNextSensitivity() {
         let sensitive = this._page != SetupPage.OFFLINE;
@@ -120,7 +119,7 @@ var InitialSetupWindow = new Lang.Class({
             sensitive = this._serverRoomList.can_join;
 
         this._nextButton.sensitive = sensitive;
-    },
+    }
 
     _joinRooms() {
         this.hide();
diff --git a/src/joinDialog.js b/src/joinDialog.js
index 080a977..b468b6f 100644
--- a/src/joinDialog.js
+++ b/src/joinDialog.js
@@ -15,9 +15,7 @@ const DialogPage = {
     CONNECTION: 1
 };
 
-var JoinDialog = new Lang.Class({
-    Name: 'JoinDialog',
-    Extends: Gtk.Dialog,
+var JoinDialog = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/join-room-dialog.ui',
     InternalChildren: ['cancelButton',
                        'joinButton',
@@ -31,10 +29,10 @@ var JoinDialog = new Lang.Class({
                        'details',
                        'addButton',
                        'customToggle'],
-
+}, class JoinDialog extends Gtk.Dialog {
     _init(params) {
         params['use-header-bar'] = 1;
-        this.parent(params);
+        super._init(params);
 
         // TODO: Is there really no way to do this in the template?
         let icon = new Gtk.Image({ icon_name: 'go-previous-symbolic' });
@@ -89,11 +87,11 @@ var JoinDialog = new Lang.Class({
 
         this._updateConnectionCombo();
         this._updateCanJoin();
-    },
+    }
 
     get _hasAccounts() {
       return Object.keys(this._accounts).length > 0;
-    },
+    }
 
     _setupMainPage() {
         this._connectionButton.connect('clicked', () => {
@@ -106,7 +104,7 @@ var JoinDialog = new Lang.Class({
 
         this._serverRoomList.connect('notify::can-join',
                                      Lang.bind(this, this._updateCanJoin));
-    },
+    }
 
     _setupConnectionPage() {
         this._backButton.connect('clicked', () => {
@@ -148,7 +146,7 @@ var JoinDialog = new Lang.Class({
             if (this._filterEntry.text.length > 0)
                 this._connectionsList.activateFirst();
         });
-    },
+    }
 
     _onAccountChanged() {
         let selected = this._connectionCombo.get_active_text();
@@ -157,11 +155,11 @@ var JoinDialog = new Lang.Class({
             return;
 
        this._serverRoomList.setAccount(account);
-    },
+    }
 
     _onAccountCreated(w, account) {
         this._connectionCombo.set_active_id(account.display_name);
-    },
+    }
 
     _joinRoom() {
         this.hide();
@@ -181,7 +179,7 @@ var JoinDialog = new Lang.Class({
                                              room,
                                              Utils.getTpEventTime() ]));
         });
-    },
+    }
 
     _updateConnectionCombo() {
         this._connectionCombo.remove_all();
@@ -200,7 +198,7 @@ var JoinDialog = new Lang.Class({
         if(activeRoom)
             activeIndex = Math.max(names.indexOf(activeRoom.account.display_name), 0);
         this._connectionCombo.set_active(activeIndex);
-    },
+    }
 
     _updateCanJoin() {
         let sensitive = false;
@@ -212,14 +210,14 @@ var JoinDialog = new Lang.Class({
         this._joinButton.sensitive = sensitive;
         this.set_default_response(sensitive ? Gtk.ResponseType.OK
                                             : Gtk.ResponseType.NONE);
-    },
+    }
 
     get _page() {
         if (this._mainStack.visible_child_name == 'connection')
             return DialogPage.CONNECTION;
         else
             return DialogPage.MAIN;
-    },
+    }
 
     _setPage(page) {
         let isMain = page == DialogPage.MAIN;
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 1af30a0..c59a3c3 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -18,9 +18,7 @@ const UserList = imports.userList;
 const Utils = imports.utils;
 
 
-var FixedSizeFrame = new Lang.Class({
-    Name: 'FixedSizeFrame',
-    Extends: Gtk.Frame,
+var FixedSizeFrame = GObject.registerClass({
     Properties: {
         height: GObject.ParamSpec.int('height',
                                       'height',
@@ -33,24 +31,24 @@ var FixedSizeFrame = new Lang.Class({
                                      GObject.ParamFlags.READWRITE,
                                      -1, GLib.MAXINT32, -1)
     },
-
+}, class FixedSizeFrame extends Gtk.Frame {
     _init(params) {
         this._height = -1;
         this._width = -1;
 
-        this.parent(params);
-    },
+        super._init(params);
+    }
 
     _queueRedraw() {
         let child = this.get_child();
         if (child)
             child.queue_resize();
         this.queue_draw();
-    },
+    }
 
     get height() {
         return this._height;
-    },
+    }
 
     set height(height) {
         if (height == this._height)
@@ -59,11 +57,11 @@ var FixedSizeFrame = new Lang.Class({
         this.notify('height');
         this.set_size_request(this._width, this._height);
         this._queueRedraw();
-    },
+    }
 
     get width() {
         return this._width;
-    },
+    }
 
     set width(width) {
         if (width == this._width)
@@ -73,22 +71,20 @@ var FixedSizeFrame = new Lang.Class({
         this.notify('width');
         this.set_size_request(this._width, this._height);
         this._queueRedraw();
-    },
+    }
 
     vfunc_get_preferred_width_for_height(forHeight) {
-        let [min, nat] = this.parent(forHeight);
+        let [min, nat] = super.vfunc_get_preferred_width_for_height(forHeight);
         return [min, this._width < 0 ? nat : this._width];
-    },
+    }
 
     vfunc_get_preferred_height_for_width(forWidth) {
-        let [min, nat] = this.parent(forWidth);
+        let [min, nat] = super.vfunc_get_preferred_height_for_width(forWidth);
         return [min, this._height < 0 ? nat : this._height];
     }
 });
 
-var MainWindow = new Lang.Class({
-    Name: 'MainWindow',
-    Extends: Gtk.ApplicationWindow,
+var MainWindow = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/main-window.ui',
     InternalChildren: ['titlebarRight',
                        'titlebarLeft',
@@ -117,7 +113,7 @@ var MainWindow = new Lang.Class({
                                                 Polari.Room.$gtype)
     },
     Signals: { 'active-room-state-changed': {} },
-
+}, class MainWindow extends Gtk.ApplicationWindow {
     _init(params) {
         this._subtitle = '';
         params.show_menubar = false;
@@ -130,7 +126,7 @@ var MainWindow = new Lang.Class({
         this._membersChangedId = 0;
         this._channelChangedId = 0;
 
-        this.parent(params);
+        super._init(params);
 
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
         this._gtkSettings = Gtk.Settings.get_default();
@@ -210,27 +206,27 @@ var MainWindow = new Lang.Class({
 
         if (this._settings.get_boolean('window-maximized'))
             this.maximize();
-    },
+    }
 
     get subtitle() {
         return this._subtitle;
-    },
+    }
 
     get subtitle_visible() {
         return this._subtitle.length > 0;
-    },
+    }
 
     _onWindowStateEvent(widget, event) {
         let state = event.get_window().get_state();
 
         this._isFullscreen = (state & Gdk.WindowState.FULLSCREEN) != 0;
         this._isMaximized = (state & Gdk.WindowState.MAXIMIZED) != 0;
-    },
+    }
 
     _onSizeAllocate(widget, allocation) {
         if (!this._isFullscreen && !this._isMaximized)
             this._currentSize = this.get_size();
-    },
+    }
 
     _onDestroy(widget) {
         this._settings.set_boolean ('window-maximized', this._isMaximized);
@@ -248,7 +244,7 @@ var MainWindow = new Lang.Class({
             this._settings.set_value('last-selected-channel', serializedChannel);
         else
             this._settings.reset('last-selected-channel');
-    },
+    }
 
     _touchFile(file) {
         try {
@@ -259,7 +255,7 @@ var MainWindow = new Lang.Class({
 
         let stream = file.create(0, null);
         stream.close(null);
-    },
+    }
 
     _onDeleteEvent() {
         let f = Gio.File.new_for_path(GLib.get_user_cache_dir() +
@@ -274,12 +270,12 @@ var MainWindow = new Lang.Class({
 
         this._closeConfirmationDialog.show();
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _onAccountsChanged(am) {
         let hasAccounts = this._accountsMonitor.enabledAccounts.length > 0;
         this._roomListRevealer.reveal_child = hasAccounts;
-    },
+    }
 
     _updateDecorations() {
         let layoutLeft = null;
@@ -295,11 +291,11 @@ var MainWindow = new Lang.Class({
 
         this._titlebarLeft.set_decoration_layout(layoutLeft);
         this._titlebarRight.set_decoration_layout(layoutRight);
-    },
+    }
 
     get active_room() {
         return this._room;
-    },
+    }
 
     set active_room(room) {
         if (room == this._room)
@@ -342,7 +338,7 @@ var MainWindow = new Lang.Class({
                 this._updateUserListLabel();
                 this.emit('active-room-state-changed');
             });
-    },
+    }
 
     _onRoomsLoaded(mgr) {
         if (this.active_room)
@@ -360,17 +356,17 @@ var MainWindow = new Lang.Class({
 
         this.active_room = this._roomManager.lookupRoom(roomId) ||
                            this._roomManager.rooms.shift();
-    },
+    }
 
     _onRoomRemoved(mgr, room) {
         if (room == this._lastActiveRoom)
             this._lastActiveRoom = null;
-    },
+    }
 
     showJoinRoomDialog() {
         let dialog = new JoinDialog.JoinDialog({ transient_for: this });
         dialog.show();
-    },
+    }
 
     _updateUserListLabel() {
         let numMembers = 0;
@@ -384,7 +380,7 @@ var MainWindow = new Lang.Class({
                                       "%d users", numMembers).format(numMembers);
         this._showUserListButton.get_accessible().set_name(accessibleName);
         this._showUserListButton.label = '%d'.format(numMembers);
-    },
+    }
 
     _updateTitlebar() {
         let subtitle = '';
diff --git a/src/pasteManager.js b/src/pasteManager.js
index 4954594..4671c71 100644
--- a/src/pasteManager.js
+++ b/src/pasteManager.js
@@ -77,8 +77,7 @@ var PasteManager = class {
     }
 };
 
-var DropTargetIface = new Lang.Interface({
-    Name: 'DropTargetIface',
+var DropTargetIface = GObject.registerClass({
     Requires: [GObject.Object],
     Properties: {
         'can-drop': GObject.ParamSpec.boolean('can-drop', '', '',
@@ -90,7 +89,7 @@ var DropTargetIface = new Lang.Interface({
         'image-dropped': { param_types: [GdkPixbuf.Pixbuf.$gtype] },
         'file-dropped': { param_types: [Gio.File.$gtype] }
     },
-
+}, class DropTargetIface extends GObject.Interface {
     addTargets(widget) {
         this._dragHighlight = false;
 
@@ -111,7 +110,7 @@ var DropTargetIface = new Lang.Interface({
         widget.connect('drag-motion', Lang.bind(this, this._onDragMotion));
         widget.connect_after('drag-data-received',
                              Lang.bind(this, this._onDragDataReceived));
-    },
+    }
 
     _onDragDrop(widget, context, x, y, time) {
         if (!this.can_drop)
@@ -122,12 +121,12 @@ var DropTargetIface = new Lang.Interface({
 
         Polari.drag_dest_request_data(widget, context, time);
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _onDragLeave(widget, context, time) {
         widget.drag_unhighlight();
         this._dragHighlight = false;
-    },
+    }
 
     _onDragMotion(widget, context, x, y, time) {
         if (!this.can_drop)
@@ -153,7 +152,7 @@ var DropTargetIface = new Lang.Interface({
         }
 
         return Gdk.EVENT_STOP;
-    },
+    }
 
 
     _onDragDataReceived(widget, context, x, y, data, info, time) {
@@ -190,7 +189,7 @@ var DropTargetIface = new Lang.Interface({
             }
             Gtk.drag_finish(context, success, false, time);
         }
-    },
+    }
 
     _lookupFileInfo(file, callback) {
         let attr = Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE;
diff --git a/src/polari-accounts.in b/src/polari-accounts.in
index 9dae1e2..017c9c5 100755
--- a/src/polari-accounts.in
+++ b/src/polari-accounts.in
@@ -7,12 +7,10 @@ const Tp = imports.gi.TelepathyGLib;
 
 const Lang = imports.lang;
 
-const AccountsWindow = new Lang.Class({
-    Name: 'AccountsWindow',
-    Extends: Gtk.ApplicationWindow,
-
+const AccountsWindow = GObject.registerClass(
+class AccountsWindow extends Gtk.ApplicationWindow {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         let scrolled = new Gtk.ScrolledWindow({ hscrollbar_policy: Gtk.PolicyType.NEVER,
                                                 shadow_type: Gtk.ShadowType.NONE });
@@ -38,7 +36,7 @@ const AccountsWindow = new Lang.Class({
 
         let am = Tp.AccountManager.dup();
         am.prepare_async(null, Lang.bind(this, this._onPrepared));
-    },
+    }
 
     _onPrepared(am) {
         am.connect('account-validity-changed', (am, account, valid) => {
@@ -51,7 +49,7 @@ const AccountsWindow = new Lang.Class({
             this._removeAccount(account);
         });
         am.dup_valid_accounts().forEach(Lang.bind(this, this._addAccount));
-    },
+    }
 
     _addAccount(account) {
         if (account.protocol_name != 'irc')
@@ -84,7 +82,7 @@ const AccountsWindow = new Lang.Class({
             account.set_enabled_async(state, null);
             return true;
         });
-    },
+    }
 
     _removeAccount(account) {
         let rows = this._list.get_children();
diff --git a/src/roomList.js b/src/roomList.js
index 37c2c19..b45acc4 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -18,14 +18,12 @@ function _onPopoverVisibleChanged(popover) {
         context.remove_class('has-open-popup');
 }
 
-var RoomRow = new Lang.Class({
-    Name: 'RoomRow',
-    Extends: Gtk.ListBoxRow,
+var RoomRow = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/room-list-row.ui',
     InternalChildren: ['eventBox', 'icon', 'roomLabel', 'counter'],
-
+}, class RoomRow extends Gtk.ListBoxRow {
     _init(room) {
-        this.parent();
+        super._init();
 
         this._room = room;
         this._popover = null;
@@ -45,24 +43,24 @@ var RoomRow = new Lang.Class({
 
         this._updatePending();
         this._onChannelChanged();
-    },
+    }
 
     get room() {
         return this._room;
-    },
+    }
 
     get account() {
         return this._room.account;
-    },
+    }
 
     get hasPending() {
         return !this.get_style_context().has_class('inactive');
-    },
+    }
 
     selected() {
         if (!this._room.channel)
             this._updatePending();
-    },
+    }
 
     _getNumPending() {
         if (!this._room.channel)
@@ -78,7 +76,7 @@ var RoomRow = new Lang.Class({
             return this._room.should_highlight_message(m.sender.alias, text);
         });
         return [nPending, highlights.length];
-    },
+    }
 
     _updatePending() {
         let [nPending, nHighlights] = this._getNumPending();
@@ -91,7 +89,7 @@ var RoomRow = new Lang.Class({
             context.add_class('inactive');
         else
             context.remove_class('inactive');
-    },
+    }
 
     _onChannelChanged() {
         if (!this._room.channel)
@@ -101,7 +99,7 @@ var RoomRow = new Lang.Class({
         this._room.channel.connect('pending-message-removed',
                                    Lang.bind(this, this._updatePending));
         this._updatePending();
-    },
+    }
 
     _onButtonRelease(w, event) {
         let [, button] = event.get_button();
@@ -111,7 +109,7 @@ var RoomRow = new Lang.Class({
         this._showPopover();
 
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _onKeyPress(w, event) {
         let [, keyval] = event.get_keyval();
@@ -124,7 +122,7 @@ var RoomRow = new Lang.Class({
         this._showPopover();
 
         return Gdk.EVENT_STOP;
-    },
+    }
 
     _showPopover() {
         if (!this._popover) {
@@ -141,9 +139,7 @@ var RoomRow = new Lang.Class({
     }
 });
 
-var RoomListHeader = new Lang.Class({
-    Name: 'RoomListHeader',
-    Extends: Gtk.MenuButton,
+var RoomListHeader = GObject.registerClass({
     CssName: 'row',
     Template: 'resource:///org/gnome/Polari/ui/room-list-header.ui',
     InternalChildren: ['label',
@@ -156,14 +152,14 @@ var RoomListHeader = new Lang.Class({
                        'popoverRemove',
                        'popoverProperties',
                        'spinner'],
-
+}, class RoomListHeader extends Gtk.MenuButton {
     _init(params) {
         this._account = params.account;
         delete params.account;
 
         this._app = Gio.Application.get_default();
 
-        this.parent(params);
+        super._init(params);
 
         this.popover.set_default_widget(this._popoverPassword);
         this.popover.connect('notify::visible', _onPopoverVisibleChanged);
@@ -205,7 +201,7 @@ var RoomListHeader = new Lang.Class({
             this._account.disconnect(connectionStatusChangedId);
             this._account.disconnect(presenceChangedId);
         });
-    },
+    }
 
     _onDisplayNameChanged() {
         this._label.label = this._account.display_name;
@@ -223,27 +219,27 @@ var RoomListHeader = new Lang.Class({
 
         let accessibleName = _("Network %s has an error").format(this._account.display_name);
         this.get_accessible().set_name(accessibleName);
-    },
+    }
 
     /* hack: Handle primary and secondary button interchangeably */
     vfunc_button_press_event(event) {
         if (event.button == Gdk.BUTTON_SECONDARY)
             event.button = Gdk.BUTTON_PRIMARY;
-        return this.parent(event);
-    },
+        return super.vfunc_button_press_event(event);
+    }
 
     vfunc_button_release_event(event) {
         if (event.button == Gdk.BUTTON_SECONDARY)
             event.button = Gdk.BUTTON_PRIMARY;
-        return this.parent(event);
-    },
+        return super.vfunc_button_release_event(event);
+    }
 
     _getConnectionStatus() {
         let presence = this._account.requested_presence_type;
         if (presence == Tp.ConnectionPresenceType.OFFLINE)
             return Tp.ConnectionStatus.DISCONNECTED;
         return this._account.connection_status;
-    },
+    }
 
     _onConnectionStatusChanged() {
         let status = this._getConnectionStatus();
@@ -288,7 +284,7 @@ var RoomListHeader = new Lang.Class({
             this._popoverTitle.label = '<b>' + _("Connection Problem") + '</b>';
             this._popoverStatus.label = this._getErrorLabel();
         }
-    },
+    }
 
     _onRequestedPresenceChanged() {
         let presence = this._account.requested_presence_type;
@@ -296,7 +292,7 @@ var RoomListHeader = new Lang.Class({
         this._popoverConnect.visible = offline;
         this._popoverReconnect.visible = !offline;
         this._onConnectionStatusChanged();
-    },
+    }
 
     _getStatusLabel() {
         switch (this._getConnectionStatus()) {
@@ -309,7 +305,7 @@ var RoomListHeader = new Lang.Class({
             default:
                 return _("Unknown");
         }
-    },
+    }
 
     _getErrorLabel() {
         switch (this._account.connection_error) {
@@ -341,15 +337,13 @@ var RoomListHeader = new Lang.Class({
             default:
                 return _("Could not connect to %s.").format(this._account.display_name);
         }
-    },
+    }
 });
 
-var RoomList = new Lang.Class({
-    Name: 'RoomList',
-    Extends: Gtk.ListBox,
-
+var RoomList = GObject.registerClass(
+class RoomList extends Gtk.ListBox {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this.set_header_func(Lang.bind(this, this._updateHeader));
         this.set_sort_func(Lang.bind(this, this._sort));
@@ -408,22 +402,22 @@ var RoomList = new Lang.Class({
         actions.forEach(a => {
             app.lookup_action(a.name).connect('activate', a.handler);
         });
-    },
+    }
 
     vfunc_realize() {
-        this.parent();
+        super.vfunc_realize();
 
         let toplevel = this.get_toplevel();
         toplevel.connect('notify::active-room',
                          Lang.bind(this, this._activeRoomChanged));
         this._activeRoomChanged();
-    },
+    }
 
     _rowToRoomIndex(index) {
         let placeholders = [...this._placeholders.values()];
         let nBefore = placeholders.filter(p => p.get_index() < index).length;
         return index - nBefore;
-    },
+    }
 
     _roomToRowIndex(index) {
         let nChildren = this.get_children().length;
@@ -431,21 +425,21 @@ var RoomList = new Lang.Class({
             if (this.get_row_at_index(i).room && roomIndex++ == index)
                 return i;
         return -1;
-    },
+    }
 
     _getRoomRowAtIndex(index) {
         return this.get_row_at_index(this._roomToRowIndex(index));
-    },
+    }
 
     _selectRoomAtIndex(index) {
         let row = this._getRoomRowAtIndex(index);
         if (row)
             this.select_row(row);
-    },
+    }
 
     _moveSelection(direction) {
         this._moveSelectionFull(direction, () => { return true; });
-    },
+    }
 
     _moveSelectionFull(direction, testFunction){
         let current = this.get_selected_row();
@@ -464,7 +458,7 @@ var RoomList = new Lang.Class({
 
         if (row)
             this.select_row(row);
-    },
+    }
 
     _moveSelectionFromRow(row) {
         if (this._roomManager.roomCount == 0)
@@ -491,7 +485,7 @@ var RoomList = new Lang.Class({
 
         if (selected != row)
             this.select_row(selected);
-    },
+    }
 
     _accountAdded(am, account) {
         if (this._placeholders.has(account))
@@ -510,7 +504,7 @@ var RoomList = new Lang.Class({
         });
 
         this._updatePlaceholderVisibility(account);
-    },
+    }
 
     _accountRemoved(am, account) {
         let placeholder = this._placeholders.get(account);
@@ -520,7 +514,7 @@ var RoomList = new Lang.Class({
 
         this._placeholders.delete(account);
         placeholder.destroy();
-    },
+    }
 
     _roomAdded(roomManager, room) {
         if (this._roomRows.has(room.id))
@@ -532,7 +526,7 @@ var RoomList = new Lang.Class({
 
         row.connect('destroy', w => { this._roomRows.delete(w.room.id); });
         this._placeholders.get(room.account).hide();
-    },
+    }
 
     _roomRemoved(roomManager, room) {
         let row = this._roomRows.get(room.id);
@@ -543,7 +537,7 @@ var RoomList = new Lang.Class({
         row.destroy();
         this._roomRows.delete(room.id);
         this._updatePlaceholderVisibility(room.account);
-    },
+    }
 
     _updatePlaceholderVisibility(account) {
         if (!account.enabled) {
@@ -554,7 +548,7 @@ var RoomList = new Lang.Class({
         let rows = [...this._roomRows.values()];
         let hasRooms = rows.some(r => r.account == account);
         this._placeholders.get(account).visible = !hasRooms;
-    },
+    }
 
     _activeRoomChanged() {
         let room = this.get_toplevel().active_room;
@@ -567,13 +561,13 @@ var RoomList = new Lang.Class({
         row.can_focus = false;
         this.select_row(row);
         row.can_focus = true;
-    },
+    }
 
     vfunc_row_selected(row) {
         this.get_toplevel().active_room = row ? row.room : null;
         if (row)
             row.selected();
-    },
+    }
 
     _updateHeader(row, before) {
         let getAccount = row => row ? row.account : null;
@@ -594,7 +588,7 @@ var RoomList = new Lang.Class({
 
         let roomListHeader = new RoomListHeader({ account: account });
         row.set_header(roomListHeader);
-    },
+    }
 
     _sort(row1, row2) {
         let account1 = row1.account;
diff --git a/src/roomStack.js b/src/roomStack.js
index 582d5e7..0de230a 100644
--- a/src/roomStack.js
+++ b/src/roomStack.js
@@ -11,9 +11,7 @@ const EntryArea = imports.entryArea;
 const Lang = imports.lang;
 const RoomManager = imports.roomManager;
 
-var RoomStack = new Lang.Class({
-    Name: 'RoomStack',
-    Extends: Gtk.Stack,
+var RoomStack = GObject.registerClass({
     Properties: {
         'entry-area-height': GObject.ParamSpec.uint('entry-area-height',
                                                     'entry-area-height',
@@ -21,9 +19,9 @@ var RoomStack = new Lang.Class({
                                                     GObject.ParamFlags.READABLE,
                                                     0, GLib.MAXUINT32, 0)
     },
-
+}, class RoomStack extends Gtk.Stack {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this._sizeGroup = new Gtk.SizeGroup({ mode: Gtk.SizeGroupMode.VERTICAL });
         this._rooms = new Map();
@@ -43,10 +41,10 @@ var RoomStack = new Lang.Class({
             this._entryAreaHeight = rect.height - 1;
             this.notify('entry-area-height');
         });
-    },
+    }
 
     vfunc_realize() {
-        this.parent();
+        super.vfunc_realize();
 
         let toplevel = this.get_toplevel();
 
@@ -56,30 +54,30 @@ var RoomStack = new Lang.Class({
                          Lang.bind(this, this._updateSensitivity));
         this._activeRoomChanged();
         this._updateSensitivity();
-    },
+    }
 
     get entry_area_height() {
         return this._entryAreaHeight;
-    },
+    }
 
     _addView(id, view) {
         this._rooms.set(id, view);
         this.add_named(view, id);
-    },
+    }
 
     _roomAdded(roomManager, room) {
         this._addView(room.id, new RoomView(room, this._sizeGroup));
-    },
+    }
 
     _roomRemoved(roomManager, room) {
         this._rooms.get(room.id).destroy();
         this._rooms.delete(room.id);
-    },
+    }
 
     _activeRoomChanged() {
         let room = this.get_toplevel().active_room;
         this.set_visible_child_name(room ? room.id : 'placeholder');
-    },
+    }
 
     _updateSensitivity() {
         let room = this.get_toplevel().active_room;
@@ -90,14 +88,12 @@ var RoomStack = new Lang.Class({
     }
 });
 
-var SavePasswordConfirmationBar = new Lang.Class({
-    Name: 'SavePasswordConfirmationBar',
-    Extends: Gtk.Revealer,
-
+var SavePasswordConfirmationBar = GObject.registerClass(
+class SavePasswordConfirmationBar extends Gtk.Revealer {
     _init(room) {
         this._room = room;
 
-        this.parent({ valign: Gtk.Align.START });
+        super._init({ valign: Gtk.Align.START });
 
         this.connect('destroy', Lang.bind(this, this._onDestroy));
 
@@ -114,7 +110,7 @@ var SavePasswordConfirmationBar = new Lang.Class({
             }
             this.reveal_child = false;
         });
-    },
+    }
 
     _createWidget() {
         this._infoBar = new Gtk.InfoBar({ show_close_button: true })
@@ -144,7 +140,7 @@ var SavePasswordConfirmationBar = new Lang.Class({
         box.add(this._subtitleLabel);
 
         this._infoBar.show_all();
-    },
+    }
 
     _onDestroy() {
         if (this._identifySentId)
@@ -153,10 +149,8 @@ var SavePasswordConfirmationBar = new Lang.Class({
     }
 });
 
-var ChatPlaceholder = new Lang.Class({
-    Name: 'ChatPlaceholder',
-    Extends: Gtk.Overlay,
-
+var ChatPlaceholder = GObject.registerClass(
+class ChatPlaceholder extends Gtk.Overlay {
     _init(sizeGroup) {
         this._accountsMonitor = AccountsMonitor.getDefault();
 
@@ -177,7 +171,7 @@ var ChatPlaceholder = new Lang.Class({
         let inputPlaceholder = new Gtk.Box({ valign: Gtk.Align.END });
         sizeGroup.add_widget(inputPlaceholder);
 
-        this.parent();
+        super._init();
         let grid = new Gtk.Grid({ column_homogeneous: true, can_focus: false,
                                   column_spacing: 18, hexpand: true, vexpand: true,
                                   valign: Gtk.Align.CENTER });
@@ -191,12 +185,10 @@ var ChatPlaceholder = new Lang.Class({
     }
 });
 
-var RoomView = new Lang.Class({
-    Name: 'RoomView',
-    Extends: Gtk.Overlay,
-
+var RoomView = GObject.registerClass(
+class RoomView extends Gtk.Overlay {
     _init(room, sizeGroup) {
-        this.parent();
+        super._init();
 
         let box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
         this.add(box);
@@ -227,7 +219,7 @@ var RoomView = new Lang.Class({
         });
 
         this.show_all();
-    },
+    }
 
     set inputSensitive(sensitive) {
         this._entryArea.sensitive = sensitive;
diff --git a/src/serverRoomManager.js b/src/serverRoomManager.js
index fc65ecd..08717fd 100644
--- a/src/serverRoomManager.js
+++ b/src/serverRoomManager.js
@@ -114,9 +114,7 @@ function _strBaseEqual(str1, str2) {
     return str1.localeCompare(str2, {}, { sensitivity: 'base'}) == 0;
 };
 
-var ServerRoomList = new Lang.Class({
-    Name: 'ServerRoomList',
-    Extends: Gtk.Box,
+var ServerRoomList = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/server-room-list.ui',
     InternalChildren: ['filterEntry',
                        'list',
@@ -129,13 +127,13 @@ var ServerRoomList = new Lang.Class({
                                                         GObject.ParamFlags.READABLE,
                                                        false)
     },
-
+}, class ServerRoomList extends Gtk.Box {
     _init(params) {
         this._account = null;
         this._pendingInfos = [];
         this._filterTerms = [];
 
-        this.parent(params);
+        super._init(params);
 
         this.connect('destroy', () => {
             this.setAccount(null);
@@ -195,7 +193,7 @@ var ServerRoomList = new Lang.Class({
         this._manager = getDefault();
         this._manager.connect('loading-changed',
                               Lang.bind(this, this._onLoadingChanged));
-    },
+    }
 
     get can_join() {
         let canJoin = false;
@@ -205,7 +203,7 @@ var ServerRoomList = new Lang.Class({
             return canJoin;
         });
         return canJoin;
-    },
+    }
 
     get selectedRooms() {
         let rooms = [];
@@ -217,7 +215,7 @@ var ServerRoomList = new Lang.Class({
             rooms.push(this._store.get_value(iter, RoomListColumn.NAME));
         }
         return rooms;
-    },
+    }
 
     setAccount(account) {
         if (this._account == account)
@@ -228,17 +226,17 @@ var ServerRoomList = new Lang.Class({
         this._clearList();
         this._filterEntry.set_text('');
         this._onLoadingChanged(this._manager, account);
-    },
+    }
 
     focusEntry() {
         this._filterEntry.grab_focus();
-    },
+    }
 
     _isCustomRoomItem(iter) {
         let path = this._store.get_path(iter);
         let customPath = this._store.get_path(this._customRoomItem);
         return path.compare(customPath) == 0;
-    },
+    }
 
     _updateCustomRoomName() {
         let newName = this._filterEntry.text.trim();
@@ -260,7 +258,7 @@ var ServerRoomList = new Lang.Class({
         }
 
         this._store.set_value(this._customRoomItem, RoomListColumn.NAME, newName);
-    },
+    }
 
     _updateSelection() {
         if (this._filterEntry.text.trim().length == 0)
@@ -273,7 +271,7 @@ var ServerRoomList = new Lang.Class({
 
         this._list.get_selection().select_iter(iter);
         this._list.scroll_to_cell(model.get_path(iter), null, true, 0.0, 0.0);
-    },
+    }
 
     _clearList() {
         let [valid, iter] = this._store.get_iter_first();
@@ -282,7 +280,7 @@ var ServerRoomList = new Lang.Class({
         this._store.move_before(this._customRoomItem, iter);
         while (this._store.remove(iter))
             ;
-    },
+    }
 
     _onLoadingChanged(mgr, account) {
         if (account != this._account)
@@ -355,13 +353,13 @@ var ServerRoomList = new Lang.Class({
             this._checkSpinner();
             return GLib.SOURCE_REMOVE;
         });
-    },
+    }
 
     _checkSpinner() {
         let loading = this._pendingInfos.length ||
                       (this._account && this._manager.isLoading(this._account));
         this._spinner.active = loading;
-    },
+    }
 
     _toggleChecked(path) {
         let childPath = this._list.model.convert_path_to_child_path(path);
diff --git a/src/telepathyClient.js b/src/telepathyClient.js
index 3c02712..c1a7264 100644
--- a/src/telepathyClient.js
+++ b/src/telepathyClient.js
@@ -1,5 +1,6 @@
 const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
+const GObject = imports.gi.GObject;
 const Polari = imports.gi.Polari;
 const Tp = imports.gi.TelepathyGLib;
 
@@ -107,10 +108,8 @@ class SASLAuthHandler {
     }
 };
 
-var TelepathyClient = new Lang.Class({
-    Name: 'TelepathyClient',
-    Extends: Tp.BaseClient,
-
+var TelepathyClient = GObject.registerClass(
+class TelepathyClient extends Tp.BaseClient {
     _init(params) {
         this._app = Gio.Application.get_default();
         this._app.connect('prepare-shutdown', () => {
@@ -123,7 +122,7 @@ var TelepathyClient = new Lang.Class({
         this._pendingBotPasswords = new Map();
         this._pendingRequests = new Map();
 
-        this.parent(params);
+        super._init(params);
 
         this.set_handler_bypass_approval(false);
         this.set_observer_recover(true);
@@ -137,7 +136,7 @@ var TelepathyClient = new Lang.Class({
         });
         this._accountsMonitor = AccountsMonitor.getDefault();
         this._accountsMonitor.prepare(Lang.bind(this, this._onPrepared));
-    },
+    }
 
     _onPrepared() {
         let actions = [
@@ -199,7 +198,7 @@ var TelepathyClient = new Lang.Class({
                                      Lang.bind(this, this._onNetworkChanged));
         this._onNetworkChanged(this._networkMonitor,
                                this._networkMonitor.network_available);
-    },
+    }
 
     _onNetworkChanged(mon, connected) {
         let presence = connected ? Tp.ConnectionPresenceType.AVAILABLE
@@ -210,7 +209,7 @@ var TelepathyClient = new Lang.Class({
         this._accountsMonitor.enabledAccounts.forEach(a => {
             this._setAccountPresence(a, presence);
         });
-    },
+    }
 
     _onAccountStatusChanged(mon, account) {
         if (account.connection_status != Tp.ConnectionStatus.CONNECTED)
@@ -222,11 +221,11 @@ var TelepathyClient = new Lang.Class({
             else
                 this._connectRooms(account);
         });
-    },
+    }
 
     _connectAccount(account) {
         this._setAccountPresence(account, Tp.ConnectionPresenceType.AVAILABLE);
-    },
+    }
 
     _setAccountPresence(account, presence) {
         let statuses = Object.keys(Tp.ConnectionPresenceType).map(s =>
@@ -245,18 +244,18 @@ var TelepathyClient = new Lang.Class({
                 log('Connection failed: ' + e.message);
             }
         });
-    },
+    }
 
     _connectRooms(account) {
         this._roomManager.rooms.forEach(room => {
             if (account == null || room.account == account)
                 this._connectRoom(room);
         });
-    },
+    }
 
     _connectRoom(room) {
         this._requestChannel(room.account, room.type, room.channel_name, null);
-    },
+    }
 
     _requestChannel(account, targetType, targetId, callback) {
         if (!account || !account.enabled)
@@ -290,7 +289,7 @@ var TelepathyClient = new Lang.Class({
                     callback(channel);
                 this._pendingRequests.delete(roomId);
             });
-    },
+    }
 
     _sendIdentify(account, password) {
         let settings = this._accountsMonitor.getAccountSettings(account);
@@ -321,7 +320,7 @@ var TelepathyClient = new Lang.Class({
                     this._connectRooms(account);
                 });
             });
-    },
+    }
 
     _sendMessage(channel, message) {
         if (!message || !channel)
@@ -336,19 +335,19 @@ var TelepathyClient = new Lang.Class({
                     log('Failed to send message: ' + e.message);
                 }
             });
-    },
+    }
 
     _onConnectAccountActivated(action, parameter) {
         let accountPath = parameter.deep_unpack();
         let account = this._accountsMonitor.lookupAccount(accountPath);
         this._connectAccount(account);
-    },
+    }
 
     _onReconnectAccountActivated(action, parameter) {
         let accountPath = parameter.deep_unpack();
         let account = this._accountsMonitor.lookupAccount(accountPath);
         account.reconnect_async((a, res) => { a.reconnect_finish(res); });
-    },
+    }
 
     _onAuthenticateAccountActivated(action, parameter) {
         let [accountPath, password] = parameter.deep_unpack();
@@ -362,7 +361,7 @@ var TelepathyClient = new Lang.Class({
                 a.reconnect_async(null);
             });
         });
-    },
+    }
 
     _onQueryActivated(action, parameter) {
         let [accountPath, channelName, message, time] = parameter.deep_unpack();
@@ -373,7 +372,7 @@ var TelepathyClient = new Lang.Class({
 
         this._requestChannel(account, Tp.HandleType.CONTACT, channelName,
                              Lang.bind(this, this._sendMessage, message));
-    },
+    }
 
     _onLeaveActivated(action, parameter) {
         let [id, message] = parameter.deep_unpack();
@@ -405,7 +404,7 @@ var TelepathyClient = new Lang.Class({
                 log('Failed to leave channel: ' + e.message);
             }
         });
-    },
+    }
 
     _onSaveIdentifyPasswordActivated(action, parameter) {
         let accountPath = parameter.deep_unpack();
@@ -423,7 +422,7 @@ var TelepathyClient = new Lang.Class({
 
             this._pendingBotPasswords.delete(account.object_path);
         });
-    },
+    }
 
     _saveIdentifySettings(account, data) {
         let settings = this._accountsMonitor.getAccountSettings(account);
@@ -440,22 +439,21 @@ var TelepathyClient = new Lang.Class({
 
         settings.set_string('identify-username', data.username);
         settings.set_boolean('identify-username-supported', data.usernameSupported);
-    },
+    }
 
     _onDiscardIdentifyPasswordActivated(action, parameter) {
         let accountPath = parameter.deep_unpack();
         this._discardIdentifyPassword(accountPath);
-    },
+    }
 
     _discardIdentifyPassword(accountPath) {
         this._pendingBotPasswords.delete(accountPath);
         this._app.withdraw_notification(this._getIdentifyNotificationID(accountPath));
-    },
-
+    }
 
     _isAuthChannel(channel) {
         return channel.channel_type == Tp.IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION;
-    },
+    }
 
     _processRequest(context, connection, channels, processChannel) {
         if (connection.protocol_name != 'irc') {
@@ -478,7 +476,7 @@ var TelepathyClient = new Lang.Class({
             processChannel.call(this, channels[i]);
         }
         context.accept();
-    },
+    }
 
     vfunc_observe_channels(account, connection, channels,
                                      op, requests, context) {
@@ -501,7 +499,7 @@ var TelepathyClient = new Lang.Class({
 
             this._roomManager.ensureRoomForChannel(channel, 0);
         });
-    },
+    }
 
     vfunc_handle_channels(account, connection, channels,
                                     satisfied, userTime, context) {
@@ -519,15 +517,15 @@ var TelepathyClient = new Lang.Class({
             this._roomManager.ensureRoomForChannel(channel, userTime);
             //channel.join_async('', null);
         });
-    },
+    }
 
     _getPendingNotificationID(room, id) {
         return 'pending-message-%s-%d'.format(room.id, id);
-    },
+    }
 
     _getIdentifyNotificationID(accountPath) {
         return 'identify-password-%s'.format(accountPath);
-    },
+    }
 
     _createNotification(room, summary, body) {
         let notification = new Gio.Notification();
@@ -551,7 +549,7 @@ var TelepathyClient = new Lang.Class({
         let param = GLib.Variant.new(paramFormat, params);
         notification.set_default_action_and_target(actionName, param);
         return notification;
-    },
+    }
 
     _onIdentifySent(room, command, username, password) {
         let accountPath = room.account.object_path;
@@ -579,7 +577,7 @@ var TelepathyClient = new Lang.Class({
                                             new GLib.Variant('o', accountPath));
 
         this._app.send_notification(this._getIdentifyNotificationID(accountPath), notification);
-    },
+    }
 
     _onMessageReceived(channel, msg) {
         let [id, ] = msg.get_pending_message_id();
@@ -601,7 +599,7 @@ var TelepathyClient = new Lang.Class({
         let summary = _('%s in %s').format(nick, room.display_name);
         let notification = this._createNotification(room, summary, text);
         this._app.send_notification(this._getPendingNotificationID(room, id), notification);
-    },
+    }
 
     _onPendingMessageRemoved(channel, msg) {
         let [id, valid] = msg.get_pending_message_id();
diff --git a/src/userList.js b/src/userList.js
index 2237f4a..05bfe52 100644
--- a/src/userList.js
+++ b/src/userList.js
@@ -15,12 +15,10 @@ const READWRITE = GObject.ParamFlags.READABLE | GObject.ParamFlags.WRITABLE;
 const MAX_USERS_SHOWN = 8;
 const MAX_USERS_WIDTH_CHARS = 17;
 
-var UserListPopover = new Lang.Class({
-    Name: 'UserListPopover',
-    Extends: Gtk.Popover,
-
+var UserListPopover = GObject.registerClass(
+class UserListPopover extends Gtk.Popover {
     _init(params) {
-        this.parent(params);
+        super._init(params);
 
         this._createWidget();
 
@@ -32,15 +30,15 @@ var UserListPopover = new Lang.Class({
         this._revealer.connect('notify::child-revealed', () => {
             this._revealer.transition_duration = 250;
         });
-    },
+    }
 
     vfunc_realize() {
-        this.parent();
+        super.vfunc_realize();
 
         let toplevel = this.get_toplevel();
         toplevel.connect('notify::active-room',
                          Lang.bind(this, this._activeRoomChanged));
-    },
+    }
 
     _createWidget() {
         this._box = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL,
@@ -59,7 +57,7 @@ var UserListPopover = new Lang.Class({
         this._revealer.add(this._entry);
 
         this._box.show_all();
-    },
+    }
 
     _activeRoomChanged() {
         this._entry.text = '';
@@ -67,7 +65,7 @@ var UserListPopover = new Lang.Class({
         if (this._userList)
             this._userList.destroy();
         this._userList = null;
-    },
+    }
 
     _ensureUserList() {
         if (this._userList)
@@ -83,7 +81,7 @@ var UserListPopover = new Lang.Class({
         this._userList.vadjustment.connect('changed',
                                            Lang.bind(this, this._updateEntryVisibility));
         this._updateEntryVisibility();
-    },
+    }
 
     _updateEntryVisibility() {
         if (!this._userList)
@@ -92,7 +90,7 @@ var UserListPopover = new Lang.Class({
         let reveal = this._entry.text != '' ||
                      this._userList.numRows > MAX_USERS_SHOWN;
         this._revealer.reveal_child = reveal;
-    },
+    }
 
     _updateFilter() {
         if (!this._userList)
@@ -101,9 +99,7 @@ var UserListPopover = new Lang.Class({
     }
 });
 
-var UserDetails = new Lang.Class({
-    Name: 'UserDetails',
-    Extends: Gtk.Frame,
+var UserDetails = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/user-details.ui',
     InternalChildren: ['spinnerBox',
                        'spinner',
@@ -122,7 +118,7 @@ var UserDetails = new Lang.Class({
                                                              'notifications-enabled',
                                                              READWRITE,
                                                              false)},
-
+}, class UserDetails extends Gtk.Frame {
     _init(params = {}) {
         let user = params.user;
         delete params.user;
@@ -132,7 +128,7 @@ var UserDetails = new Lang.Class({
         this._notificationsEnabled = false;
         this._user = null;
 
-        this.parent(params);
+        super._init(params);
 
         this.user = user;
 
@@ -142,11 +138,11 @@ var UserDetails = new Lang.Class({
         this._updateButtonVisibility();
         this._detailsGrid.hide();
         this._notificationLabel.opacity = this.notifications_enabled ? 1. : 0.;
-    },
+    }
 
     get notifications_enabled() {
         return this._notificationsEnabled;
-    },
+    }
 
     set notifications_enabled(value) {
         if (this._notificationsEnabled == value)
@@ -157,7 +153,7 @@ var UserDetails = new Lang.Class({
         this.notify('notifications-enabled');
 
         this._notificationLabel.opacity = value ? 1. : 0.;
-    },
+    }
 
     set user(user) {
         if (this._user == user)
@@ -179,7 +175,7 @@ var UserDetails = new Lang.Class({
         this._updateButtonVisibility();
         this._notificationLabel.visible = this._user == null;
         this._lastLabel.visible = this._user != null;
-    },
+    }
 
     set nickname(nickname) {
         this._nickname = nickname;
@@ -189,11 +185,11 @@ var UserDetails = new Lang.Class({
 
 
         this._updateButtonVisibility();
-    },
+    }
 
     get expanded() {
         return this._expanded;
-    },
+    }
 
     set expanded(v) {
         if (v == this._expanded)
@@ -207,7 +203,7 @@ var UserDetails = new Lang.Class({
             this._unexpand();
 
         this.notify('expanded');
-    },
+    }
 
     _expand() {
         this._detailsGrid.visible = this._initialDetailsLoaded;
@@ -222,7 +218,7 @@ var UserDetails = new Lang.Class({
         //TODO: else use this._nickname to query tracker
         else
             this._revealDetails();
-    },
+    }
 
     _unexpand() {
         this._spinner.stop();
@@ -230,7 +226,7 @@ var UserDetails = new Lang.Class({
         if (this._cancellable)
             this._cancellable.cancel();
         this._cancellable = null;
-    },
+    }
 
     _formatLast(seconds) {
         if (seconds < 60)
@@ -260,7 +256,7 @@ var UserDetails = new Lang.Class({
         let months = days / 30;
         return ngettext("%d month ago",
                         "%d months ago", months).format(months);
-    },
+    }
 
     _onContactInfoReady(c, res) {
         this._initialDetailsLoaded = true;
@@ -287,13 +283,13 @@ var UserDetails = new Lang.Class({
         }
 
         this._revealDetails();
-    },
+    }
 
     _revealDetails() {
         this._spinner.stop();
         this._spinnerBox.hide();
         this._detailsGrid.show();
-    },
+    }
 
     _onMessageButtonClicked() {
         let account = this._user.connection.get_account();
@@ -306,7 +302,7 @@ var UserDetails = new Lang.Class({
                                            this._user.alias,
                                            '',
                                            time ]));
-    },
+    }
 
     _updateButtonVisibility() {
         if (!this._user) {
@@ -325,15 +321,13 @@ var UserDetails = new Lang.Class({
     }
 });
 
-var UserPopover = new Lang.Class({
-    Name: 'UserPopover',
-    Extends: Gtk.Popover,
+var UserPopover = GObject.registerClass({
     Template: 'resource:///org/gnome/Polari/ui/user-popover.ui',
     InternalChildren: ['nickLabel',
                        'statusLabel',
                        'notifyButton',
                        'userDetails'],
-
+}, class UserPopover extends Gtk.Popover {
     _init(params) {
         this._room = params.room;
         delete params.room;
@@ -344,7 +338,7 @@ var UserPopover = new Lang.Class({
         this._nickname = null;
         this._basenick = null;
 
-        this.parent(params);
+        super._init(params);
 
         this._nickLabel.set_state_flags(Gtk.StateFlags.LINK, false);
 
@@ -359,7 +353,7 @@ var UserPopover = new Lang.Class({
         });
 
         this.show();
-    },
+    }
 
     set nickname(nickname) {
         if (this._nickname == nickname)
@@ -376,7 +370,7 @@ var UserPopover = new Lang.Class({
         this._notifyButton.action_name = actionName;
 
         this._setBasenick(Polari.util_get_basenick(nickname));
-    },
+    }
 
     _setBasenick(basenick) {
         if (this._basenick == basenick)
@@ -402,11 +396,11 @@ var UserPopover = new Lang.Class({
 
         this._onStatusChanged();
         this._updateDetailsContact();
-    },
+    }
 
     get nickname() {
         return this._nickname;
-    },
+    }
 
     _onStatusChanged() {
         let status = this._userTracker.getNickStatus(this._nickname);
@@ -423,25 +417,23 @@ var UserPopover = new Lang.Class({
         this._statusLabel.label = label;
 
         this._nickLabel.sensitive = (status == Tp.ConnectionPresenceType.AVAILABLE);
-    },
+    }
 
     _updateDetailsContact() {
         this._userDetails.user = this._userTracker.lookupContact(this._nickname);
-     },
+     }
 
     _onNickStatusChanged(baseNick, status) {
         this._onStatusChanged();
     }
 });
 
-var UserListRow = new Lang.Class({
-    Name: 'UserListRow',
-    Extends: Gtk.ListBoxRow,
-
+const UserListRow = GObject.registerClass(
+class UserListRow extends Gtk.ListBoxRow {
     _init(user) {
         this._user = user;
 
-        this.parent();
+        super._init();
 
         this._createWidget();
 
@@ -453,21 +445,21 @@ var UserListRow = new Lang.Class({
 
         this._revealer.connect('notify::reveal-child',
                                Lang.bind(this, this._onExpandedChanged));
-    },
+    }
 
     get user() {
         return this._user;
-    },
+    }
 
     get expand() {
         return this._revealer.reveal_child;
-    },
+    }
 
     set expand(expand) {
         if (expand)
             this._ensureDetails();
         this._revealer.reveal_child = expand;
-    },
+    }
 
     _createWidget() {
         let vbox = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
@@ -494,7 +486,7 @@ var UserListRow = new Lang.Class({
         vbox.add(this._revealer);
 
         this.show_all();
-    },
+    }
 
     _ensureDetails() {
         if (this._revealer.get_child())
@@ -505,16 +497,16 @@ var UserListRow = new Lang.Class({
         this._revealer.bind_property('reveal-child', details, 'expanded', 0);
 
         this._revealer.add(details);
-    },
+    }
 
     shouldShow() {
         return this._user.alias.toLowerCase().indexOf(this._filter) != -1;
-    },
+    }
 
     setFilter(filter) {
         this._filter = filter.toLowerCase();
         this._updateLabel();
-    },
+    }
 
     _updateLabel() {
         let filterIndex = -1;
@@ -529,14 +521,14 @@ var UserListRow = new Lang.Class({
             let postMatch = this._user.alias.substring(filterIndex + this._filter.length);
             this._label.label = preMatch + '<b>' + theMatch + '</b>' + postMatch;
         }
-    },
+    }
 
     _updateArrowVisibility() {
         let flags = this.get_state_flags();
         this._arrow.visible = this.expand ||
                               flags & Gtk.StateFlags.PRELIGHT ||
                               flags & Gtk.StateFlags.FOCUSED;
-    },
+    }
 
     _onExpandedChanged() {
         if (this._revealer.reveal_child) {
@@ -550,12 +542,10 @@ var UserListRow = new Lang.Class({
     }
 });
 
-var UserList = new Lang.Class({
-    Name: 'UserList',
-    Extends: Gtk.ScrolledWindow,
-
+var UserList = GObject.registerClass(
+class UserList extends Gtk.ScrolledWindow {
     _init(room) {
-        this.parent({ hexpand: true,
+        super._init({ hexpand: true,
                       shadow_type: Gtk.ShadowType.ETCHED_IN,
                       hscrollbar_policy: Gtk.PolicyType.NEVER,
                       propagate_natural_width: true });
@@ -625,22 +615,22 @@ var UserList = new Lang.Class({
         this._onChannelChanged(room);
 
         this.show_all();
-    },
+    }
 
     get numRows() {
         return Object.keys(this._rows).length;
-    },
+    }
 
     _onDestroy() {
         for (let i = 0; i < this._roomSignals.length; i++)
             this._room.disconnect(this._roomSignals[i]);
         this._roomSignals = [];
-    },
+    }
 
     setFilter(filter) {
         this._filter = filter;
         this._list.invalidate_filter();
-    },
+    }
 
     _updateContentHeight() {
         if (this._updateHeightId != 0)
@@ -664,24 +654,24 @@ var UserList = new Lang.Class({
             this._updateHeightId = 0;
             return GLib.SOURCE_REMOVE;
         });
-    },
+    }
 
     _onMemberRenamed(room, oldMember, newMember) {
         this._removeMember(oldMember);
         this._addMember(newMember);
-    },
+    }
 
     _onMemberRemoved(room, member) {
         this._removeMember(member);
-    },
+    }
 
     _onMemberJoined(room, member) {
         this._addMember(member);
-    },
+    }
 
     _onMembersChanged(room) {
         this._counterLabel.label = this.numRows.toString();
-    },
+    }
 
     _onChannelChanged(room) {
         this._list.foreach(w => { w.destroy(); });
@@ -693,40 +683,40 @@ var UserList = new Lang.Class({
         let members = room.channel.group_dup_members_contacts();
         for (let i = 0; i < members.length; i++)
             this._addMember(members[i]);
-    },
+    }
 
     _addMember(member) {
         let row = new UserListRow(member);
         this._rows[member] = row;
         this._list.add(row);
-    },
+    }
 
     _removeMember(member) {
         let row = this._rows[member];
         if (row)
             row.destroy();
         delete this._rows[member];
-    },
+    }
 
     _setActiveRow(row) {
         if (this._activeRow && this._activeRow != row)
             this._activeRow.expand = false;
         this._activeRow = row;
-    },
+    }
 
     _onRowActivated(list, row) {
         this._setActiveRow(row);
         this._activeRow.expand = !this._activeRow.expand;
-    },
+    }
 
     _sort(row1, row2) {
         return row1.user.alias.localeCompare(row2.user.alias);
-    },
+    }
 
     _filterRows(row) {
         row.setFilter(this._filter);
         return row.shouldShow();
-    },
+    }
 
     _updateHeader(row, before) {
         if (before) {
diff --git a/src/userTracker.js b/src/userTracker.js
index f3e0ca1..b0506a6 100644
--- a/src/userTracker.js
+++ b/src/userTracker.js
@@ -49,10 +49,7 @@ class UserStatusMonitor {
 };
 
 
-var UserTracker = new Lang.Class({
-    Name: 'UserTracker',
-    Extends: GObject.Object,
-
+var UserTracker = GObject.registerClass({
     Signals: {
         'status-changed': {
             flags: GObject.SignalFlags.DETAILED,
@@ -62,10 +59,10 @@ var UserTracker = new Lang.Class({
             flags: GObject.SignalFlags.DETAILED,
             param_types: [GObject.TYPE_STRING]
         }
-    },
-
+    }
+}, class UserTracker extends GObject.Object {
     _init(account) {
-        this.parent();
+        super._init();
 
         this._account = account;
 
@@ -79,24 +76,24 @@ var UserTracker = new Lang.Class({
         this._roomManager = RoomManager.getDefault();
         this._roomManager.connect('room-added', Lang.bind(this, this._onRoomAdded));
         this._roomManager.connect('room-removed', Lang.bind(this, this._onRoomRemoved));
-    },
+    }
 
     _onShutdown() {
         for (let room of this._roomData.keys())
             this._onRoomRemoved(this._roomManager, room);
-    },
+    }
 
     _getRoomContacts(room) {
         return this._roomData.get(room).contactMapping;
-    },
+    }
 
     _getRoomHandlers(room) {
         return this._roomData.get(room).handlerMapping;
-    },
+    }
 
     _getRoomSignals(room) {
         return this._roomData.get(room).roomSignals;
-    },
+    }
 
     _onRoomAdded(roomManager, room) {
         if (room.account != this._account)
@@ -125,7 +122,7 @@ var UserTracker = new Lang.Class({
         roomSignals.forEach(signal => {
             signalIds.push(room.connect(signal.name, signal.handler));
         });
-    },
+    }
 
     _onRoomRemoved(roomManager, room) {
         if (!this._roomData.has(room))
@@ -134,7 +131,7 @@ var UserTracker = new Lang.Class({
         this._getRoomSignals(room).forEach(id => { room.disconnect(id); });
         this._clearUsersFromRoom(room);
         this._roomData.delete(room);
-    },
+    }
 
     _onChannelChanged(room) {
         if (!room.channel) {
@@ -151,13 +148,13 @@ var UserTracker = new Lang.Class({
         /*keep track of initial members in the room, both locally and
         globally*/
         members.forEach(m => { this._trackMember(m, room); });
-    },
+    }
 
     _clearUsersFromRoom(room) {
         let map = this._getRoomContacts(room);
         for (let [baseNick, contacts] of map)
             contacts.slice().forEach((m) => { this._untrackMember(m, room); });
-    },
+    }
 
     _ensureRoomMappingForRoom(room) {
         if (this._roomData.has(room))
@@ -165,20 +162,20 @@ var UserTracker = new Lang.Class({
         this._roomData.set(room, { contactMapping: new Map(),
                                    handlerMapping: new Map(),
                                    roomSignals: [] });
-    },
+    }
 
     _onMemberRenamed(room, oldMember, newMember) {
         this._untrackMember(oldMember, room);
         this._trackMember(newMember, room);
-    },
+    }
 
     _onMemberJoined(room, member) {
         this._trackMember(member, room);
-    },
+    }
 
     _onMemberLeft(room, member) {
         this._untrackMember(member, room);
-    },
+    }
 
     _runHandlers(room, member, status) {
         let baseNick = Polari.util_get_basenick(member.alias);
@@ -186,14 +183,14 @@ var UserTracker = new Lang.Class({
         for (let [id, info] of roomHandlers)
             if (!info.nickName || info.nickName == baseNick)
                 info.handler(baseNick, status);
-    },
+    }
 
     _pushMember(map, baseNick, member) {
         if (!map.has(baseNick))
             map.set(baseNick, []);
         let contacts = map.get(baseNick);
         return contacts.push(member);
-    },
+    }
 
     _trackMember(member, room) {
         let baseNick = Polari.util_get_basenick(member.alias);
@@ -220,7 +217,7 @@ var UserTracker = new Lang.Class({
         }
 
         this.emit("contacts-changed::" + baseNick, member.alias);
-    },
+    }
 
     _popMember(map, baseNick, member) {
         let contacts = map.get(baseNick) || [];
@@ -229,7 +226,7 @@ var UserTracker = new Lang.Class({
             return [false, contacts.length];
         contacts.splice(index, 1);
         return [true, contacts.length];
-    },
+    }
 
     _untrackMember(member, room) {
         let baseNick = Polari.util_get_basenick(member.alias);
@@ -257,7 +254,7 @@ var UserTracker = new Lang.Class({
             }
             this.emit("contacts-changed::" + baseNick, member.alias);
         }
-    },
+    }
 
     getNickStatus(nickName) {
         let baseNick = Polari.util_get_basenick(nickName);
@@ -265,7 +262,7 @@ var UserTracker = new Lang.Class({
         let contacts = this._baseNickContacts.get(baseNick) || [];
         return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
                                     : Tp.ConnectionPresenceType.AVAILABLE;
-    },
+    }
 
     getNickRoomStatus(nickName, room) {
         let baseNick = Polari.util_get_basenick(nickName);
@@ -275,7 +272,7 @@ var UserTracker = new Lang.Class({
         let contacts = this._getRoomContacts(room).get(baseNick) || [];
         return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
                                     : Tp.ConnectionPresenceType.AVAILABLE;
-    },
+    }
 
     lookupContact(nickName) {
         let baseNick = Polari.util_get_basenick(nickName);
@@ -289,7 +286,7 @@ var UserTracker = new Lang.Class({
                 return contacts[i];
 
         return contacts[0];
-    },
+    }
 
     watchRoomStatus(room, baseNick, callback) {
         this._ensureRoomMappingForRoom(room);
@@ -300,13 +297,13 @@ var UserTracker = new Lang.Class({
         });
 
         return this._handlerCounter;
-    },
+    }
 
     unwatchRoomStatus(room, handlerID) {
         if (!this._roomData.has(room))
             return;
         this._getRoomHandlers(room).delete(handlerID);
-    },
+    }
 
     _notifyNickAvailable (member, room) {
         let notification = new Gio.Notification();
@@ -322,27 +319,27 @@ var UserTracker = new Lang.Class({
         this._app.send_notification(this._getNotifyActionNameInternal(member.alias), notification);
 
         let baseNick = Polari.util_get_basenick(member.alias);
-    },
+    }
 
     _shouldNotifyNick(nickName) {
         let actionName = this._getNotifyActionNameInternal(nickName);
         let state = this._app.get_action_state(actionName);
         return state ? state.get_boolean()
                      : false;
-    },
+    }
 
     _setNotifyActionEnabled(nickName, enabled) {
         let name = this._getNotifyActionNameInternal(nickName);
         let action = this._app.lookup_action(name);
         if (action)
             action.enabled = enabled;
-    },
+    }
 
     _getNotifyActionNameInternal(nickName) {
         return 'notify-user-' +
                this._account.get_path_suffix() + '-' +
                Polari.util_get_basenick(nickName);
-    },
+    }
 
     getNotifyActionName(nickName) {
         let name = this._getNotifyActionNameInternal(nickName);


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