make status notification prettier, part 1 of n
This commit is contained in:
Родитель
80de303a96
Коммит
dab16d5889
|
@ -20,3 +20,17 @@ app.update.url=https://aus.mozilla.org/update2/0/%PRODUCT%/%VERSION%/%BUILD_ID%/
|
|||
app.update.url.manual=http://www.mozilla.org/update
|
||||
# This value should be empty unless you wish to override app.update.url
|
||||
app.update.url.override=
|
||||
|
||||
statusFormatKBKB=#1 of #2 KB
|
||||
statusFormatKBMB=#1 KB of #2 MB
|
||||
statusFormatMBMB=#1 of #2 MB
|
||||
statusFormatUnknownKB=#1 KB
|
||||
statusFormatUnknownMB=#1 MB
|
||||
remain=remain
|
||||
unknownFilesize=unknown file size
|
||||
statusFormat=#1 at #2 KB/sec; #3
|
||||
longTimeFormat=#1:#2:#3
|
||||
shortTimeFormat=#2:#3
|
||||
downloadingPrefix=Downloading %S...
|
||||
pausedStatus=Download Paused
|
||||
pausedName=Paused %S
|
||||
|
|
|
@ -366,6 +366,7 @@ var gDownloadingPage = {
|
|||
active.startDownload();
|
||||
active.state = STATE_DOWNLOADING;
|
||||
active.progress = gUpdates.update.selectedPatch.progress;
|
||||
active.status = gUpdates.update.selectedPatch.status;
|
||||
},
|
||||
|
||||
onStatus: function(request, context, status, statusText) {
|
||||
|
|
|
@ -56,7 +56,7 @@
|
|||
</resources>
|
||||
<content>
|
||||
<xul:hbox pack="start">
|
||||
<xul:label class="update-item-name" xbl:inherits="value=name" crop="right" flex="1"/>
|
||||
<xul:label anonid="name" class="update-item-name" xbl:inherits="value=name" crop="right" flex="1"/>
|
||||
<xul:link class="update-item-details" xbl:inherits="href=detailsURL">&details.link;</xul:link>
|
||||
</xul:hbox>
|
||||
<xul:deck anonid="modeDeck">
|
||||
|
@ -79,6 +79,9 @@
|
|||
<field name="_strings">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "strings");
|
||||
</field>
|
||||
<field name="_name">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "name");
|
||||
</field>
|
||||
<field name="_progressBar">
|
||||
document.getAnonymousElementByAttribute(this, "anonid", "progress");
|
||||
</field>
|
||||
|
@ -93,21 +96,24 @@
|
|||
<body><![CDATA[
|
||||
this._update = update;
|
||||
|
||||
this.setAttribute("name", update.name);
|
||||
this.name = update.name;
|
||||
this.setAttribute("detailsURL", update.detailsURL);
|
||||
this.state = update.selectedPatch.state;
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
<property name="progress">
|
||||
<getter><![CDATA[
|
||||
return parseInt(this._progressBar.getAttribute("value"));
|
||||
]]></getter>
|
||||
<setter><![CDATA[
|
||||
this._progressBar.setAttribute("value", val);
|
||||
]]></setter>
|
||||
</property>
|
||||
<property name="name"
|
||||
onget="return this._name.getAttribute('value');"
|
||||
onset="this._name.setAttribute('value', val); return val;"/>
|
||||
|
||||
<property name="progress"
|
||||
onget="return parseInt(this._progressBar.getAttribute('value'));"
|
||||
onset="this._progressBar.setAttribute('value', val); return val;"/>
|
||||
|
||||
<property name="status"
|
||||
onget="return this.getAttribute('status');"
|
||||
onset="this.setAttribute('status', val); return val;"/>
|
||||
|
||||
<field name="_started">false</field>
|
||||
<method name="startDownload">
|
||||
<body><![CDATA[
|
||||
|
@ -137,6 +143,19 @@
|
|||
<setter><![CDATA[
|
||||
this._paused = val;
|
||||
var key = val ? "pauseButtonResume" : "pauseButtonPause";
|
||||
if (val) {
|
||||
this.setAttribute("old-status", this.status);
|
||||
this.status = this._strings.getString("pausedStatus");
|
||||
this.setAttribute("old-name", this.name);
|
||||
this.name = this._strings.getFormattedString("pausedName", [this.name]);
|
||||
LOG("GOAT = " + this._strings.getFormattedString("pausedName", [this.name]));
|
||||
}
|
||||
else {
|
||||
this.status = this.getAttribute("old-status");
|
||||
this.removeAttribute("old-status");
|
||||
this.setAttribute("name", this.getAttribute("old-name"));
|
||||
this.removeAttribute("old-name");
|
||||
}
|
||||
this._pauseButton.label = this._strings.getString(key);
|
||||
return val;
|
||||
]]></setter>
|
||||
|
@ -149,6 +168,13 @@
|
|||
<setter><![CDATA[
|
||||
this.setAttribute("state", val);
|
||||
this._modeDeck.setAttribute("selectedIndex", val == "downloading" ? 1 : 0);
|
||||
var name = this._update.name;
|
||||
if (val == "downloading") {
|
||||
var name = this._strings.getFormattedString("downloadingPrefix",
|
||||
[this._update.name]);
|
||||
}
|
||||
this.setAttribute("name", name);
|
||||
|
||||
if (val == "failed") {
|
||||
var failed = this._strings.getString("statusFailed");
|
||||
this.setAttribute("status", failed);
|
||||
|
|
|
@ -74,6 +74,11 @@ interface nsIUpdatePatch : nsISupports
|
|||
*/
|
||||
attribute double progress;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
attribute AString status;
|
||||
|
||||
/**
|
||||
* The state of this update
|
||||
*/
|
||||
|
|
|
@ -862,6 +862,7 @@ function UpdatePatch(patch) {
|
|||
this.size = parseInt(patch.getAttribute("size"));
|
||||
this.percentage = parseFloat(patch.getAttribute("percentage"));
|
||||
this.state = patch.getAttribute("state");
|
||||
this.status = patch.getAttribute("status");
|
||||
this.selected = patch.getAttribute("selected") == "true";
|
||||
}
|
||||
UpdatePatch.prototype = {
|
||||
|
@ -877,6 +878,7 @@ UpdatePatch.prototype = {
|
|||
patch.setAttribute("size", this.size);
|
||||
patch.setAttribute("percentage", this.percentage);
|
||||
patch.setAttribute("state", this.state);
|
||||
patch.setAttribute("status", this.status);
|
||||
patch.setAttribute("selected", this.selected);
|
||||
return patch;
|
||||
},
|
||||
|
@ -1155,6 +1157,181 @@ Checker.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Formats status messages for a download operation based on the progress
|
||||
* of the download.
|
||||
* @constructor
|
||||
*/
|
||||
function DownloadStatusFormatter() {
|
||||
this._downloadStartTime = (new Date()).getTime();
|
||||
this._elapsed = 0;
|
||||
|
||||
var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"]
|
||||
.getService(Components.interfaces.nsIStringBundleService);
|
||||
var bundle = sbs.createBundle(URI_UPDATES_PROPERTIES);
|
||||
|
||||
this._statusFormat = bundle.GetStringFromName("statusFormat");
|
||||
this._statusFormatKBMB = bundle.GetStringFromName("statusFormatKBMB");
|
||||
this._statusFormatKBKB = bundle.GetStringFromName("statusFormatKBKB");
|
||||
this._statusFormatMBMB = bundle.GetStringFromName("statusFormatMBMB");
|
||||
this._statusFormatUnknownMB = bundle.GetStringFromName("statusFormatUnknownMB");
|
||||
this._statusFormatUnknownKB = bundle.GetStringFromName("statusFormatUnknownKB");
|
||||
this._remain = bundle.GetStringFromName("remain");
|
||||
this._unknownFilesize = bundle.GetStringFromName("unknownFilesize");
|
||||
this._longTimeFormat = bundle.GetStringFromName("longTimeFormat");
|
||||
this._shortTimeFormat = bundle.GetStringFromName("shortTimeFormat");
|
||||
}
|
||||
DownloadStatusFormatter.prototype = {
|
||||
/**
|
||||
* Time when the download started (in seconds since epoch)
|
||||
*/
|
||||
_downloadStartTime: 0,
|
||||
|
||||
/**
|
||||
* Time elapsed since the start of the download operation (in seconds)
|
||||
*/
|
||||
_elapsed: 0,
|
||||
|
||||
/**
|
||||
* Format a human-readable status message based on the current download
|
||||
* progress.
|
||||
* @param currSize
|
||||
* The current number of bytes transferred
|
||||
* @param finalSize
|
||||
* The total number of bytes to be transferred
|
||||
* @returns A human readable status message, e.g.
|
||||
* "3.4 of 4.7MB; 1.15 remain"
|
||||
*/
|
||||
formatStatus: function(currSize, finalSize) {
|
||||
var now = (new Date()).getTime();
|
||||
|
||||
// 1) Determine the Download Progress in Kilobytes
|
||||
var KBTotal = parseInt(finalSize/1024 + 0.5);
|
||||
var KBProgress = this._formatKBytes(parseInt(currSize/1024 + 0.5), KBTotal);
|
||||
LOG("KBP = " + KBProgress);
|
||||
|
||||
// 2) Determine the Transfer Rate
|
||||
this._elapsed = now - (this._startTime / 1000);
|
||||
var rate = this._elapsed ? (currSize * 1024) / this.elapsed : 0
|
||||
var KBRate = "??.?";
|
||||
if (rate) {
|
||||
var KBRate = parseInt((rate / 1024) * 10 + 0.5);
|
||||
var fraction = KBRate % 10;
|
||||
KBRate = parseInt((KBRate - remainder) / 10);
|
||||
if (KBRate < 100)
|
||||
KBRate += "." + fraction;
|
||||
}
|
||||
|
||||
// 3) Determine the Time Remaining
|
||||
var remainingTime = this._unknownFileSize;
|
||||
if (rate && (finalSize > 0)) {
|
||||
remainingTime = (finalSize - currSize) / rate;
|
||||
remainingTime = parseInt(remainingTime + 0.5);
|
||||
remainingTime = this._formatSeconds(remainingTime);
|
||||
}
|
||||
|
||||
var status = this._statusFormat;
|
||||
status = this._replaceInsert(status, 1, KBProgress);
|
||||
status = this._replaceInsert(status, 2, KBRate);
|
||||
status = this._replaceInsert(status, 3, remainingTime);
|
||||
return status;
|
||||
},
|
||||
|
||||
/**
|
||||
* Inserts a string into another string at the specified index, e.g. for
|
||||
* the format string var foo ="#1 #2 #3", |_replaceInsert(foo, 2, "test")|
|
||||
* returns "#1 test #3";
|
||||
* @param format
|
||||
* The format string
|
||||
* @param index
|
||||
* The Index to insert into
|
||||
* @param value
|
||||
* The value to insert
|
||||
* @returns The string with the value inserted.
|
||||
*/
|
||||
_replaceInsert: function(format, index, value) {
|
||||
return format.replace(new RegExp("#" + index), value);
|
||||
},
|
||||
|
||||
/**
|
||||
* Formats progress in the form of kilobytes transfered vs. total to
|
||||
* transfer.
|
||||
* @param currentKB
|
||||
* The current amount of data transfered, in kilobytes.
|
||||
* @param totalKB
|
||||
* The total amount of data that must be transfered, in kilobytes.
|
||||
* @returns A string representation of the progress, formatted according to:
|
||||
*
|
||||
* KB totalKB returns
|
||||
* x, < 1MB y < 1MB x of y KB
|
||||
* x, < 1MB y >= 1MB x KB of y MB
|
||||
* x, >= 1MB y >= 1MB x of y MB
|
||||
*/
|
||||
_formatKBytes: function(currentKB, totalKB) {
|
||||
var progressHasMB = parseInt(currentKB / 1024) > 0;
|
||||
var totalHasMB = parseInt(totalKB / 1024) > 0;
|
||||
|
||||
var format = "";
|
||||
if (!progressHasMB && !totalHasMB) {
|
||||
if (!totalKB) {
|
||||
format = this._statusFormatUnknownKB;
|
||||
format = this._replaceInsert(format, 1, currentKB);
|
||||
} else {
|
||||
format = this._statusFormatKBKB;
|
||||
format = this._replaceInsert(format, 1, currentKB);
|
||||
format = this._replaceInsert(format, 2, totalKB);
|
||||
}
|
||||
}
|
||||
else if (progressHasMB && totalHasMB) {
|
||||
format = this._statusFormatMBMB;
|
||||
format = this._replaceInsert(format, 1, (currentKB / 1024).toFixed(1));
|
||||
format = this._replaceInsert(format, 2, (totalKB / 1024).toFixed(1));
|
||||
}
|
||||
else if (totalHasMB && !progressHasMB) {
|
||||
format = this._statusFormatKBMB;
|
||||
format = this._replaceInsert(format, 1, currentKB);
|
||||
format = this._replaceInsert(format, 2, (totalKB / 1024).toFixed(1));
|
||||
}
|
||||
else if (progressHasMB && !totalHasMB) {
|
||||
format = this._statusFormatUnknownMB;
|
||||
format = this._replaceInsert(format, 1, (currentKB / 1024).toFixed(1));
|
||||
}
|
||||
return format;
|
||||
},
|
||||
|
||||
/**
|
||||
* Formats a time in seconds into something human readable.
|
||||
* @param seconds
|
||||
* The time to format
|
||||
* @returns A human readable string representing the date.
|
||||
*/
|
||||
_formatSeconds: function(seconds) {
|
||||
// Round the number of seconds to remove fractions.
|
||||
seconds = parseInt(seconds + .5);
|
||||
var hours = parseInt(seconds/3600);
|
||||
seconds -= hours * 3600;
|
||||
|
||||
var minutes = parseInt(seconds/60);
|
||||
seconds -= minutes * 60;
|
||||
var result = hours ? this._longTimeFormat : this._shortTimeFormat;
|
||||
|
||||
if (hours < 10)
|
||||
hours = "0" + hours;
|
||||
if (minutes < 10)
|
||||
minutes = "0" + minutes;
|
||||
if (seconds < 10)
|
||||
seconds = "0" + seconds;
|
||||
|
||||
// Insert hours, minutes, and seconds into result string.
|
||||
result = this._replaceInsert(result, 1, hours);
|
||||
result = this._replaceInsert(result, 2, minutes);
|
||||
result = this._replaceInsert(result, 3, seconds);
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Manages the download of updates
|
||||
* @param background
|
||||
|
@ -1454,19 +1631,31 @@ Downloader.prototype = {
|
|||
LOG("LISTENERS1 = " + this._listeners.length);
|
||||
},
|
||||
|
||||
_statusFormatter: null,
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
onStartRequest: function(request, context) {
|
||||
request.QueryInterface(nsIIncrementalDownload);
|
||||
LOG("Downloader.onStartRequest: " + request.URI.spec);
|
||||
|
||||
this._statusFormatter = new DownloadStatusFormatter();
|
||||
|
||||
var listenerCount = this._listeners.length;
|
||||
for (var i = 0; i < listenerCount; ++i)
|
||||
this._listeners[i].onStartRequest(request, context);
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
onProgress: function(request, context, progress, maxProgress) {
|
||||
request.QueryInterface(nsIIncrementalDownload);
|
||||
// LOG("Downloader.onProgress: " + request.URI.spec + ", " + progress + "/" + maxProgress);
|
||||
|
||||
this._patch.progress = Math.round(100 * (progress/maxProgress));
|
||||
this._patch.status = this._statusFormatter.formatStatus(progress, maxProgress);
|
||||
|
||||
var listenerCount = this._listeners.length;
|
||||
for (var i = 0; i < listenerCount; ++i) {
|
||||
|
@ -1476,6 +1665,9 @@ Downloader.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
onStatus: function(request, context, status, statusText) {
|
||||
request.QueryInterface(nsIIncrementalDownload);
|
||||
LOG("Downloader.onStatus: " + request.URI.spec + " status = " + status + ", text = " + statusText);
|
||||
|
@ -1487,6 +1679,9 @@ Downloader.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
onStopRequest: function(request, context, status) {
|
||||
request.QueryInterface(nsIIncrementalDownload);
|
||||
LOG("Downloader.onStopRequest: " + request.URI.spec + ", status = " + status);
|
||||
|
|
Загрузка…
Ссылка в новой задаче