mirror of
https://github.com/nextcloud/server.git
synced 2026-02-18 18:28:50 -05:00
chore!(core): drop deprecated OC.Dialogs.fileexists
It is deprecated since 29.0.0. Instead use `openConflictPicker` from the `@nextcloud/upload` (Vue 2). Or from `@nextcloud/dialogs` (every other framework like Vue 3 etc). Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
This commit is contained in:
parent
9c8f80102a
commit
16f4ff98e4
3 changed files with 1 additions and 436 deletions
|
|
@ -60,14 +60,6 @@
|
|||
"count": 1
|
||||
}
|
||||
},
|
||||
"core/src/OC/dialogs.js": {
|
||||
"camelcase": {
|
||||
"count": 33
|
||||
},
|
||||
"no-undef": {
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"core/src/views/Login.vue": {
|
||||
"vue/multi-word-component-names": {
|
||||
"count": 1
|
||||
|
|
|
|||
|
|
@ -9,14 +9,12 @@ import IconCopy from '@mdi/svg/svg/folder-multiple-outline.svg?raw'
|
|||
import { DialogBuilder, FilePickerType, getFilePickerBuilder } from '@nextcloud/dialogs'
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { spawnDialog } from '@nextcloud/vue/functions/dialog'
|
||||
import $ from 'jquery'
|
||||
import { basename } from 'path'
|
||||
import { defineAsyncComponent } from 'vue'
|
||||
import logger from '../logger.js'
|
||||
import OC from './index.js'
|
||||
|
||||
/**
|
||||
* this class to ease the usage of jquery dialogs
|
||||
* this class to ease the usage of dialogs
|
||||
*/
|
||||
const Dialogs = {
|
||||
// dialog button types
|
||||
|
|
@ -410,396 +408,6 @@ const Dialogs = {
|
|||
}
|
||||
return buttonList
|
||||
},
|
||||
|
||||
_fileexistsshown: false,
|
||||
/**
|
||||
* Displays file exists dialog
|
||||
*
|
||||
* @param {object} data upload object
|
||||
* @param {object} original file with name, size and mtime
|
||||
* @param {object} replacement file with name, size and mtime
|
||||
* @param {object} controller with onCancel, onSkip, onReplace and onRename methods
|
||||
* @return {Promise} jquery promise that resolves after the dialog template was loaded
|
||||
*
|
||||
* @deprecated 29.0.0 Use openConflictPicker from the @nextcloud/upload package instead
|
||||
*/
|
||||
fileexists: function(data, original, replacement, controller) {
|
||||
const self = this
|
||||
const dialogDeferred = new $.Deferred()
|
||||
|
||||
const getCroppedPreview = function(file) {
|
||||
const deferred = new $.Deferred()
|
||||
// Only process image files.
|
||||
const type = file.type && file.type.split('/').shift()
|
||||
if (window.FileReader && type === 'image') {
|
||||
const reader = new FileReader()
|
||||
reader.onload = function(e) {
|
||||
const blob = new Blob([e.target.result])
|
||||
window.URL = window.URL || window.webkitURL
|
||||
const originalUrl = window.URL.createObjectURL(blob)
|
||||
const image = new Image()
|
||||
image.src = originalUrl
|
||||
image.onload = function() {
|
||||
const url = crop(image)
|
||||
deferred.resolve(url)
|
||||
}
|
||||
}
|
||||
reader.readAsArrayBuffer(file)
|
||||
} else {
|
||||
deferred.reject()
|
||||
}
|
||||
return deferred
|
||||
}
|
||||
|
||||
/**
|
||||
* @param img
|
||||
*/
|
||||
function crop(img) {
|
||||
const canvas = document.createElement('canvas')
|
||||
const targetSize = 96
|
||||
const width = img.width
|
||||
const height = img.height
|
||||
let x
|
||||
let y
|
||||
|
||||
// Calculate the width and height, constraining the proportions
|
||||
if (width > height) {
|
||||
y = 0
|
||||
x = (width - height) / 2
|
||||
} else {
|
||||
y = (height - width) / 2
|
||||
x = 0
|
||||
}
|
||||
const size = Math.min(width, height)
|
||||
|
||||
// Set canvas size to the cropped area
|
||||
canvas.width = size
|
||||
canvas.height = size
|
||||
const ctx = canvas.getContext('2d')
|
||||
ctx.drawImage(img, x, y, size, size, 0, 0, size, size)
|
||||
|
||||
// Resize the canvas to match the destination (right size uses 96px)
|
||||
resampleHermite(canvas, size, size, targetSize, targetSize)
|
||||
|
||||
return canvas.toDataURL('image/png', 0.7)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast image resize/resample using Hermite filter with JavaScript.
|
||||
*
|
||||
* @author ViliusL
|
||||
*
|
||||
* @param {*} canvas
|
||||
* @param {number} W
|
||||
* @param {number} H
|
||||
* @param {number} W2
|
||||
* @param {number} H2
|
||||
*/
|
||||
function resampleHermite(canvas, W, H, W2, H2) {
|
||||
W2 = Math.round(W2)
|
||||
H2 = Math.round(H2)
|
||||
const img = canvas.getContext('2d').getImageData(0, 0, W, H)
|
||||
const img2 = canvas.getContext('2d').getImageData(0, 0, W2, H2)
|
||||
const data = img.data
|
||||
const data2 = img2.data
|
||||
const ratio_w = W / W2
|
||||
const ratio_h = H / H2
|
||||
const ratio_w_half = Math.ceil(ratio_w / 2)
|
||||
const ratio_h_half = Math.ceil(ratio_h / 2)
|
||||
|
||||
for (let j = 0; j < H2; j++) {
|
||||
for (let i = 0; i < W2; i++) {
|
||||
const x2 = (i + j * W2) * 4
|
||||
let weight = 0
|
||||
let weights = 0
|
||||
let weights_alpha = 0
|
||||
let gx_r = 0
|
||||
let gx_g = 0
|
||||
let gx_b = 0
|
||||
let gx_a = 0
|
||||
const center_y = (j + 0.5) * ratio_h
|
||||
for (let yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++) {
|
||||
const dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half
|
||||
const center_x = (i + 0.5) * ratio_w
|
||||
const w0 = dy * dy // pre-calc part of w
|
||||
for (let xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++) {
|
||||
let dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half
|
||||
const w = Math.sqrt(w0 + dx * dx)
|
||||
if (w >= -1 && w <= 1) {
|
||||
// hermite filter
|
||||
weight = 2 * w * w * w - 3 * w * w + 1
|
||||
if (weight > 0) {
|
||||
dx = 4 * (xx + yy * W)
|
||||
// alpha
|
||||
gx_a += weight * data[dx + 3]
|
||||
weights_alpha += weight
|
||||
// colors
|
||||
if (data[dx + 3] < 255) {
|
||||
weight = weight * data[dx + 3] / 250
|
||||
}
|
||||
gx_r += weight * data[dx]
|
||||
gx_g += weight * data[dx + 1]
|
||||
gx_b += weight * data[dx + 2]
|
||||
weights += weight
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
data2[x2] = gx_r / weights
|
||||
data2[x2 + 1] = gx_g / weights
|
||||
data2[x2 + 2] = gx_b / weights
|
||||
data2[x2 + 3] = gx_a / weights_alpha
|
||||
}
|
||||
}
|
||||
canvas.getContext('2d').clearRect(0, 0, Math.max(W, W2), Math.max(H, H2))
|
||||
canvas.width = W2
|
||||
canvas.height = H2
|
||||
canvas.getContext('2d').putImageData(img2, 0, 0)
|
||||
}
|
||||
|
||||
const addConflict = function($conflicts, original, replacement) {
|
||||
const $conflict = $conflicts.find('.template').clone().removeClass('template').addClass('conflict')
|
||||
const $originalDiv = $conflict.find('.original')
|
||||
const $replacementDiv = $conflict.find('.replacement')
|
||||
|
||||
$conflict.data('data', data)
|
||||
|
||||
$conflict.find('.filename').text(original.name)
|
||||
$originalDiv.find('.size').text(OC.Util.humanFileSize(original.size))
|
||||
$originalDiv.find('.mtime').text(OC.Util.formatDate(original.mtime))
|
||||
// ie sucks
|
||||
if (replacement.size && replacement.lastModified) {
|
||||
$replacementDiv.find('.size').text(OC.Util.humanFileSize(replacement.size))
|
||||
$replacementDiv.find('.mtime').text(OC.Util.formatDate(replacement.lastModified))
|
||||
}
|
||||
let path = original.directory + '/' + original.name
|
||||
const urlSpec = {
|
||||
file: path,
|
||||
x: 96,
|
||||
y: 96,
|
||||
c: original.etag,
|
||||
forceIcon: 0,
|
||||
}
|
||||
let previewpath = Files.generatePreviewUrl(urlSpec)
|
||||
// Escaping single quotes
|
||||
previewpath = previewpath.replace(/'/g, '%27')
|
||||
$originalDiv.find('.icon').css({ 'background-image': "url('" + previewpath + "')" })
|
||||
getCroppedPreview(replacement).then(function(path) {
|
||||
$replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
|
||||
}, function() {
|
||||
path = OC.MimeType.getIconUrl(replacement.type)
|
||||
$replacementDiv.find('.icon').css('background-image', 'url(' + path + ')')
|
||||
})
|
||||
// connect checkboxes with labels
|
||||
const checkboxId = $conflicts.find('.conflict').length
|
||||
$originalDiv.find('input:checkbox').attr('id', 'checkbox_original_' + checkboxId)
|
||||
$replacementDiv.find('input:checkbox').attr('id', 'checkbox_replacement_' + checkboxId)
|
||||
|
||||
$conflicts.append($conflict)
|
||||
|
||||
// set more recent mtime bold
|
||||
// ie sucks
|
||||
if (replacement.lastModified > original.mtime) {
|
||||
$replacementDiv.find('.mtime').css('font-weight', 'bold')
|
||||
} else if (replacement.lastModified < original.mtime) {
|
||||
$originalDiv.find('.mtime').css('font-weight', 'bold')
|
||||
} else {
|
||||
// TODO add to same mtime collection?
|
||||
}
|
||||
|
||||
// set bigger size bold
|
||||
if (replacement.size && replacement.size > original.size) {
|
||||
$replacementDiv.find('.size').css('font-weight', 'bold')
|
||||
} else if (replacement.size && replacement.size < original.size) {
|
||||
$originalDiv.find('.size').css('font-weight', 'bold')
|
||||
} else {
|
||||
// TODO add to same size collection?
|
||||
}
|
||||
|
||||
// TODO show skip action for files with same size and mtime in bottom row
|
||||
|
||||
// always keep readonly files
|
||||
|
||||
if (original.status === 'readonly') {
|
||||
$originalDiv
|
||||
.addClass('readonly')
|
||||
.find('input[type="checkbox"]')
|
||||
.prop('checked', true)
|
||||
.prop('disabled', true)
|
||||
$originalDiv.find('.message')
|
||||
.text(t('core', 'read-only'))
|
||||
}
|
||||
}
|
||||
|
||||
const dialogName = 'oc-dialog-fileexists-content'
|
||||
const dialogId = '#' + dialogName
|
||||
if (this._fileexistsshown) {
|
||||
// add conflict
|
||||
|
||||
const $conflicts = $(dialogId + ' .conflicts')
|
||||
addConflict($conflicts, original, replacement)
|
||||
|
||||
const count = $(dialogId + ' .conflict').length
|
||||
const title = n(
|
||||
'core',
|
||||
'{count} file conflict',
|
||||
'{count} file conflicts',
|
||||
count,
|
||||
{ count },
|
||||
)
|
||||
$(dialogId).parent().children('.oc-dialog-title').text(title)
|
||||
|
||||
// recalculate dimensions
|
||||
$(window).trigger('resize')
|
||||
dialogDeferred.resolve()
|
||||
} else {
|
||||
// create dialog
|
||||
this._fileexistsshown = true
|
||||
$.when(this._getFileExistsTemplate()).then(function($tmpl) {
|
||||
const title = t('core', 'One file conflict')
|
||||
const $dlg = $tmpl.octemplate({
|
||||
dialog_name: dialogName,
|
||||
title,
|
||||
type: 'fileexists',
|
||||
|
||||
allnewfiles: t('core', 'New Files'),
|
||||
allexistingfiles: t('core', 'Already existing files'),
|
||||
|
||||
why: t('core', 'Which files do you want to keep?'),
|
||||
what: t('core', 'If you select both versions, the copied file will have a number added to its name.'),
|
||||
})
|
||||
$('body').append($dlg)
|
||||
|
||||
if (original && replacement) {
|
||||
const $conflicts = $dlg.find('.conflicts')
|
||||
addConflict($conflicts, original, replacement)
|
||||
}
|
||||
|
||||
const buttonlist = [{
|
||||
text: t('core', 'Cancel'),
|
||||
classes: 'cancel',
|
||||
click: function() {
|
||||
if (typeof controller.onCancel !== 'undefined') {
|
||||
controller.onCancel(data)
|
||||
}
|
||||
$(dialogId).ocdialog('close')
|
||||
},
|
||||
}, {
|
||||
text: t('core', 'Continue'),
|
||||
classes: 'continue',
|
||||
click: function() {
|
||||
if (typeof controller.onContinue !== 'undefined') {
|
||||
controller.onContinue($(dialogId + ' .conflict'))
|
||||
}
|
||||
$(dialogId).ocdialog('close')
|
||||
},
|
||||
}]
|
||||
|
||||
$(dialogId).ocdialog({
|
||||
width: 500,
|
||||
closeOnEscape: true,
|
||||
modal: true,
|
||||
buttons: buttonlist,
|
||||
closeButton: null,
|
||||
close: function() {
|
||||
self._fileexistsshown = false
|
||||
try {
|
||||
$(this).ocdialog('destroy').remove()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
$(dialogId).css('height', 'auto')
|
||||
|
||||
const $primaryButton = $dlg.closest('.oc-dialog').find('button.continue')
|
||||
$primaryButton.prop('disabled', true)
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
function updatePrimaryButton() {
|
||||
const checkedCount = $dlg.find('.conflicts .checkbox:checked').length
|
||||
$primaryButton.prop('disabled', checkedCount === 0)
|
||||
}
|
||||
|
||||
// add checkbox toggling actions
|
||||
$(dialogId).find('.allnewfiles').on('click', function() {
|
||||
const $checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]')
|
||||
$checkboxes.prop('checked', $(this).prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.allexistingfiles').on('click', function() {
|
||||
const $checkboxes = $(dialogId).find('.conflict .original:not(.readonly) input[type="checkbox"]')
|
||||
$checkboxes.prop('checked', $(this).prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.conflicts').on('click', '.replacement,.original:not(.readonly)', function() {
|
||||
const $checkbox = $(this).find('input[type="checkbox"]')
|
||||
$checkbox.prop('checked', !$checkbox.prop('checked'))
|
||||
})
|
||||
$(dialogId).find('.conflicts').on('click', '.replacement input[type="checkbox"],.original:not(.readonly) input[type="checkbox"]', function() {
|
||||
const $checkbox = $(this)
|
||||
$checkbox.prop('checked', !$checkbox.prop('checked'))
|
||||
})
|
||||
|
||||
// update counters
|
||||
$(dialogId).on('click', '.replacement,.allnewfiles', function() {
|
||||
const count = $(dialogId).find('.conflict .replacement input[type="checkbox"]:checked').length
|
||||
if (count === $(dialogId + ' .conflict').length) {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', true)
|
||||
$(dialogId).find('.allnewfiles + .count').text(t('core', '(all selected)'))
|
||||
} else if (count > 0) {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', false)
|
||||
$(dialogId).find('.allnewfiles + .count').text(t('core', '({count} selected)', { count }))
|
||||
} else {
|
||||
$(dialogId).find('.allnewfiles').prop('checked', false)
|
||||
$(dialogId).find('.allnewfiles + .count').text('')
|
||||
}
|
||||
updatePrimaryButton()
|
||||
})
|
||||
$(dialogId).on('click', '.original,.allexistingfiles', function() {
|
||||
const count = $(dialogId).find('.conflict .original input[type="checkbox"]:checked').length
|
||||
if (count === $(dialogId + ' .conflict').length) {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', true)
|
||||
$(dialogId).find('.allexistingfiles + .count').text(t('core', '(all selected)'))
|
||||
} else if (count > 0) {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', false)
|
||||
$(dialogId).find('.allexistingfiles + .count')
|
||||
.text(t('core', '({count} selected)', { count }))
|
||||
} else {
|
||||
$(dialogId).find('.allexistingfiles').prop('checked', false)
|
||||
$(dialogId).find('.allexistingfiles + .count').text('')
|
||||
}
|
||||
updatePrimaryButton()
|
||||
})
|
||||
|
||||
dialogDeferred.resolve()
|
||||
})
|
||||
.fail(function() {
|
||||
dialogDeferred.reject()
|
||||
alert(t('core', 'Error loading file exists template'))
|
||||
})
|
||||
}
|
||||
// }
|
||||
return dialogDeferred.promise()
|
||||
},
|
||||
|
||||
_getFileExistsTemplate: function() {
|
||||
const defer = $.Deferred()
|
||||
if (!this.$fileexistsTemplate) {
|
||||
const self = this
|
||||
$.get(OC.filePath('core', 'templates/legacy', 'fileexists.html'), function(tmpl) {
|
||||
self.$fileexistsTemplate = $(tmpl)
|
||||
defer.resolve(self.$fileexistsTemplate)
|
||||
})
|
||||
.fail(function() {
|
||||
defer.reject()
|
||||
})
|
||||
} else {
|
||||
defer.resolve(this.$fileexistsTemplate)
|
||||
}
|
||||
return defer.promise()
|
||||
},
|
||||
}
|
||||
|
||||
export default Dialogs
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
<!--
|
||||
- SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors
|
||||
- SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
<div id="{dialog_name}" title="{title}" class="fileexists">
|
||||
<span class="why">{why}<!-- Which files do you want to keep --></span><br/>
|
||||
<span class="what">{what}<!-- If you select both versions, the copied file will have a number added to its name. --></span><br/>
|
||||
<br/>
|
||||
<table>
|
||||
<th><input id="checkbox-allnewfiles" class="allnewfiles checkbox" type="checkbox" /><label for="checkbox-allnewfiles">{allnewfiles}<span class="count"></span></label></th>
|
||||
<th><input id="checkbox-allexistingfiles" class="allexistingfiles checkbox" type="checkbox" /><label for="checkbox-allexistingfiles">{allexistingfiles}<span class="count"></span></label></th>
|
||||
</table>
|
||||
<div class="conflicts">
|
||||
<div class="template">
|
||||
<div class="filename"></div>
|
||||
<div class="replacement">
|
||||
<input type="checkbox" class="checkbox u-left"/>
|
||||
<label>
|
||||
<span class="svg icon"></span>
|
||||
<div class="mtime"></div>
|
||||
<div class="size"></div>
|
||||
</label>
|
||||
</div>
|
||||
<div class="original">
|
||||
<input type="checkbox" class="checkbox u-left" />
|
||||
<label>
|
||||
<span class="svg icon"></span>
|
||||
<div class="mtime"></div>
|
||||
<div class="size"></div>
|
||||
<div class="message"></div>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
Loading…
Reference in a new issue