/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ Components.utils.import("resource://gre/modules/Services.jsm"); Components.utils.import("resource:///modules/cloudFileAccounts.js"); var kUploadNotificationValue = "bigAttachmentUploading"; var kPrivacyWarningNotificationValue = "bigAttachmentPrivacyWarning"; var gBigFileObserver = { bigFiles: [], sessionHidden: false, privacyWarned: false, get hidden() { return this.sessionHidden || !Services.prefs.getBoolPref("mail.cloud_files.enabled") || !Services.prefs.getBoolPref("mail.compose.big_attachments.notify") || Services.io.offline; }, hide: function(aPermanent) { if (aPermanent) Services.prefs.setBoolPref("mail.compose.big_attachments.notify", false); else this.sessionHidden = true; }, init: function() { let bucket = document.getElementById("attachmentBucket"); bucket.addEventListener("attachments-added", this, false); bucket.addEventListener("attachments-removed", this, false); bucket.addEventListener("attachments-uploading", this, false); bucket.addEventListener("attachment-uploaded", this, false); bucket.addEventListener("attachment-upload-failed", this, false); bucket.addEventListener("attachments-converted", this, false); this.sessionHidden = false; this.privacyWarned = false; this.bigFiles = []; }, handleEvent: function(event) { if (this.hidden) return; const bucketCallbacks = { "attachments-added": this.attachmentsAdded, "attachments-removed": this.attachmentsRemoved, "attachments-converted": this.attachmentsConverted, "attachments-uploading": this.attachmentsUploading, }; const itemCallbacks = { "attachment-uploaded": this.attachmentUploaded, "attachment-upload-failed": this.attachmentUploadFailed, } if (event.type in bucketCallbacks) bucketCallbacks[event.type].call(this, event.detail); if (event.type in itemCallbacks) itemCallbacks[event.type].call(this, event.target, ("detail" in event) ? event.detail : null); this.updateNotification(); }, formatString: function (key, replacements, plural) { let str = getComposeBundle().getString(key); if (plural !== undefined) str = PluralForm.get(plural, str); if (replacements !== undefined) { for (let i = 0; i < replacements.length; i++) str = str.replace("#" + (i + 1), replacements[i]); } return str; }, attachmentsAdded: function(aAttachments) { let threshold = Services.prefs.getIntPref( "mail.compose.big_attachments.threshold_kb") * 1024; for (let attachment in fixIterator( aAttachments, Components.interfaces.nsIMsgAttachment)) { if (attachment.size >= threshold && !attachment.sendViaCloud) this.bigFiles.push(attachment); } }, attachmentsRemoved: function(aAttachments) { for (let attachment in fixIterator( aAttachments, Components.interfaces.nsIMsgAttachment)) { let index = this.bigFiles.indexOf(attachment); if (index != -1) this.bigFiles.splice(index, 1); } }, attachmentsConverted: function(aAttachments) { let uploaded = []; for (let attachment in fixIterator( aAttachments, Components.interfaces.nsIMsgAttachment)) { if (attachment.sendViaCloud) { this.attachmentsRemoved([attachment]); uploaded.push(attachment); } } if (uploaded.length) this.showUploadingNotification(uploaded); }, attachmentsUploading: function(aAttachments) { this.showUploadingNotification(aAttachments); }, attachmentUploaded: function(aAttachment) { if (!this._anyUploadsInProgress()) { this.hideUploadingNotification(); if (!this.privacyWarned) { this.showPrivacyNotification(); this.privacyWarned = true; } } }, attachmentUploadFailed: function(aAttachment, aStatusCode) { if (!this._anyUploadsInProgress()) this.hideUploadingNotification(); }, updateNotification: function() { let nb = document.getElementById("attachmentNotificationBox"); let notification = nb.getNotificationWithValue("bigAttachment"); let numAccounts = cloudFileAccounts.accounts.length; if (this.bigFiles.length) { if (notification) { notification.label = this.formatString("bigFileDescription", [this.bigFiles.length], this.bigFiles.length); return; } let buttons = [ { label: getComposeBundle().getString("learnMore.label"), accessKey: getComposeBundle().getString("learnMore.accesskey"), callback: this.openLearnMore.bind(this), }, { label: this.formatString("bigFileShare.label", []), accessKey: this.formatString("bigFileShare.accesskey"), callback: this.convertAttachments.bind(this), }, { label: this.formatString("bigFileAttach.label", []), accessKey: this.formatString("bigFileAttach.accesskey"), callback: this.hideNotification.bind(this), }, ]; let msg = this.formatString("bigFileDescription", [this.bigFiles.length], this.bigFiles.length); notification = nb.appendNotification(msg, "bigAttachment", "null", nb.PRIORITY_WARNING_MEDIUM, buttons); } else { if (notification) nb.removeNotification(notification); } }, openLearnMore: function() { let url = Services.prefs.getCharPref("mail.cloud_files.learn_more_url"); openContentTab(url); return true; }, convertAttachments: function() { let cloudProvider; let accounts = cloudFileAccounts.accounts; if (accounts.length == 1) { cloudProvider = accounts[0]; } else if(accounts.length > 1) { let selection = {}; let names = accounts.map(i => cloudFileAccounts.getDisplayName(i)); if (Services.prompt.select(window, this.formatString("bigFileChooseAccount.title"), this.formatString("bigFileChooseAccount.text"), names.length, names, selection)) cloudProvider = accounts[selection.value]; } else { let accountKey = cloudFileAccounts.addAccountDialog(); if (accountKey) cloudProvider = cloudFileAccounts.getAccount(accountKey); else return true; } if (cloudProvider) convertToCloudAttachment(this.bigFiles, cloudProvider); }, hideNotification: function() { let never = {}; if (Services.prompt.confirmCheck(window, this.formatString("bigFileHideNotification.title"), this.formatString("bigFileHideNotification.text"), this.formatString("bigFileHideNotification.check"), never)) this.hide(never.value); else return true; }, showUploadingNotification: function(aAttachments) { // We will show the uploading notification for a minimum of 2.5 seconds // seconds. const kThreshold = 2500; // milliseconds if (!aAttachments.length || !Services.prefs .getBoolPref("mail.compose.big_attachments.insert_notification")) return; let nb = document.getElementById("attachmentNotificationBox"); let notification = nb.getNotificationWithValue(kUploadNotificationValue); if (notification) return; let message = this.formatString("cloudFileUploadingNotification"); message = PluralForm.get(aAttachments.length, message); let showUploadButton = { accessKey: this.formatString("stopShowingUploadingNotification.accesskey"), label: this.formatString("stopShowingUploadingNotification.label"), callback: function (aNotificationBar, aButton) { Services.prefs.setBoolPref("mail.compose.big_attachments.insert_notification", false); } }; notification = nb.appendNotification(message, kUploadNotificationValue, "null", nb.PRIORITY_WARNING_MEDIUM, [showUploadButton]); notification.timeout = Date.now() + kThreshold; }, hideUploadingNotification: function() { let nb = document.getElementById("attachmentNotificationBox"); let notification = nb.getNotificationWithValue(kUploadNotificationValue); if (notification) { // Check the timestamp that we stashed in the timeout field of the // notification... let now = Date.now(); if (now >= notification.timeout) { nb.removeNotification(notification); } else { setTimeout(function() { nb.removeNotification(notification); }, notification.timeout - now); } } }, showPrivacyNotification: function() { const kPrivacyNotificationValue = "bigAttachmentPrivacyWarning"; let nb = document.getElementById("attachmentNotificationBox"); let notification = nb.getNotificationWithValue(kPrivacyNotificationValue); if (notification) return; let message = this.formatString("cloudFilePrivacyNotification"); nb.appendNotification(message, kPrivacyNotificationValue, "null", nb.PRIORITY_WARNING_MEDIUM, null); }, _anyUploadsInProgress: function() { let bucket = document.getElementById("attachmentBucket"); let rowCount = bucket.getRowCount(); for (let i = 0; i < bucket.getRowCount(); ++i) { let item = bucket.getItemAtIndex(i); if (item && item.uploading) return true; } return false; }, }; window.addEventListener("compose-window-init", gBigFileObserver.init.bind(gBigFileObserver), true);