diff --git a/mailnews/compose/public/nsIMsgComposeProgress.idl b/mailnews/compose/public/nsIMsgComposeProgress.idl new file mode 100644 index 000000000000..58945d3f9079 --- /dev/null +++ b/mailnews/compose/public/nsIMsgComposeProgress.idl @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): +*/ +#include "nsISupports.idl" +#include "domstubs.idl" +#include "nsIPrompt.idl" +#include "nsIWebProgressListener.idl" + +interface nsIDOMWindowInternal; + +[scriptable, uuid(2080d500-149e-11d5-9daa-e276a42bc27c)] +interface nsIMsgComposeProgress: nsIWebProgressListener { + + /* Open the progress widget, usually it's a dialog + you can specify the subject of the message, + and specify if it a save or send operation + */ + void openProgress(in nsIDOMWindowInternal parent, in wstring subject, in boolean itsASaveOperation); + + /* Close the progress widget, usually it's a dialog */ + void closeProgress(in boolean forceClose); + + /* Register a Web Progress Listener */ + void registerListener(in nsIWebProgressListener listener); + + /* Unregister a Web Progress Listener */ + void unregisterListener(in nsIWebProgressListener listener); + + /* Retrive the prompter, needed to display modal dialog on top of progress dialog */ + nsIPrompt getPrompter(); + + /* Indicated if the user asked to cancel the current process */ + attribute boolean processCanceledByUser; +}; + + diff --git a/mailnews/compose/public/nsIURLFetcher.idl b/mailnews/compose/public/nsIURLFetcher.idl new file mode 100644 index 000000000000..350f29e05b14 --- /dev/null +++ b/mailnews/compose/public/nsIURLFetcher.idl @@ -0,0 +1,54 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * The contents of this file are subject to the Netscape Public + * License Version 1.1 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or + * implied. See the License for the specific language governing + * rights and limitations under the License. + * + * The Original Code is mozilla.org code. + * + * The Initial Developer of the Original Code is Netscape + * Communications Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All + * Rights Reserved. + * + * Contributor(s): + */ + +#include "nsISupports.idl" +#include "nsIURI.idl" + +%{ C++ + +#include "nsFileStream.h" + +// +// Callback declarations for URL completion +// +// For completion of send/message creation operations... +typedef nsresult (*nsAttachSaveCompletionCallback) (nsresult aStatus, + const char *aContentType, + const char *aCharset, + PRInt32 totalSize, const PRUnichar* aMsg, + void *tagData); + +%} + +[ptr] native nsOutputFileStream(nsOutputFileStream); +native nsAttachSaveCompletionCallback(nsAttachSaveCompletionCallback); + + +[noscript, uuid(01B8A700-2F52-11D5-9DAA-F78DA781A1FC)] +interface nsIURLFetcher : nsISupports +{ + boolean stillRunning(); + + void fireURLRequest(in nsIURI aURL, in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); + + void initialize(in nsOutputFileStream fOut, in nsAttachSaveCompletionCallback cb, in voidPtr tagData); +}; diff --git a/mailnews/compose/resources/content/sendProgress.js b/mailnews/compose/resources/content/sendProgress.js new file mode 100644 index 000000000000..0010041e1314 --- /dev/null +++ b/mailnews/compose/resources/content/sendProgress.js @@ -0,0 +1,292 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla Communicator client code, + * released March 31, 1998. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are + * Copyright (C) 1998 Netscape Communications Corporation. All Rights + * Reserved. + * + * Contributors: + * William A. ("PowerGUI") Law + * Scott MacGregor + * jean-Francois Ducarroz + */ + +var prefContractID = "@mozilla.org/preferences;1"; + +// dialog is just an array we'll use to store various properties from the dialog document... +var dialog; + +// the msgComposeProgress is a nsIMsgComposeProgress object +var msgComposeProgress = null; + +// random global variables... +var keepProgressWindowUpBox; +var targetFile; +var itsASaveOperation = false; + +// all progress notifications are done through the nsIWebProgressListener implementation... +var progressListener = { + onStateChange: function(aWebProgress, aRequest, aStateFlags, aStatus) + { + if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_START) + { + // Put progress meter in undetermined mode. + dialog.progress.setAttribute( "value", 0 ); + dialog.progress.setAttribute( "mode", "undetermined" ); + } + + if (aStateFlags & Components.interfaces.nsIWebProgressListener.STATE_STOP) + { + // we are done sending/saving the message... + // Indicate completion in status area. + var msg; + if (itsASaveOperation) + msg = getString( "messageSaved" ); + else + msg = getString( "messageSent" ); + dialog.status.setAttribute("value", msg); + + // Put progress meter at 100%. + dialog.progress.setAttribute( "value", 100 ); + dialog.progress.setAttribute( "mode", "normal" ); + var percentMsg = getString( "percentMsg" ); + percentMsg = replaceInsert( percentMsg, 1, 100 ); + dialog.progressText.setAttribute("value", percentMsg); + if (aStatus == 0) + processEndOfDownload(false); + else + processEndOfDownload(true); + } + }, + + onProgressChange: function(aWebProgress, aRequest, aCurSelfProgress, aMaxSelfProgress, aCurTotalProgress, aMaxTotalProgress) + { + + var overallProgress = aCurTotalProgress; + + // Calculate percentage. + var percent; + if ( aMaxTotalProgress != "-1" ) + { + percent = parseInt( (overallProgress*100)/aMaxTotalProgress + .5 ); + if ( percent > 100 ) + percent = 100; + + // Advance progress meter. + dialog.progress.setAttribute( "value", percent ); + } + else + { + percent = "??"; + + // Progress meter should be barber-pole in this case. + dialog.progress.setAttribute( "mode", "undetermined" ); + } + + // Update status msg. + dialog.status.setAttribute("value", status); + + // Update percentage label on progress meter. + var percentMsg = getString( "percentMsg" ); + percentMsg = replaceInsert( percentMsg, 1, percent ); + dialog.progressText.setAttribute("value", percentMsg); + }, + + onLocationChange: function(aWebProgress, aRequest, aLocation) + { + // we can ignore this notification + }, + + onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) + { + dialog.status.setAttribute("value", aMessage); + }, + + onSecurityChange: function(aWebProgress, aRequest, state) + { + // we can ignore this notification + }, + + QueryInterface : function(iid) + { + if (iid.equals(Components.interfaces.nsIWebProgressListener) || iid.equals(Components.interfaces.nsISupportsWeakReference)) + return this; + + throw Components.results.NS_NOINTERFACE; + } +}; + +function getString( stringId ) { + // Check if we've fetched this string already. + if ( !dialog.strings[ stringId ] ) { + // Try to get it. + var elem = document.getElementById( "dialog.strings."+stringId ); + try { + if ( elem + && + elem.childNodes + && + elem.childNodes[0] + && + elem.childNodes[0].nodeValue ) { + dialog.strings[ stringId ] = elem.childNodes[0].nodeValue; + } else { + // If unable to fetch string, use an empty string. + dialog.strings[ stringId ] = ""; + } + } catch (e) { dialog.strings[ stringId ] = ""; } + } + return dialog.strings[ stringId ]; +} + +function loadDialog() +{ + if (itsASaveOperation) + { + keepProgressWindowUpBox.checked = false; + keepProgressWindowUpBox.setAttribute("hidden", true); + } + else + { + var prefs = Components.classes[prefContractID].getService(Components.interfaces.nsIPref); + if (prefs) + keepProgressWindowUpBox.checked = prefs.GetBoolPref("mailnews.send.progressDnldDialog.keepAlive"); + } +} + +function replaceInsert( text, index, value ) { + var result = text; + var regExp = eval( "/#"+index+"/" ); + result = result.replace( regExp, value ); + return result; +} + +function onLoad() { + // Set global variables. + var subject = window.arguments[0]; + itsASaveOperation = window.arguments[1]; + msgComposeProgress = window.arguments[2]; + + if ( !msgComposeProgress ) { + dump( "Invalid argument to downloadProgress.xul\n" ); + window.close() + return; + } + + dialog = new Object; + dialog.strings = new Array; + dialog.status = document.getElementById("dialog.status"); + dialog.progress = document.getElementById("dialog.progress"); + dialog.progressText = document.getElementById("dialog.progressText"); + dialog.cancel = document.getElementById("cancel"); + keepProgressWindowUpBox = document.getElementById('keepProgressDialogUp'); + + // Set up dialog button callbacks. + var object = this; + doSetOKCancel("", function () { return object.onCancel();}); + + // Fill dialog. + loadDialog(); + + // set our web progress listener on the helper app launcher + msgComposeProgress.registerListener(progressListener); + window.moveTo(opener.screenX + 16, opener.screenY + 32); + + //We need to delay the set title else dom will overwrite it + return window.setTimeout( "SetTitle('" + subject + "');", 0 ); +} + +function onUnload() +{ + if (!itsASaveOperation) + { + // remember the user's decision for the checkbox. + var prefs = Components.classes[prefContractID].getService(Components.interfaces.nsIPref); + if (prefs) + prefs.SetBoolPref("mailnews.send.progressDnldDialog.keepAlive", keepProgressWindowUpBox.checked); + } + + if (msgComposeProgress) + { + try + { + msgComposeProgress.unregisterListener(progressListener); + msgComposeProgress = null; + } + + catch( exception ) {} + } +} + +function SetTitle(subject) +{ + var prefix; + if (itsASaveOperation) + prefix = getString("titlePrefixSave"); + else + prefix = getString("titlePrefixSend"); + window.title = prefix + " " + subject; +} + +// If the user presses cancel, tell the app launcher and close the dialog... +function onCancel () +{ + // Cancel app launcher. + try + { + msgComposeProgress.processCanceledByUser = true; + } + catch( exception ) {return true;} + + // don't Close up dialog by returning false, the backend will close the dialog when everything will be aborted. + return false; +} + +// closeWindow should only be called from processEndOfDownload +function closeWindow(forceClose) +{ + // while the time out was fired the user may have checked the + // keep this dialog open box...so we should abort and not actually + // close the window. + if (forceClose || itsASaveOperation || !keepProgressWindowUpBox.checked) + window.close(); + else + setupPostProgressUI(); +} + +function setupPostProgressUI() +{ + //dialog.cancel.childNodes[0].nodeValue = "Close"; + // turn the cancel button into a close button + var cancelButton = document.getElementById('cancel'); + if (cancelButton) + { + cancelButton.setAttribute("label", getString("dialogCloseLabel")); + cancelButton.setAttribute("onclick", "window.close()"); + } +} + +// when we receive a stop notification we are done reporting progress on the send/save +// now we have to decide if the window is supposed to go away or if we are supposed to remain open +function processEndOfDownload(forceClose) +{ + if (forceClose || itsASaveOperation || !keepProgressWindowUpBox.checked) +// return window.setTimeout( "closeWindow();", 2000 ); // shut down, we are all done. + return closeWindow(forceClose); // shut down, we are all done. + + // o.t the user has asked the window to stay open so leave it open and enable the open and open new folder buttons + setupPostProgressUI(); +} diff --git a/mailnews/compose/resources/content/sendProgress.xul b/mailnews/compose/resources/content/sendProgress.xul new file mode 100644 index 000000000000..37e8b6b23066 --- /dev/null +++ b/mailnews/compose/resources/content/sendProgress.xul @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + +