/** * ident_switch - Account switcher UI and new mail notifications. * * Places the hidden onchange). */ var ident_switch_switching = false; function plugin_switchIdent_switch(val) { if (ident_switch_switching) return; ident_switch_switching = true; rcmail.env.unread_counts = {}; rcmail.http_post('plugin.ident_switch.switch', { '_ident-id': val, '_mbox': rcmail.env.mailbox }); } /** * Update per-account counts in select options and total badge. * * Each entry in data is {unseen: N, baseline: B}. * - Option text: "account (baseline+delta)" when delta > 0, else "account (unseen)" * - Badge: sum of deltas across all accounts (new messages not yet visited). * * @param {Object} data - Map of iid to {unseen, baseline}. */ function ident_switch_updateCounts(data) { var map = rcmail.env.ident_switch_iid_map || {}; var $select = $('#plugin-ident_switch-account'); var totalDelta = 0; // Reset all options to original text $select.find('option').each(function() { var orig = $(this).data('orig-text'); if (orig) { $(this).text(orig); } }); // On mail task, skip count for the active account (already shown in folder list) var selectedVal = rcmail.env.task === 'mail' ? $select.val() : null; // Update each option with its count for (var iid in data) { if (!data.hasOwnProperty(iid)) continue; var info = data[iid]; var unseen = parseInt(info.unseen) || 0; var baseline = parseInt(info.baseline) || 0; var delta = Math.max(0, unseen - baseline); totalDelta += delta; if (map[iid] === undefined) continue; var selectVal = '' + map[iid]; var $opt = $select.find('option').filter(function() { return $(this).val() === selectVal; }); if (!$opt.length) continue; // Skip active account on mail task if (selectVal === selectedVal) continue; var suffix; if (delta > 0) { suffix = ' (' + baseline + '+' + delta + ')'; } else if (unseen > 0) { suffix = ' (' + unseen + ')'; } else { suffix = ''; } if (suffix) { $opt.text($opt.data('orig-text') + suffix); } } // Update total badge (only new messages not yet visited) var $badge = $('#ident-switch-badge'); if (totalDelta > 0) { $badge.text(totalDelta).show(); } else { $badge.hide().text(''); } } /** * Handle new mail notification from server. * @param {Object} data - {iid, label, count, basic, sound, desktop} */ function ident_switch_onNotify(data) { if (data.basic) { ident_switch_notifyBasic(); } if (data.sound) { ident_switch_notifySound(); } if (data.desktop) { ident_switch_notifyDesktop(data.label, data.count); } } /** * Basic notification: change page title. */ function ident_switch_notifyBasic() { var marker = '(*) '; if (document.title.indexOf(marker) !== 0) { document.title = marker + document.title; } } /** * Sound notification: play newmail_notifier sound. */ function ident_switch_notifySound() { var src = rcmail.assets_path('plugins/newmail_notifier/sound'); try { new Audio(src + '.mp3').play().catch(function() { new Audio(src + '.wav').play().catch(function() {}); }); } catch(e) {} } /** * Desktop notification via Notification API. */ function ident_switch_notifyDesktop(label, count) { if (!('Notification' in window)) { return; } if (Notification.permission === 'default') { Notification.requestPermission(); return; } if (Notification.permission !== 'granted') { return; } var body = count + ' unread message' + (count > 1 ? 's' : ''); var popup = new Notification('New mail — ' + label, { body: body, tag: 'ident_switch_' + label, icon: rcmail.assets_path('plugins/ident_switch/mail.png') }); var timeout = (rcmail.env.newmail_notifier_timeout || 10) * 1000; setTimeout(function() { popup.close(); }, timeout); } /** * Fix identity selection in compose view when impersonating. */ function plugin_switchIdent_fixIdent(iid) { if (parseInt(iid) > 0) { $('#_from').val(iid); } } /** * Filter compose From dropdown to only show identities for the active account. * Removes options whose identity_id is not in ident_switch_allowed_identities. */ function plugin_switchIdent_filterFrom() { var allowed = rcmail.env.ident_switch_allowed_identities; if (!allowed || !allowed.length) { return; } var $from = $('#_from'); if (!$from.length) { return; } var currentVal = parseInt($from.val()); $from.find('option').each(function() { if (allowed.indexOf(parseInt($(this).val())) === -1) { $(this).remove(); } }); // If selected option was removed, select the first remaining var $remaining = $from.find('option:first'); if (allowed.indexOf(currentVal) === -1 && $remaining.length) { $from.val($remaining.val()).trigger('change'); } } // Filter compose From dropdown on page load $(function() { plugin_switchIdent_filterFrom(); });