diff --git a/extension.js b/extension.js index 0083cf0..0ad1f92 100644 --- a/extension.js +++ b/extension.js @@ -26,14 +26,24 @@ const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); const Convenience = Me.imports.convenience; const Indicator = Me.imports.indicator; +const Opts = Me.imports.opts; const AVATAR_ICON_SIZE = 38; -const SHOW_AVATARS_KEY = 'show-avatars'; -const MAX_VISIBLE_MAILS_KEY = 'max-visible-mails'; -const SHOW_DATES_KEY = 'show-dates'; -const GROUP_BY_ACCOUNT_KEY = 'group-by-account' -const REMOVE_INDICATOR_KEY = 'remove-indicator'; +const SHOW_AVATARS_KEY = 'show-avatars'; +const MAX_VISIBLE_MAILS_KEY = 'max-visible-mails'; +const SHOW_DATES_KEY = 'show-dates'; +const SHOW_MARK_ALL_AS_READ_BUTTON_KEY = 'show-mark-all-as-read-button'; +const SHOW_CHECK_FOR_MAIL_BUTTON_KEY = 'show-check-for-mail-button'; +const SHOW_SETTINGS_BUTTON_KEY = 'show-settings-button'; +const GROUP_BY_ACCOUNT_KEY = 'group-by-account'; +const REMOVE_INDICATOR_KEY = 'remove-indicator'; + +const KeyActionMap = new Map([ + [ SHOW_MARK_ALL_AS_READ_BUTTON_KEY, Opts.ACTION_FLAGS.MARK_ALL_AS_READ ], + [ SHOW_CHECK_FOR_MAIL_BUTTON_KEY, Opts.ACTION_FLAGS.CHECK_FOR_MAIL ], + [ SHOW_SETTINGS_BUTTON_KEY, Opts.ACTION_FLAGS.SETTINGS ] +]); const MailnagIface = '\ @@ -64,14 +74,10 @@ const MailnagDbus = Gio.DBusProxy.makeProxyWrapper(MailnagIface); const MailnagExtension = new Lang.Class({ Name: 'MailnagExtension', - _init: function(maxVisibleMails, showDates, groupByAccount, removeIndicator, avatars) { + _init: function(options) { this._mails = []; - this._avatars = avatars; - this._maxVisibleMails = maxVisibleMails; - this._showDates = showDates; - this._groupByAccount = groupByAccount; - this._removeIndicator = removeIndicator; + this._opts = options; this._indicator = null; this._proxy = new MailnagDbus(Gio.DBus.session, @@ -92,7 +98,7 @@ const MailnagExtension = new Lang.Class({ this._proxy.GetMailsRemote(Lang.bind(this, function([mails], error) { if (!error) { - if ((mails.length > 0) || !this._removeIndicator) { + if ((mails.length > 0) || !this._opts.removeIndicator) { this._handle_new_mails(mails, mails); } } @@ -109,7 +115,7 @@ const MailnagExtension = new Lang.Class({ this._mails = []; if (this._indicator != null) { - if ((this._mails.length == 0) && this._removeIndicator) { + if ((this._mails.length == 0) && this._opts.removeIndicator) { this._destroyIndicator(); } else { this._indicator.setMails(this._mails); @@ -129,10 +135,7 @@ const MailnagExtension = new Lang.Class({ }, _createIndicator: function() { - this._indicator = new Indicator.MailnagIndicator( - this._maxVisibleMails, this._showDates, - this._groupByAccount, this._avatars, AVATAR_ICON_SIZE, this); - + this._indicator = new Indicator.MailnagIndicator(this._opts, this); this._indicator.setMails(this._mails); Main.panel.addToStatusArea('mailnag-indicator', this._indicator, 0); }, @@ -170,7 +173,7 @@ const MailnagExtension = new Lang.Class({ }); // Update Panel Indicator - if ((this._mails.length == 0) && this._removeIndicator) { + if ((this._mails.length == 0) && this._opts.removeIndicator) { this._destroyIndicator(); } else { if (this._indicator != null) @@ -193,7 +196,7 @@ const MailnagExtension = new Lang.Class({ this._mails = []; - if (this._removeIndicator) { + if (this._opts.removeIndicator) { this._destroyIndicator(); } else { if (this._indicator != null) @@ -275,12 +278,23 @@ function aggregateAvatarsAsync(completedCallback) { } function createExt(s, avatars) { - return new MailnagExtension( - s.get_int(MAX_VISIBLE_MAILS_KEY), - s.get_boolean(SHOW_DATES_KEY), - s.get_boolean(GROUP_BY_ACCOUNT_KEY), - s.get_boolean(REMOVE_INDICATOR_KEY), - avatars); + + let opts = new Opts.Options(); + + opts.maxVisibleMails = s.get_int(MAX_VISIBLE_MAILS_KEY); + opts.showDates = s.get_boolean(SHOW_DATES_KEY); + opts.groupMailsByAccount = s.get_boolean(GROUP_BY_ACCOUNT_KEY); + opts.removeIndicator = s.get_boolean(REMOVE_INDICATOR_KEY); + opts.avatars = avatars; + opts.avatarSize = AVATAR_ICON_SIZE; + opts.menuActions = Opts.ACTION_FLAGS.NONE; + + for ([k, v] of KeyActionMap) { + if (s.get_boolean(k)) + opts.menuActions |= v; + } + + return new MailnagExtension(opts); } let ext = null; diff --git a/indicator.js b/indicator.js index 8e50c04..39024a3 100644 --- a/indicator.js +++ b/indicator.js @@ -29,6 +29,7 @@ const Mainloop = imports.mainloop; const ExtensionUtils = imports.misc.extensionUtils; const Me = ExtensionUtils.getCurrentExtension(); const Utils = Me.imports.utils; +const Opts = Me.imports.opts; const INDICATOR_ICON = 'mail-unread-symbolic' const INACTIVE_ITEM = { reactive: true, can_focus: false, activate: false, hover: false }; @@ -161,13 +162,9 @@ const MailnagIndicator = new Lang.Class({ Name: 'MailnagIndicator', Extends: PanelMenu.Button, - _init: function(maxVisibleMails, showDates, groupByAccount, avatars, avatarSize, extension) { + _init: function(options, extension) { this.parent(0.0, this.Name); - this._maxVisisbleMails = maxVisibleMails; - this._showDates = showDates; - this._groupByAccount = groupByAccount; - this._avatars = avatars; - this._avatarSize = avatarSize; + this._opts = options; this._extension = extension; this._icon = new St.Icon({ @@ -231,16 +228,16 @@ const MailnagIndicator = new Lang.Class({ this.menu.removeAll(); if (mails.length > 0) { - let maxMails = (mails.length <= this._maxVisisbleMails) ? - mails.length : this._maxVisisbleMails; + let maxMails = (mails.length <= this._opts.maxVisibleMails) ? + mails.length : this._opts.maxVisibleMails; - if (this._groupByAccount && (mails[0]['account_name'] != undefined)) { + if (this._opts.groupMailsByAccount && (mails[0]['account_name'] != undefined)) { this._addGroupedMailItems(this.menu, mails, maxMails); } else { this._addMailItems(this.menu, mails, maxMails); - if (mails.length > this._maxVisisbleMails) { - let str = _("(and {0} more)").replace("{0}", (mails.length - this._maxVisisbleMails)); + if (mails.length > this._opts.maxVisibleMails) { + let str = _("(and {0} more)").replace("{0}", (mails.length - this._opts.maxVisibleMails)); item = new PopupMenu.PopupBaseMenuItem(INACTIVE_ITEM); item.actor.add_child(new St.Label({ text: str, style_class: 'more-label' })); @@ -248,48 +245,61 @@ const MailnagIndicator = new Lang.Class({ } } - this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()) + if (this._opts.menuActions != Opts.ACTION_FLAGS.NONE) + this.menu.addMenuItem(new PopupMenu.PopupSeparatorMenuItem()) - item = new PopupMenu.PopupMenuItem(_("Mark All As Read")); - item.connect('activate', Lang.bind(this, function() { - // We call markAllMailsAsRead() on the mainloop (deferred) - // because it will cause the menu to be rebuilt - // (the 'activate' event is closing the menu and - // rebuilding it while it is being closed, somehow - // reopens the menu). - Mainloop.idle_add(Lang.bind(this, function() { - this._extension.markAllMailsAsRead(); - return false; + if (this._opts.menuActions & Opts.ACTION_FLAGS.MARK_ALL_AS_READ) { + item = new PopupMenu.PopupMenuItem(_("Mark All As Read")); + item.connect('activate', Lang.bind(this, function() { + // We call markAllMailsAsRead() on the mainloop (deferred) + // because it will cause the menu to be rebuilt + // (the 'activate' event is closing the menu and + // rebuilding it while it is being closed, somehow + // reopens the menu). + Mainloop.idle_add(Lang.bind(this, function() { + this._extension.markAllMailsAsRead(); + return false; + })); })); + this.menu.addMenuItem(item); + } + } + + if (this._opts.menuActions & Opts.ACTION_FLAGS.CHECK_FOR_MAIL) { + item = new PopupMenu.PopupMenuItem(_("Check For Mail")); + item.connect('activate', Lang.bind(this, function() { + this._extension.checkForMails(); })); this.menu.addMenuItem(item); } - item = new PopupMenu.PopupMenuItem(_("Check For Mail")); - item.connect('activate', Lang.bind(this, function() { - this._extension.checkForMails(); - })); - this.menu.addMenuItem(item); - - this._addSettingsSubmenu(this.menu); + if (this._opts.menuActions & Opts.ACTION_FLAGS.SETTINGS) + this._addSettingsSubmenu(this.menu); - // Fix hover effect of the focused mail menu-item after menu rebuild - let [x, y] = global.get_pointer(); - let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); - if ((actor != null) && (actor.isMailnagMailItem)) { - actor.hover = true; - } + if (this.menu.isOpen) { + if (mails.length == 0) { + // It the menu is open and the last mail was removed by the user, + // close the menu. + this.menu.close(); + } else { + // Fix hover effect of the focused mail menu-item after menu rebuild + let [x, y] = global.get_pointer(); + let actor = global.stage.get_actor_at_pos(Clutter.PickMode.REACTIVE, x, y); + if ((actor != null) && (actor.isMailnagMailItem)) { + actor.hover = true; + } - // If the menu is open, set the key-focus on the panel icon - // so the focus won't get lost if a mail was removed via the delete key. - if (this.menu.isOpen) - this.actor.grab_key_focus(); + // If the menu is open, set the key-focus on the panel icon + // so the focus won't get lost if a mail was removed via the delete key. + this.actor.grab_key_focus(); + } + } }, _addMailItems: function(menu, mails, maxMails) { for (let i = 0; i < maxMails; i++) { - let item = new IndicatorMailMenuItem(mails[i], this._avatars, - this._avatarSize, this._showDates, this._extension); + let item = new IndicatorMailMenuItem(mails[i], this._opts.avatars, + this._opts.avatarSize, this._opts.showDates, this._extension); menu.addMenuItem(item); } diff --git a/opts.js b/opts.js new file mode 100644 index 0000000..fd37040 --- /dev/null +++ b/opts.js @@ -0,0 +1,41 @@ +/* Mailnag - GNOME-Shell extension frontend +* +* Copyright 2016 Patrick Ulbrich +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +* MA 02110-1301, USA. +*/ + +const Lang = imports.lang; + +const ACTION_FLAGS = { + NONE : 0, + MARK_ALL_AS_READ : 1, + CHECK_FOR_MAIL : 2, + SETTINGS : 4, + ALL : 7 +}; + +const Options = new Lang.Class({ + Name: 'Options', + + maxVisibleMails : 10, + showDates : true, + groupMailsByAccount : false, + removeIndicator : true, + avatars : {}, + avatarSize : 38, + menuActions : ACTION_FLAGS.ALL +}); diff --git a/prefs.js b/prefs.js index 111a053..63f6ebc 100644 --- a/prefs.js +++ b/prefs.js @@ -55,25 +55,33 @@ const MailnagSettingsWidget = new GObject.Class({ box.add(spinbtn); this.add(box); - let checkbtn_avatars = new Gtk.CheckButton( { label: _("Show avatars") } ); - settings.bind('show-avatars', checkbtn_avatars, 'active', Gio.SettingsBindFlags.DEFAULT); + let checkbtn_remove = new Gtk.CheckButton( { label: _('Remove indicator icon if maillist is empty') } ); + settings.bind('remove-indicator', checkbtn_remove, 'active', Gio.SettingsBindFlags.DEFAULT); + this.add(checkbtn_remove); + let checkbtn_group = new Gtk.CheckButton( { label: _('Group mails by account') } ); + settings.bind('group-by-account', checkbtn_group, 'active', Gio.SettingsBindFlags.DEFAULT); + this.add(checkbtn_group); + + let checkbtn_avatars = new Gtk.CheckButton( { label: _('Show avatars') } ); + settings.bind('show-avatars', checkbtn_avatars, 'active', Gio.SettingsBindFlags.DEFAULT); this.add(checkbtn_avatars); - let checkbtn_dates = new Gtk.CheckButton( { label: _("Show dates") } ); + let checkbtn_dates = new Gtk.CheckButton( { label: _('Show dates') } ); settings.bind('show-dates', checkbtn_dates, 'active', Gio.SettingsBindFlags.DEFAULT); - this.add(checkbtn_dates); - let checkbtn_group = new Gtk.CheckButton( { label: _("Group mails by account") } ); - settings.bind('group-by-account', checkbtn_group, 'active', Gio.SettingsBindFlags.DEFAULT); - - this.add(checkbtn_group); + let checkbtn_mark = new Gtk.CheckButton( { label: _('Show Mark-All-As-Read button') } ); + settings.bind('show-mark-all-as-read-button', checkbtn_mark, 'active', Gio.SettingsBindFlags.DEFAULT); + this.add(checkbtn_mark); - let checkbtn_remove = new Gtk.CheckButton( { label: _("Remove indicator icon if maillist is empty") } ); - settings.bind('remove-indicator', checkbtn_remove, 'active', Gio.SettingsBindFlags.DEFAULT); + let checkbtn_check = new Gtk.CheckButton( { label: _('Show Check-For-Mail button') } ); + settings.bind('show-check-for-mail-button', checkbtn_check, 'active', Gio.SettingsBindFlags.DEFAULT); + this.add(checkbtn_check); - this.add(checkbtn_remove); + let checkbtn_settings = new Gtk.CheckButton( { label: _('Show Settings button') } ); + settings.bind('show-settings-button', checkbtn_settings, 'active', Gio.SettingsBindFlags.DEFAULT); + this.add(checkbtn_settings); } }); diff --git a/schemas/org.gnome.shell.extensions.mailnag.gschema.xml b/schemas/org.gnome.shell.extensions.mailnag.gschema.xml index 99fac68..a9720d1 100644 --- a/schemas/org.gnome.shell.extensions.mailnag.gschema.xml +++ b/schemas/org.gnome.shell.extensions.mailnag.gschema.xml @@ -11,6 +11,21 @@ Show dates Show labels indicating the date of a mail + + true + Show Mark-All-As-Read button + Show a button to mark all mails as read + + + true + Show Check-For-Mail-Button + Show a button to check for mail + + + true + Show Settings button + Show a button to open a settings submenu + true Remove indicator icon