clipboard: use snackbar for interaction with user
Instead of leaflet popup we use now snackbar. - control is not removed and added again for next copy-paste but we keep single instance for all the time - added download error message - simplified close snackbar code Signed-off-by: Szymon Kłos <szymon.klos@collabora.com> Change-Id: I804a82c4f589b029a42fc2800958ff2b46b7df50
This commit is contained in:
parent
585e00a1ee
commit
689c6fa063
3 changed files with 54 additions and 97 deletions
|
@ -5,65 +5,18 @@
|
||||||
/* global _ $ */
|
/* global _ $ */
|
||||||
L.Control.DownloadProgress = L.Control.extend({
|
L.Control.DownloadProgress = L.Control.extend({
|
||||||
options: {
|
options: {
|
||||||
position: 'bottomright'
|
snackbarTimeout: 20000
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
L.setOptions(this, options);
|
L.setOptions(this, options);
|
||||||
},
|
},
|
||||||
|
|
||||||
onAdd: function () {
|
onAdd: function (map) {
|
||||||
this._initLayout();
|
this._map = map;
|
||||||
return this._container;
|
this._started = false;
|
||||||
},
|
this._complete = false;
|
||||||
|
this._closed = false;
|
||||||
// we really don't want mouse and other events propagating
|
|
||||||
// to the parent map - since they affect the context.
|
|
||||||
_ignoreEvents: function(elem) {
|
|
||||||
L.DomEvent.on(elem, 'mousedown mouseup mouseover mouseout mousemove',
|
|
||||||
function(e) {
|
|
||||||
L.DomEvent.stopPropagation(e);
|
|
||||||
return false;
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
|
|
||||||
_initLayout: function () {
|
|
||||||
this._container = L.DomUtil.create('div', 'leaflet-control-layers');
|
|
||||||
this._container.style.visibility = 'hidden';
|
|
||||||
this._ignoreEvents(this._container);
|
|
||||||
|
|
||||||
var closeButton = L.DomUtil.create('a', 'leaflet-popup-close-button download-popup', this._container);
|
|
||||||
closeButton.href = '#close';
|
|
||||||
closeButton.innerHTML = '×';
|
|
||||||
L.DomEvent.on(closeButton, 'click', this._onClose, this);
|
|
||||||
|
|
||||||
var wrapper = L.DomUtil.create('div', 'leaflet-popup-content-wrapper', this._container);
|
|
||||||
var content = this._content = L.DomUtil.create('div', 'leaflet-popup-content', wrapper);
|
|
||||||
content.style.width = '100px';
|
|
||||||
|
|
||||||
// start download button
|
|
||||||
var startDownload = this._downloadButton = document.createElement('a');
|
|
||||||
startDownload.href = '#start';
|
|
||||||
startDownload.innerHTML = _('Start download');
|
|
||||||
startDownload.style.font = '13px/11px Tahoma, Verdana, sans-serif';
|
|
||||||
startDownload.style.alignment = 'center';
|
|
||||||
startDownload.style.height = 20 + 'px';
|
|
||||||
L.DomEvent.on(startDownload, 'click', this._onStartDownload, this);
|
|
||||||
|
|
||||||
// download progress bar
|
|
||||||
this._progress = L.DomUtil.create('div', 'leaflet-paste-progress', null);
|
|
||||||
this._bar = L.DomUtil.create('span', '', this._progress);
|
|
||||||
this._value = L.DomUtil.create('span', '', this._bar);
|
|
||||||
L.DomUtil.setStyle(this._value, 'line-height', '14px');
|
|
||||||
|
|
||||||
// confirm button
|
|
||||||
var confirmCopy = this._confirmPasteButton = document.createElement('a');
|
|
||||||
confirmCopy.href = '#complete';
|
|
||||||
confirmCopy.innerHTML = _('Confirm copy to clipboard');
|
|
||||||
confirmCopy.style.font = '13px/11px Tahoma, Verdana, sans-serif';
|
|
||||||
confirmCopy.style.alignment = 'center';
|
|
||||||
confirmCopy.style.height = 20 + 'px';
|
|
||||||
L.DomEvent.on(confirmCopy, 'click', this._onConfirmCopyAction, this);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
show: function () {
|
show: function () {
|
||||||
|
@ -73,8 +26,11 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
this._started = false;
|
this._started = false;
|
||||||
this._complete = false;
|
this._complete = false;
|
||||||
this._closed = false;
|
this._closed = false;
|
||||||
this._content.appendChild(this._downloadButton);
|
|
||||||
this._container.style.visibility = '';
|
var msg = _('Start download') + ' (Alt + C)'; // TODO: on Mac Alt == Option
|
||||||
|
this._map.uiManager.showSnackbar(
|
||||||
|
_('To copy outside, you have to download the content'),
|
||||||
|
msg, this._onStartDownload.bind(this), this.options.snackbarTimeout);
|
||||||
},
|
},
|
||||||
|
|
||||||
isClosed: function () {
|
isClosed: function () {
|
||||||
|
@ -88,11 +44,11 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
currentStatus: function () {
|
currentStatus: function () {
|
||||||
if (this._closed)
|
if (this._closed)
|
||||||
return 'closed';
|
return 'closed';
|
||||||
if (this._content.contains(this._downloadButton))
|
if (!this._started && !this._complete)
|
||||||
return 'downloadButton';
|
return 'downloadButton';
|
||||||
if (this._content.contains(this._progress))
|
if (this._started)
|
||||||
return 'progress';
|
return 'progress';
|
||||||
if (this._content.contains(this._confirmPasteButton))
|
if (this._complete)
|
||||||
return 'confirmPasteButton';
|
return 'confirmPasteButton';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -102,8 +58,7 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue: function (value) {
|
setValue: function (value) {
|
||||||
this._bar.style.width = Math.round(value) + '%';
|
this._map.uiManager.setSnackbarProgress(Math.round(value));
|
||||||
this._value.innerHTML = Math.round(value) + '%';
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_setProgressCursor: function() {
|
_setProgressCursor: function() {
|
||||||
|
@ -117,9 +72,9 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
startProgressMode: function() {
|
startProgressMode: function() {
|
||||||
this._setProgressCursor();
|
this._setProgressCursor();
|
||||||
this._started = true;
|
this._started = true;
|
||||||
|
this._map.uiManager.showProgressBar(
|
||||||
|
'Downloading clipboard content', 'Cancel', this._onClose.bind(this));
|
||||||
this.setValue(0);
|
this.setValue(0);
|
||||||
this._content.removeChild(this._downloadButton);
|
|
||||||
this._content.appendChild(this._progress);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_onStartDownload: function () {
|
_onStartDownload: function () {
|
||||||
|
@ -143,10 +98,12 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
return;
|
return;
|
||||||
this._setNormalCursor();
|
this._setNormalCursor();
|
||||||
this._complete = true;
|
this._complete = true;
|
||||||
if (this._content.contains(this._progress))
|
this._started = false;
|
||||||
this._content.removeChild(this._progress);
|
|
||||||
this._content.style.width = '150px';
|
var msg = _('Confirm copy to clipboard');
|
||||||
this._content.appendChild(this._confirmPasteButton);
|
// TODO: on Mac Alt == Option
|
||||||
|
this._map.uiManager.showSnackbar(msg, _('Confirm') + ' (Alt + C)',
|
||||||
|
this._onConfirmCopyAction.bind(this), this.options.snackbarTimeout);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onConfirmCopyAction: function () {
|
_onConfirmCopyAction: function () {
|
||||||
|
@ -155,16 +112,17 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
_onClose: function () {
|
_onClose: function () {
|
||||||
|
if (this._userAlreadyWarned())
|
||||||
|
this._map.uiManager.closeSnackbar();
|
||||||
|
|
||||||
|
this._started = false;
|
||||||
|
this._complete = false;
|
||||||
|
this._closed = true;
|
||||||
|
|
||||||
this._setNormalCursor();
|
this._setNormalCursor();
|
||||||
this._cancelDownload();
|
this._cancelDownload();
|
||||||
if (this._content.contains(this._confirmPasteButton))
|
|
||||||
this._content.removeChild(this._confirmPasteButton);
|
|
||||||
if (this._content.contains(this._progress))
|
|
||||||
this._content.removeChild(this._progress);
|
|
||||||
if (this._map)
|
if (this._map)
|
||||||
this._map.focus();
|
this._map.focus();
|
||||||
this.remove();
|
|
||||||
this._closed = true;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_download: function () {
|
_download: function () {
|
||||||
|
@ -186,7 +144,12 @@ L.Control.DownloadProgress = L.Control.extend({
|
||||||
// TODO: failure to parse ? ...
|
// TODO: failure to parse ? ...
|
||||||
reader.readAsText(response);
|
reader.readAsText(response);
|
||||||
},
|
},
|
||||||
function(progress) { return progress/2; }
|
function(progress) { return progress/2; },
|
||||||
|
function () {
|
||||||
|
that._onClose();
|
||||||
|
that._map.uiManager.showSnackbar(
|
||||||
|
_('Download failed'), '', null,this.options.snackbarTimeout);
|
||||||
|
}
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -917,18 +917,16 @@ L.Control.UIManager = L.Control.extend({
|
||||||
|
|
||||||
// Snack bar
|
// Snack bar
|
||||||
|
|
||||||
|
closeSnackbar: function() {
|
||||||
|
var closeMessage = { id: 'snackbar', jsontype: 'dialog', type: 'snackbar', action: 'close' };
|
||||||
|
app.socket._onMessage({ textMsg: 'jsdialog: ' + JSON.stringify(closeMessage) });
|
||||||
|
},
|
||||||
|
|
||||||
showSnackbar: function(label, action, callback, timeout, hasProgress) {
|
showSnackbar: function(label, action, callback, timeout, hasProgress) {
|
||||||
if (!app.socket)
|
if (!app.socket)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var closeJson = {
|
this.closeSnackbar();
|
||||||
id: 'snackbar',
|
|
||||||
jsontype: 'dialog',
|
|
||||||
type: 'snackbar',
|
|
||||||
action: 'fadeout'
|
|
||||||
};
|
|
||||||
|
|
||||||
app.socket._onMessage({textMsg: 'jsdialog: ' + JSON.stringify(closeJson)});
|
|
||||||
|
|
||||||
var json = {
|
var json = {
|
||||||
id: 'snackbar',
|
id: 'snackbar',
|
||||||
|
@ -948,6 +946,7 @@ L.Control.UIManager = L.Control.extend({
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var that = this;
|
||||||
var builderCallback = function(objectType, eventType, object, data) {
|
var builderCallback = function(objectType, eventType, object, data) {
|
||||||
window.app.console.debug('control: \'' + objectType + '\' id:\'' + object.id + '\' event: \'' + eventType + '\' state: \'' + data + '\'');
|
window.app.console.debug('control: \'' + objectType + '\' id:\'' + object.id + '\' event: \'' + eventType + '\' state: \'' + data + '\'');
|
||||||
|
|
||||||
|
@ -955,8 +954,7 @@ L.Control.UIManager = L.Control.extend({
|
||||||
if (callback)
|
if (callback)
|
||||||
callback();
|
callback();
|
||||||
|
|
||||||
var closeMessage = { id: 'snackbar', jsontype: 'dialog', type: 'snackbar', action: 'close' };
|
that.closeSnackbar();
|
||||||
app.socket._onMessage({ textMsg: 'jsdialog: ' + JSON.stringify(closeMessage) });
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ L.Clipboard = L.Class.extend({
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
|
|
||||||
// avoid to invoke the following code if the download widget depends on user interaction
|
// avoid to invoke the following code if the download widget depends on user interaction
|
||||||
if (!that._downloadProgress || !that._downloadProgress.isVisible()) {
|
if (!that._downloadProgress || that._downloadProgress.isClosed()) {
|
||||||
that._startProgress();
|
that._startProgress();
|
||||||
that._downloadProgress.startProgressMode();
|
that._downloadProgress.startProgressMode();
|
||||||
}
|
}
|
||||||
|
@ -802,33 +802,31 @@ L.Clipboard = L.Class.extend({
|
||||||
_startProgress: function() {
|
_startProgress: function() {
|
||||||
if (!this._downloadProgress) {
|
if (!this._downloadProgress) {
|
||||||
this._downloadProgress = L.control.downloadProgress();
|
this._downloadProgress = L.control.downloadProgress();
|
||||||
}
|
this._map.addControl(this._downloadProgress);
|
||||||
if (!this._downloadProgress.isVisible()) {
|
|
||||||
this._downloadProgress.addTo(this._map);
|
|
||||||
}
|
}
|
||||||
this._downloadProgress.show();
|
this._downloadProgress.show();
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDownloadOnLargeCopyPaste: function () {
|
_onDownloadOnLargeCopyPaste: function () {
|
||||||
if (!this._downloadProgress || this._downloadProgress.isClosed()) {
|
if (this._downloadProgress && this._downloadProgress.isStarted()) {
|
||||||
this._warnFirstLargeCopyPaste();
|
|
||||||
this._startProgress();
|
|
||||||
}
|
|
||||||
else if (this._downloadProgress.isStarted()) {
|
|
||||||
// Need to show this only when a download is really in progress and we block it.
|
// Need to show this only when a download is really in progress and we block it.
|
||||||
// Otherwise, it's easier to flash the widget or something.
|
// Otherwise, it's easier to flash the widget or something.
|
||||||
this._warnLargeCopyPasteAlreadyStarted();
|
this._warnLargeCopyPasteAlreadyStarted();
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this._warnFirstLargeCopyPaste();
|
||||||
|
this._startProgress();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_downloadProgressStatus: function() {
|
_downloadProgressStatus: function() {
|
||||||
if (this._downloadProgress && this._downloadProgress.isVisible())
|
if (this._downloadProgress)
|
||||||
return this._downloadProgress.currentStatus();
|
return this._downloadProgress.currentStatus();
|
||||||
},
|
},
|
||||||
|
|
||||||
// Download button is still shown after selection changed -> user has changed their mind...
|
// Download button is still shown after selection changed -> user has changed their mind...
|
||||||
_scheduleHideDownload: function(s) {
|
_scheduleHideDownload: function(s) {
|
||||||
if (!this._downloadProgress || !this._downloadProgress.isVisible())
|
if (!this._downloadProgress || this._downloadProgress.isClosed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If no other copy/paste things occurred then ...
|
// If no other copy/paste things occurred then ...
|
||||||
|
@ -847,9 +845,7 @@ L.Clipboard = L.Class.extend({
|
||||||
clearTimeout(this._hideDownloadTimer);
|
clearTimeout(this._hideDownloadTimer);
|
||||||
this._hideDownloadTimer = null;
|
this._hideDownloadTimer = null;
|
||||||
|
|
||||||
if (!this._downloadProgress ||
|
if (!this._downloadProgress || this._downloadProgress.isClosed())
|
||||||
!this._downloadProgress.isVisible() ||
|
|
||||||
this._downloadProgress.isClosed())
|
|
||||||
return;
|
return;
|
||||||
this._downloadProgress._onClose();
|
this._downloadProgress._onClose();
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue