Move clipboard from localStorage to sessionStorage

This change eliminates the permanent clipboard that unexpectedly survives beyond the current session.  Uses localStorage to momentarily flash the clipboard to other tabs.  Resolves #379
Also fixes traceback if paste is called with nothing on clipboard.
Also fixes traceback if copy is called and no context menu exists.
master
Neil Fraser 2020-02-20 13:43:12 -08:00 committed by Brett Zamir
parent 334dc09c63
commit 3766d748d5
1 changed files with 47 additions and 6 deletions

View File

@ -6349,17 +6349,57 @@ this.cutSelectedElements = function () {
canvas.deleteSelectedElements(); canvas.deleteSelectedElements();
}; };
const CLIPBOARD_ID = 'svgedit_clipboard';
/**
* Flash the clipboard data momentarily on localStorage so all tabs can see.
*/
function flashStorage() {
const data = sessionStorage.getItem(CLIPBOARD_ID);
localStorage.setItem(CLIPBOARD_ID, data);
setTimeout(function() {
localStorage.removeItem(CLIPBOARD_ID);
}, 1);
}
/**
* Transfers sessionStorage from one tab to another.
* @param {Event} event Storage event.
*/
function storageChange(event) {
if (!event.newValue) return; // This is a call from removeItem.
if (event.key === CLIPBOARD_ID + '_startup') {
// Another tab asked for our sessionStorage.
localStorage.removeItem(CLIPBOARD_ID + '_startup');
flashStorage();
} else if (event.key === CLIPBOARD_ID) {
// Another tab sent data.
sessionStorage.setItem(CLIPBOARD_ID, event.newValue);
}
}
// Listen for changes to localStorage.
window.addEventListener("storage", storageChange, false);
// Ask other tabs for sessionStorage (this is ONLY to trigger event).
localStorage.setItem(CLIPBOARD_ID + '_startup', Math.random());
/** /**
* Remembers the current selected elements on the clipboard. * Remembers the current selected elements on the clipboard.
* @function module:svgcanvas.SvgCanvas#copySelectedElements * @function module:svgcanvas.SvgCanvas#copySelectedElements
* @returns {void} * @returns {void}
*/ */
this.copySelectedElements = function () { this.copySelectedElements = function () {
localStorage.setItem('svgedit_clipboard', JSON.stringify( const data = JSON.stringify(
selectedElements.map(function (x) { return getJsonFromSvgElement(x); }) selectedElements.map(function (x) { return getJsonFromSvgElement(x); }));
)); // Use sessionStorage for the clipboard data.
sessionStorage.setItem(CLIPBOARD_ID, data);
flashStorage();
$('#cmenu_canvas').enableContextMenuItems('#paste,#paste_in_place'); let menu = $('#cmenu_canvas');
// Context menu might not exist (it is provided by editor.js).
if (menu.enableContextMenuItems) {
menu.enableContextMenuItems('#paste,#paste_in_place');
}
}; };
/** /**
@ -6372,9 +6412,10 @@ this.copySelectedElements = function () {
* @returns {void} * @returns {void}
*/ */
this.pasteElements = function (type, x, y) { this.pasteElements = function (type, x, y) {
let clipb = JSON.parse(localStorage.getItem('svgedit_clipboard')); let clipb = JSON.parse(sessionStorage.getItem(CLIPBOARD_ID));
if (!clipb) return;
let len = clipb.length; let len = clipb.length;
if (!len) { return; } if (!len) return;
const pasted = []; const pasted = [];
const batchCmd = new BatchCommand('Paste elements'); const batchCmd = new BatchCommand('Paste elements');