diff --git a/ajax/clipboard.php b/ajax/clipboard.php deleted file mode 100644 index 4c34128..0000000 --- a/ajax/clipboard.php +++ /dev/null @@ -1,55 +0,0 @@ -getL10N('files_clipboard'); - -$user = OCP\User::getUser(); -$view = new \OC\Files\View(); - -$required = array('operation', 'directory', 'files', 'destination'); -if(count(array_intersect_key(array_flip($required), $_POST)) !== count($required)) { - OCP\JSON::error(); - exit(); -} - -$messages = array(); -$cut = $_POST['operation'] == 'cut'; -foreach($_POST['files'] as $file) { - $source = $user . "/files/" . \OC\Files\Filesystem::normalizePath(stripslashes($_POST['directory']) . '/' . $file); - $target = $user . "/files" . \OC\Files\Filesystem::normalizePath(stripslashes($_POST['destination']) . '/' . $file); - - if (!$view->file_exists($source)) { - $messages[] = $l->t("Unable to paste '%s' item does not exists", array($file)); - continue; - } - - if (strpos($target, $source) === 0) { - if ($cut) { - $messages[] = $l->t("Unable to move folder '%s' into itself", array($file)); - } else { - $messages[] = $l->t("Unable to copy folder '%s' into itself", array($file)); - } - continue; - } - - if ($view->file_exists($target)) { - if (!$view->unlink($target)) { - $messages[] = $l->t("Could not remove '%s'", array($file)); - continue; - } - } - - if ($cut) { - if (!$view->rename($source, $target)) { - $messages[] = $l->t("Could not move '%s'", array($file)); - } - } else { - if (!$view->copy($source, $target)) { - $messages[] = $l->t("Could not copy '%s'", array($file)); - } - } -} - -if (empty($messages)) OCP\JSON::success(); -else OCP\JSON::error(array("messages" => $messages)); diff --git a/appinfo/info.xml b/appinfo/info.xml index 4672619..1ffd934 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -4,7 +4,7 @@ Files clipboard Clipboard operations for the files application Minimal clipboard feature for the files application. Allows to copy and move files between directories. - 0.6.5 + 0.7.1 AGPL Leizh tools diff --git a/appinfo/routes.php b/appinfo/routes.php deleted file mode 100644 index 3cd063b..0000000 --- a/appinfo/routes.php +++ /dev/null @@ -1,2 +0,0 @@ -create('files_clipboard_ajax', 'ajax/clipboard.php')->actionInclude('files_clipboard/ajax/clipboard.php'); \ No newline at end of file diff --git a/appinfo/version b/appinfo/version index ef5e445..39e898a 100644 --- a/appinfo/version +++ b/appinfo/version @@ -1 +1 @@ -0.6.5 +0.7.1 diff --git a/img/app.svg b/img/app.svg deleted file mode 100644 index 815854f..0000000 --- a/img/app.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/js/clipboard.js b/js/clipboard.js index d3b7792..49bd93b 100644 --- a/js/clipboard.js +++ b/js/clipboard.js @@ -1,202 +1,214 @@ -$(document).ready(function() { -if (!OCA.Files) return; - -var appid = 'files_clipboard', - $dir = $('#dir'), - $fileList = $('#fileList'); - -var $cut = $('') - .attr('id', 'clipboard_cut') - .append($('').addClass('svg').attr('src', OC.imagePath(appid,'cut'))) - .append(' ') - .append($('').text(t(appid,'Cut'))) - .on('click', function() { cut(); }) - .hide() - .appendTo('#headerName .selectedActions'); - -var $copy = $('') - .attr('id', 'clipboard_copy') - .append($('').addClass('svg').attr('src', OC.imagePath(appid,'copy'))) - .append(' ') - .append($('').text(t(appid,'Copy'))) - .on('click', function() { copy(); }) - .hide() - .appendTo('#headerName .selectedActions'); - -var $paste = $('') - .attr('id', 'clipboard_paste') - .append($('').addClass('svg').attr('alt', t(appid, 'Paste')).attr('src', OC.imagePath(appid,'paste'))) - .addClass('button') - .on('click', paste) - .hide() - .appendTo('#controls .creatable'); - -var clipboard = JSON.parse(sessionStorage.getItem(appid)); -$fileList.on('changeDirectory', function() { - $fileList.off('DOMNodeRemoved', onRowRemoved); -}); -$fileList.on('fileActionsReady', function() { - $fileList.on('DOMNodeRemoved', onRowRemoved); -}); +$(document).ready(function () { + if (!OCA.Files) return; + + var appid = 'files_clipboard', + $dir = $('#dir'), + $fileList = $('#fileList'); + + var $cut = $('') + .attr('id', 'clipboard_cut') + .append($('').addClass('svg').attr('src', OC.imagePath(appid, 'cut'))) + .append(' ') + .append($('').text(t(appid, 'Cut'))) + .on('click', function () { cut(); }) + .hide() + .appendTo('#headerName .selectedActions'); + + var $copy = $('') + .attr('id', 'clipboard_copy') + .append($('').addClass('svg').attr('src', OC.imagePath(appid, 'copy'))) + .append(' ') + .append($('').text(t(appid, 'Copy'))) + .on('click', function () { copy(); }) + .hide() + .appendTo('#headerName .selectedActions'); + + var $paste = $('') + .attr('id', 'clipboard_paste') + .append($('').addClass('svg').attr('alt', t(appid, 'Paste')).attr('src', OC.imagePath(appid, 'paste'))) + .addClass('button') + .on('click', paste) + .hide() + .appendTo('#controls .creatable'); + + var clipboard = JSON.parse(sessionStorage.getItem(appid)); + $fileList.on('changeDirectory', function () { + $fileList.off('DOMNodeRemoved', onRowRemoved); + }); + $fileList.on('fileActionsReady', function () { + $fileList.on('DOMNodeRemoved', onRowRemoved); + }); -OCA.Files.fileActions.registerAction({ - name: 'Cut', - displayName: t('files_clipboard', 'Cut'), - mime: 'all', - order: -10, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('files_clipboard', 'cut.svg'), - actionHandler: cut -}); -OCA.Files.fileActions.registerAction({ - name: 'Copy', - displayName: t('files_clipboard', 'Copy'), - mime: 'all', - order: -9, - permissions: OC.PERMISSION_READ, - icon: OC.imagePath('files_clipboard', 'copy.svg'), - actionHandler: copy -}); + OCA.Files.fileActions.registerAction({ + name: 'Cut', + displayName: t('files_clipboard', 'Cut'), + mime: 'all', + order: -10, + permissions: OC.PERMISSION_READ, + icon: OC.imagePath('files_clipboard', 'cut.svg'), + actionHandler: cut + }); + OCA.Files.fileActions.registerAction({ + name: 'Copy', + displayName: t('files_clipboard', 'Copy'), + mime: 'all', + order: -9, + permissions: OC.PERMISSION_READ, + icon: OC.imagePath('files_clipboard', 'copy.svg'), + actionHandler: copy + }); -function onRowRemoved(event) { - var $target = $(event.target); - if (clipboard && clipboard.directory == $dir.val() && $target.is('tr[data-file]')) { - var fileIndex = clipboard.files.indexOf($target.attr('data-file')); - if (fileIndex != -1) { - clipboard.files.splice(fileIndex, 1); - if (!clipboard.files.length) clipboard = null; + function onRowRemoved(event) { + var $target = $(event.target); + if (clipboard && clipboard.directory == $dir.val() && $target.is('tr[data-file]')) { + var fileIndex = clipboard.files.indexOf($target.attr('data-file')); + if (fileIndex != -1) { + clipboard.files.splice(fileIndex, 1); + if (!clipboard.files.length) clipboard = null; + } + update(); } - update(); } -} - -function update(blink) { - var permissions = parseInt($('#permissions').val()); - - $cut.toggle((permissions & OC.PERMISSION_READ && permissions & OC.PERMISSION_UPDATE) != 0); - $copy.toggle((permissions & OC.PERMISSION_READ) != 0); - - if (clipboard) { - var sameDirectory = clipboard.directory == $dir.val(), - noPermissions = !(permissions & OC.PERMISSION_CREATE), - disabled = noPermissions || sameDirectory, - title; - if (sameDirectory) title = t(appid, 'Unable to paste: the files come from this directory.') - else if (noPermissions) title = t(appid, 'Unable to paste: you do not have the permissions to create files in this directory.') - else title = n(appid, 'Paste %n item', 'Paste %n items', clipboard.files.length); - - $paste - .toggleClass('disabled', disabled) - .attr('title', title) - .tipsy({gravity:'ne', fade:true}) - .show(); - - if (clipboard.operation == 'cut' && clipboard.directory == $dir.val()) { - var $trs = $('tr', $fileList); - clipboard.files.forEach(function(file) { - $trs.filterAttr('data-file', file).addClass('cut'); - }); - } - - if (blink === true) { - $paste.addClass('blink'); - setTimeout(function () { $paste.removeClass('blink'); }, 500); + + function update(blink) { + var permissions = parseInt($('#permissions').val()); + + $cut.toggle((permissions & OC.PERMISSION_READ && permissions & OC.PERMISSION_UPDATE) != 0); + $copy.toggle((permissions & OC.PERMISSION_READ) != 0); + + if (clipboard) { + var sameDirectory = clipboard.directory == $dir.val(), + noPermissions = !(permissions & OC.PERMISSION_CREATE), + disabled = noPermissions || sameDirectory, + title; + if (sameDirectory) title = t(appid, 'Unable to paste: the files come from this directory.') + else if (noPermissions) title = t(appid, 'Unable to paste: you do not have the permissions to create files in this directory.') + else title = n(appid, 'Paste %n item', 'Paste %n items', clipboard.files.length); + + $paste + .toggleClass('disabled', disabled) + .attr('title', title) + .tipsy({ gravity: 'ne', fade: true }) + .show(); + + if (clipboard.operation == 'cut' && clipboard.directory == $dir.val()) { + var $trs = $('tr', $fileList); + clipboard.files.forEach(function (file) { + $trs.filterAttr('data-file', file).addClass('cut'); + }); + } + + if (blink === true) { + $paste.addClass('blink'); + setTimeout(function () { $paste.removeClass('blink'); }, 500); + } + } else { + $paste.hide(); } - } else { - $paste.hide(); + }; + + function clearCut() { + $('tr[data-file]', $fileList).removeClass('cut'); + } + + function cut(file) { + var files = file ? [file] : FileList.getSelectedFiles().map(function (file) { return file.name; }); + clipboard = { operation: 'cut', directory: $dir.val(), files: files }; + sessionStorage.setItem(appid, JSON.stringify(clipboard)); + clearCut(); + clearSelection(); + update(true); + } + + function copy(file) { + var files = file ? [file] : FileList.getSelectedFiles().map(function (file) { return file.name; }); + clipboard = { operation: 'copy', directory: $dir.val(), files: files }; + sessionStorage.setItem(appid, JSON.stringify(clipboard)); + clearCut(); + clearSelection(); + update(true); } -}; - -function clearCut() { - $('tr[data-file]', $fileList).removeClass('cut'); -} - -function cut (file) { - var files = file ? [ file ] : FileList.getSelectedFiles().map(function(file) { return file.name; }); - clipboard = { operation: 'cut', directory: $dir.val(), files: files }; - sessionStorage.setItem(appid, JSON.stringify(clipboard)); - clearCut(); - clearSelection(); - update(true); -} - -function copy (file) { - var files = file ? [ file ] : FileList.getSelectedFiles().map(function(file) { return file.name; }); - clipboard = { operation: 'copy', directory: $dir.val(), files: files }; - sessionStorage.setItem(appid, JSON.stringify(clipboard)); - clearCut(); - clearSelection(); - update(true); -} - -function clearSelection() { - $('tr[data-file]', $fileList).removeClass('selected'); - $('tr[data-file] input[type="checkbox"]', $fileList).removeAttr('checked'); - FileList._selectedFiles = {}; - FileList._selectionSummary.clear(); - FileList.updateSelectionSummary(); -} - -function paste() { - if ($(this).hasClass('disabled')) return; - FileList.showMask(); - clipboard.destination = $dir.val(); - $(window).on('beforeunload', processing); - replaceExistingFiles(function(replace) { - if (!replace) FileList.hideMask(); - else $.ajax({ - type: 'POST', - url: OC.filePath(appid, 'ajax', 'clipboard.php'), - data: clipboard, - success: function (data) { - if (data.status == 'error') { - var message; - if (data.messages.length === 1) { - message = data.messages[0]; - } else { - if (clipboard.operation == 'cut') message = '' + t(appid, 'An error occurred during the move.') + ''; - else message = '' + t(appid, 'An error occurred during the copy.') + ''; - message += '

'; - for (var i = data.messages.length - 1; i >= 0; --i) message += data.messages[i] + '
'; - message += '

'; - } - OC.Notification.hide(); - OC.Notification.showHtml(message); - } else { - if (clipboard.operation == 'cut') { - sessionStorage.removeItem(appid); - clipboard = null; - } - } - FileList.reload(); - }, - complete: function (request) { - $(window).off('beforeunload', processing); - }, - dataType: 'json' + + function clearSelection() { + $('tr[data-file]', $fileList).removeClass('selected'); + $('tr[data-file] input[type="checkbox"]', $fileList).removeAttr('checked'); + FileList._selectedFiles = {}; + FileList._selectionSummary.clear(); + FileList.updateSelectionSummary(); + } + + function paste() { + if ($(this).hasClass('disabled')) return; + FileList.showMask(); + clipboard.destination = $dir.val(); + $(window).on('beforeunload', processing); + replaceExistingFiles(function (replace) { + if (!replace) FileList.hideMask(); + else { + var promises = clipboard.files.map(function (file) { + var headers = { + 'Destination': FileList.filesClient._buildUrl(clipboard.destination, file) + }; + + return FileList.filesClient._client.request( + clipboard.operation == 'cut' ? 'MOVE' : 'COPY', + FileList.filesClient._buildUrl(clipboard.directory, file), + headers + ).then(function (response) { + if (response.status >= 200 && response.status < 300) { + return true; + } else { + console.error(response.status, response.xhr.responseXML || response.xhr.responseText); + return file; + } + }); + }); + + Promise.all(promises) + .then(function (results) { + var rejectedFiles = results.filter(function (item) { return item !== true }); + if (rejectedFiles.length) { + var message; + if (clipboard.operation == 'cut') message = '' + t(appid, "An error occurred during the move.") + ''; + else message = '' + t(appid, "An error occurred during the copy.") + ''; + message += '

'; + for (var i = rejectedFiles.length - 1; i >= 0; --i) message += rejectedFiles[i] + '
'; + message += '

'; + OC.Notification.showHtml(message, { type: 'error' }); + } + if (clipboard.operation == 'cut') { + sessionStorage.removeItem(appid); + clipboard = null; + } + $(window).off('beforeunload', processing); + FileList.reload(); + }) + .catch(function (error) { + console.error(error); + }); + + } }); - - }); -} + } -function processing() { - if (clipboard.operation == 'cut') message = t(appid, 'Processing. Leaving the page now will interrupt the move.'); - else message = t(appid, 'Processing. Leaving the page now will interrupt the copy.'); -} + function processing() { + if (clipboard.operation == 'cut') message = t(appid, 'Processing. Leaving the page now will interrupt the move.'); + else message = t(appid, 'Processing. Leaving the page now will interrupt the copy.'); + } -function replaceExistingFiles(callback) { - var $trs = $('tr', $fileList); - var existing = clipboard.files.filter(function(file) { - return $trs.filterAttr('data-file', file).attr('data-file'); - }); - if (!existing.length) callback(true); - else { - var message = t(appid, 'The contents of the clipboard is in conflicts with elements already present in this directory. Do you want to replace them ?'); - OC.dialogs.confirm(message, t(appid, 'Paste'), callback, true); + function replaceExistingFiles(callback) { + var $trs = $('tr', $fileList); + var existing = clipboard.files.filter(function (file) { + return $trs.filterAttr('data-file', file).attr('data-file'); + }); + if (!existing.length) callback(true); + else { + var message = t(appid, 'The contents of the clipboard is in conflicts with elements already present in this directory. Do you want to replace them ?'); + OC.dialogs.confirm(message, t(appid, 'Paste'), callback, true); + } } -} -$fileList.on('updated', update); -update(); + $fileList.on('updated', update); + update(); });