Skip to content

Commit

Permalink
Make all menu actions optional, merge options into an options object
Browse files Browse the repository at this point in the history
* Make all menu actions (mark-as-read, check-for-mail, settings) optional
* Merge options into an options object instead of passing them individually
* Other fixes
  • Loading branch information
pulb committed Mar 20, 2016
1 parent acdb060 commit 94e7afd
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 77 deletions.
64 changes: 39 additions & 25 deletions extension.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
'<node>\
Expand Down Expand Up @@ -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,
Expand All @@ -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);
}
}
Expand All @@ -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);
Expand All @@ -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);
},
Expand Down Expand Up @@ -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)
Expand All @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
92 changes: 51 additions & 41 deletions indicator.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down Expand Up @@ -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({
Expand Down Expand Up @@ -231,65 +228,78 @@ 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' }));

this.menu.addMenuItem(item);
}
}

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);
}
Expand Down
41 changes: 41 additions & 0 deletions opts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/* Mailnag - GNOME-Shell extension frontend
*
* Copyright 2016 Patrick Ulbrich <[email protected]>
*
* 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
});
30 changes: 19 additions & 11 deletions prefs.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
});

Expand Down
15 changes: 15 additions & 0 deletions schemas/org.gnome.shell.extensions.mailnag.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@
<summary>Show dates</summary>
<description>Show labels indicating the date of a mail</description>
</key>
<key type="b" name="show-mark-all-as-read-button">
<default>true</default>
<summary>Show Mark-All-As-Read button</summary>
<description>Show a button to mark all mails as read</description>
</key>
<key type="b" name="show-check-for-mail-button">
<default>true</default>
<summary>Show Check-For-Mail-Button</summary>
<description>Show a button to check for mail</description>
</key>
<key type="b" name="show-settings-button">
<default>true</default>
<summary>Show Settings button</summary>
<description>Show a button to open a settings submenu</description>
</key>
<key type="b" name="remove-indicator">
<default>true</default>
<summary>Remove indicator icon</summary>
Expand Down

0 comments on commit 94e7afd

Please sign in to comment.