123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272 |
- /* global alert */
- /* eslint-disable */
- /*
- * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- * @copyright Copyright (c) 2019 Gary Kim <gary@garykim.dev>
- *
- * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at>
- * @author Gary Kim <gary@garykim.dev>
- *
- * @license GNU AGPL version 3 or any later version
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
- import _ from 'underscore'
- import $ from 'jquery'
-
- import OC from './index'
- import OCA from '../OCA/index'
-
- /**
- * this class to ease the usage of jquery dialogs
- */
- const Dialogs = {
- // dialog button types
- YES_NO_BUTTONS: 70,
- OK_BUTTONS: 71,
-
- FILEPICKER_TYPE_CHOOSE: 1,
- FILEPICKER_TYPE_MOVE: 2,
- FILEPICKER_TYPE_COPY: 3,
- FILEPICKER_TYPE_COPY_MOVE: 4,
-
- // used to name each dialog
- dialogsCounter: 0,
-
- /**
- * displays alert dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses OK
- * @param {boolean} [modal] make the dialog modal
- */
- alert: function(text, title, callback, modal) {
- this.message(
- text,
- title,
- 'alert',
- Dialogs.OK_BUTTON,
- callback,
- modal
- )
- },
- /**
- * displays info dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses OK
- * @param {boolean} [modal] make the dialog modal
- */
- info: function(text, title, callback, modal) {
- this.message(text, title, 'info', Dialogs.OK_BUTTON, callback, modal)
- },
-
- /**
- * displays confirmation dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
- * @param {boolean} [modal] make the dialog modal
- * @returns {Promise}
- */
- confirm: function(text, title, callback, modal) {
- return this.message(
- text,
- title,
- 'notice',
- Dialogs.YES_NO_BUTTONS,
- callback,
- modal
- )
- },
- /**
- * displays confirmation dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {{type: Int, confirm: String, cancel: String, confirmClasses: String}} buttons text content of buttons
- * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
- * @param {boolean} [modal] make the dialog modal
- * @returns {Promise}
- */
- confirmDestructive: function(text, title, buttons, callback, modal) {
- return this.message(
- text,
- title,
- 'none',
- buttons,
- callback,
- modal
- )
- },
- /**
- * displays confirmation dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
- * @param {boolean} [modal] make the dialog modal
- * @returns {Promise}
- */
- confirmHtml: function(text, title, callback, modal) {
- return this.message(
- text,
- title,
- 'notice',
- Dialogs.YES_NO_BUTTONS,
- callback,
- modal,
- true
- )
- },
- /**
- * displays prompt dialog
- * @param {string} text content of dialog
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses OK (true or false would be passed to callback respectively)
- * @param {boolean} [modal] make the dialog modal
- * @param {string} name name of the input field
- * @param {boolean} password whether the input should be a password input
- * @returns {Promise}
- */
- prompt: function(text, title, callback, modal, name, password) {
- return $.when(this._getMessageTemplate()).then(function($tmpl) {
- var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
- var dialogId = '#' + dialogName
- var $dlg = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- message: text,
- type: 'notice'
- })
- var input = $('<input/>')
- input.attr('type', password ? 'password' : 'text').attr('id', dialogName + '-input').attr('placeholder', name)
- var label = $('<label/>').attr('for', dialogName + '-input').text(name + ': ')
- $dlg.append(label)
- $dlg.append(input)
- if (modal === undefined) {
- modal = false
- }
- $('body').append($dlg)
-
- // wrap callback in _.once():
- // only call callback once and not twice (button handler and close
- // event) but call it for the close event, if ESC or the x is hit
- if (callback !== undefined) {
- callback = _.once(callback)
- }
-
- var buttonlist = [{
- text: t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(false, input.val())
- }
- $(dialogId).ocdialog('close')
- }
- }, {
- text: t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(true, input.val())
- }
- $(dialogId).ocdialog('close')
- },
- defaultButton: true
- }]
-
- $(dialogId).ocdialog({
- closeOnEscape: true,
- modal: modal,
- buttons: buttonlist,
- close: function() {
- // callback is already fired if Yes/No is clicked directly
- if (callback !== undefined) {
- // eslint-disable-next-line standard/no-callback-literal
- callback(false, input.val())
- }
- }
- })
- input.focus()
- Dialogs.dialogsCounter++
- })
- },
- /**
- * show a file picker to pick a file from
- *
- * In order to pick several types of mime types they need to be passed as an
- * array of strings.
- *
- * When no mime type filter is given only files can be selected. In order to
- * be able to select both files and folders "['*', 'httpd/unix-directory']"
- * should be used instead.
- *
- * @param {string} title dialog title
- * @param {function} callback which will be triggered when user presses Choose
- * @param {boolean} [multiselect] whether it should be possible to select multiple files
- * @param {string[]} [mimetypeFilter] mimetype to filter by - directories will always be included
- * @param {boolean} [modal] make the dialog modal
- * @param {string} [type] Type of file picker : Choose, copy, move, copy and move
- * @param {string} [path] path to the folder that the the file can be picket from
- * @param {Object} [options] additonal options that need to be set
- */
- filepicker: function(title, callback, multiselect, mimetypeFilter, modal, type, path, options) {
- var self = this
-
- this.filepicker.sortField = 'name'
- this.filepicker.sortOrder = 'asc'
- // avoid opening the picker twice
- if (this.filepicker.loading) {
- return
- }
-
- if (type === undefined) {
- type = this.FILEPICKER_TYPE_CHOOSE
- }
-
- var emptyText = t('core', 'No files in here')
- var newText = t('files', 'New folder')
- if (type === this.FILEPICKER_TYPE_COPY || type === this.FILEPICKER_TYPE_MOVE || type === this.FILEPICKER_TYPE_COPY_MOVE) {
- emptyText = t('core', 'No more subfolders in here')
- }
-
- this.filepicker.loading = true
- this.filepicker.filesClient = (OCA.Sharing && OCA.Sharing.PublicApp && OCA.Sharing.PublicApp.fileList) ? OCA.Sharing.PublicApp.fileList.filesClient : OC.Files.getClient()
-
- this.filelist = null
- path = path || ''
- options = Object.assign({
- allowDirectoryChooser: false
- }, options)
-
- $.when(this._getFilePickerTemplate()).then(function($tmpl) {
- self.filepicker.loading = false
- var dialogName = 'oc-dialog-filepicker-content'
- if (self.$filePicker) {
- self.$filePicker.ocdialog('close')
- }
-
- if (mimetypeFilter === undefined || mimetypeFilter === null) {
- mimetypeFilter = []
- }
- if (typeof (mimetypeFilter) === 'string') {
- mimetypeFilter = [mimetypeFilter]
- }
-
- self.$filePicker = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- emptytext: emptyText,
- newtext: newText,
- nameCol: t('core', 'Name'),
- sizeCol: t('core', 'Size'),
- modifiedCol: t('core', 'Modified')
- }).data('path', path).data('multiselect', multiselect).data('mimetype', mimetypeFilter).data('allowDirectoryChooser', options.allowDirectoryChooser)
-
- if (modal === undefined) {
- modal = false
- }
- if (multiselect === undefined) {
- multiselect = false
- }
-
- // No grid for IE!
- if (OC.Util.isIE()) {
- self.$filePicker.find('#picker-view-toggle').remove()
- self.$filePicker.find('#picker-filestable').removeClass('view-grid')
- }
-
- $('body').append(self.$filePicker)
-
- self.$showGridView = $('input#picker-showgridview')
- self.$showGridView.on('change', _.bind(self._onGridviewChange, self))
-
- if (!OC.Util.isIE()) {
- self._getGridSettings()
- }
-
- var newButton = self.$filePicker.find('.actions.creatable .button-add')
- if (type === self.FILEPICKER_TYPE_CHOOSE) {
- newButton.hide()
- }
- newButton.on('focus', function() {
- self.$filePicker.ocdialog('setEnterCallback', function() {
- event.stopImmediatePropagation()
- event.preventDefault()
- newButton.click()
- })
- })
- newButton.on('blur', function() {
- self.$filePicker.ocdialog('unsetEnterCallback')
- })
-
- OC.registerMenu(newButton, self.$filePicker.find('.menu'), function() {
- $input.focus()
- self.$filePicker.ocdialog('setEnterCallback', function() {
- event.stopImmediatePropagation()
- event.preventDefault()
- self.$form.submit()
- })
- var newName = $input.val()
- var lastPos = newName.lastIndexOf('.')
- if (lastPos === -1) {
- lastPos = newName.length
- }
- $input.selectRange(0, lastPos)
- })
- var $form = self.$filePicker.find('.filenameform')
- var $input = $form.find('input[type=\'text\']')
- var $submit = $form.find('input[type=\'submit\']')
- $submit.on('click', function(event) {
- event.stopImmediatePropagation()
- event.preventDefault()
- $form.submit()
- })
-
- var checkInput = function() {
- var filename = $input.val()
- try {
- if (!Files.isFileNameValid(filename)) {
- // Files.isFileNameValid(filename) throws an exception itself
- } else if (self.filelist.find(function(file) {
- return file.name === this
- }, filename)) {
- throw t('files', '{newName} already exists', { newName: filename }, undefined, {
- escape: false
- })
- } else {
- return true
- }
- } catch (error) {
- $input.attr('title', error)
- $input.tooltip({
- placement: 'right',
- trigger: 'manual',
- 'container': '.newFolderMenu'
- })
- $input.tooltip('fixTitle')
- $input.tooltip('show')
- $input.addClass('error')
- }
- return false
- }
-
- $form.on('submit', function(event) {
- event.stopPropagation()
- event.preventDefault()
-
- if (checkInput()) {
- var newname = $input.val()
- self.filepicker.filesClient.createDirectory(self.$filePicker.data('path') + "/" + newname).always(function (status) {
- self._fillFilePicker(self.$filePicker.data('path') + "/" + newname)
- })
- OC.hideMenus()
- self.$filePicker.ocdialog('unsetEnterCallback')
- self.$filePicker.click()
- $input.val(newText)
- }
- })
- $input.keypress(function(event) {
- if (event.keyCode === 13 || event.which === 13) {
- event.stopImmediatePropagation()
- event.preventDefault()
- $form.submit()
- }
- })
-
- self.$filePicker.ready(function() {
- self.$fileListHeader = self.$filePicker.find('.filelist thead tr')
- self.$filelist = self.$filePicker.find('.filelist tbody')
- self.$filelistContainer = self.$filePicker.find('.filelist-container')
- self.$dirTree = self.$filePicker.find('.dirtree')
- self.$dirTree.on('click', 'div:not(:last-child)', self, function(event) {
- self._handleTreeListSelect(event, type)
- })
- self.$filelist.on('click', 'tr', function(event) {
- self._handlePickerClick(event, $(this), type)
- })
- self.$fileListHeader.on('click', 'a', function(event) {
- var dir = self.$filePicker.data('path')
- self.filepicker.sortField = $(event.currentTarget).data('sort')
- self.filepicker.sortOrder = self.filepicker.sortOrder === 'asc' ? 'desc' : 'asc'
- self._fillFilePicker(dir)
- })
- self._fillFilePicker(path)
- })
-
- // build buttons
- var functionToCall = function(returnType) {
- if (callback !== undefined) {
- var datapath
- if (multiselect === true) {
- datapath = []
- self.$filelist.find('tr.filepicker_element_selected').each(function(index, element) {
- datapath.push(self.$filePicker.data('path') + '/' + $(element).data('entryname'))
- })
- } else {
- datapath = self.$filePicker.data('path')
- var selectedName = self.$filelist.find('tr.filepicker_element_selected').data('entryname')
- if (selectedName) {
- datapath += '/' + selectedName
- }
- }
- callback(datapath, returnType)
- self.$filePicker.ocdialog('close')
- }
- }
-
- var chooseCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_CHOOSE)
- }
-
- var copyCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_COPY)
- }
-
- var moveCallback = function() {
- functionToCall(Dialogs.FILEPICKER_TYPE_MOVE)
- }
-
- var buttonlist = []
- if (type === Dialogs.FILEPICKER_TYPE_CHOOSE) {
- buttonlist.push({
- text: t('core', 'Choose'),
- click: chooseCallback,
- defaultButton: true
- })
- } else {
- if (type === Dialogs.FILEPICKER_TYPE_COPY || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
- buttonlist.push({
- text: t('core', 'Copy'),
- click: copyCallback,
- defaultButton: false
- })
- }
- if (type === Dialogs.FILEPICKER_TYPE_MOVE || type === Dialogs.FILEPICKER_TYPE_COPY_MOVE) {
- buttonlist.push({
- text: t('core', 'Move'),
- click: moveCallback,
- defaultButton: true
- })
- }
- }
-
- self.$filePicker.ocdialog({
- closeOnEscape: true,
- // max-width of 600
- width: 600,
- height: 500,
- modal: modal,
- buttons: buttonlist,
- style: {
- buttons: 'aside'
- },
- close: function() {
- try {
- $(this).ocdialog('destroy').remove()
- } catch (e) {
- }
- self.$filePicker = null
- }
- })
-
- // We can access primary class only from oc-dialog.
- // Hence this is one of the approach to get the choose button.
- var getOcDialog = self.$filePicker.closest('.oc-dialog')
- var buttonEnableDisable = getOcDialog.find('.primary')
- if (self.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || self.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
- }
- })
- .fail(function(status, error) {
- // If the method is called while navigating away
- // from the page, it is probably not needed ;)
- self.filepicker.loading = false
- if (status !== 0) {
- alert(t('core', 'Error loading file picker template: {error}', { error: error }))
- }
- })
- },
- /**
- * Displays raw dialog
- * You better use a wrapper instead ...
- */
- message: function(content, title, dialogType, buttons, callback, modal, allowHtml) {
- return $.when(this._getMessageTemplate()).then(function($tmpl) {
- var dialogName = 'oc-dialog-' + Dialogs.dialogsCounter + '-content'
- var dialogId = '#' + dialogName
- var $dlg = $tmpl.octemplate({
- dialog_name: dialogName,
- title: title,
- message: content,
- type: dialogType
- }, allowHtml ? { escapeFunction: '' } : {})
- if (modal === undefined) {
- modal = false
- }
- $('body').append($dlg)
- var buttonlist = []
- switch (buttons) {
- case Dialogs.YES_NO_BUTTONS:
- buttonlist = [{
- text: t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- callback(false)
- }
- $(dialogId).ocdialog('close')
- }
- },
- {
- text: t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- callback(true)
- }
- $(dialogId).ocdialog('close')
- },
- defaultButton: true
- }]
- break
- case Dialogs.OK_BUTTON:
- var functionToCall = function() {
- $(dialogId).ocdialog('close')
- if (callback !== undefined) {
- callback()
- }
- }
- buttonlist[0] = {
- text: t('core', 'OK'),
- click: functionToCall,
- defaultButton: true
- }
- break
- default:
- if (typeof(buttons) === 'object') {
- switch (buttons.type) {
- case Dialogs.YES_NO_BUTTONS:
- buttonlist = [{
- text: buttons.cancel || t('core', 'No'),
- click: function() {
- if (callback !== undefined) {
- callback(false)
- }
- $(dialogId).ocdialog('close')
- }
- },
- {
- text: buttons.confirm || t('core', 'Yes'),
- click: function() {
- if (callback !== undefined) {
- callback(true)
- }
- $(dialogId).ocdialog('close')
- },
- defaultButton: true,
- classes: buttons.confirmClasses
- }]
- break
- }
- }
- break
- }
-
- $(dialogId).ocdialog({
- closeOnEscape: true,
- modal: modal,
- buttons: buttonlist
- })
- Dialogs.dialogsCounter++
- })
- .fail(function(status, error) {
- // If the method is called while navigating away from
- // the page, we still want to deliver the message.
- if (status === 0) {
- alert(title + ': ' + content)
- } else {
- alert(t('core', 'Error loading message template: {error}', { error: error }))
- }
- })
- },
- _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
- * @returns {Promise} jquery promise that resolves after the dialog template was loaded
- */
- fileexists: function(data, original, replacement, controller) {
- var self = this
- var dialogDeferred = new $.Deferred()
-
- var getCroppedPreview = function(file) {
- var deferred = new $.Deferred()
- // Only process image files.
- var type = file.type && file.type.split('/').shift()
- if (window.FileReader && type === 'image') {
- var reader = new FileReader()
- reader.onload = function(e) {
- var blob = new Blob([e.target.result])
- window.URL = window.URL || window.webkitURL
- var originalUrl = window.URL.createObjectURL(blob)
- var image = new Image()
- image.src = originalUrl
- image.onload = function() {
- var url = crop(image)
- deferred.resolve(url)
- }
- }
- reader.readAsArrayBuffer(file)
- } else {
- deferred.reject()
- }
- return deferred
- }
-
- var crop = function(img) {
- var canvas = document.createElement('canvas')
- var targetSize = 96
- var width = img.width
- var height = img.height
- var x; var y; var size
-
- // Calculate the width and height, constraining the proportions
- if (width > height) {
- y = 0
- x = (width - height) / 2
- } else {
- y = (height - width) / 2
- x = 0
- }
- size = Math.min(width, height)
-
- // Set canvas size to the cropped area
- canvas.width = size
- canvas.height = size
- var 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
- */
- var resampleHermite = function(canvas, W, H, W2, H2) {
- W2 = Math.round(W2)
- H2 = Math.round(H2)
- var img = canvas.getContext('2d').getImageData(0, 0, W, H)
- var img2 = canvas.getContext('2d').getImageData(0, 0, W2, H2)
- var data = img.data
- var data2 = img2.data
- var ratio_w = W / W2
- var ratio_h = H / H2
- var ratio_w_half = Math.ceil(ratio_w / 2)
- var ratio_h_half = Math.ceil(ratio_h / 2)
-
- for (var j = 0; j < H2; j++) {
- for (var i = 0; i < W2; i++) {
- var x2 = (i + j * W2) * 4
- var weight = 0
- var weights = 0
- var weights_alpha = 0
- var gx_r = 0
- var gx_g = 0
- var gx_b = 0
- var gx_a = 0
- var center_y = (j + 0.5) * ratio_h
- for (var yy = Math.floor(j * ratio_h); yy < (j + 1) * ratio_h; yy++) {
- var dy = Math.abs(center_y - (yy + 0.5)) / ratio_h_half
- var center_x = (i + 0.5) * ratio_w
- var w0 = dy * dy // pre-calc part of w
- for (var xx = Math.floor(i * ratio_w); xx < (i + 1) * ratio_w; xx++) {
- var dx = Math.abs(center_x - (xx + 0.5)) / ratio_w_half
- var 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)
- }
-
- var addConflict = function($conflicts, original, replacement) {
-
- var $conflict = $conflicts.find('.template').clone().removeClass('template').addClass('conflict')
- var $originalDiv = $conflict.find('.original')
- var $replacementDiv = $conflict.find('.replacement')
-
- $conflict.data('data', data)
-
- $conflict.find('.filename').text(original.name)
- $originalDiv.find('.size').text(humanFileSize(original.size))
- $originalDiv.find('.mtime').text(formatDate(original.mtime))
- // ie sucks
- if (replacement.size && replacement.lastModifiedDate) {
- $replacementDiv.find('.size').text(humanFileSize(replacement.size))
- $replacementDiv.find('.mtime').text(formatDate(replacement.lastModifiedDate))
- }
- var path = original.directory + '/' + original.name
- var urlSpec = {
- file: path,
- x: 96,
- y: 96,
- c: original.etag,
- forceIcon: 0
- }
- var 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
- var 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.lastModifiedDate && replacement.lastModifiedDate.getTime() > original.mtime) {
- $replacementDiv.find('.mtime').css('font-weight', 'bold')
- } else if (replacement.lastModifiedDate && replacement.lastModifiedDate.getTime() < 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'))
- }
- }
- // var selection = controller.getSelection(data.originalFiles);
- // if (selection.defaultAction) {
- // controller[selection.defaultAction](data);
- // } else {
- var dialogName = 'oc-dialog-fileexists-content'
- var dialogId = '#' + dialogName
- if (this._fileexistsshown) {
- // add conflict
-
- var $conflicts = $(dialogId + ' .conflicts')
- addConflict($conflicts, original, replacement)
-
- var count = $(dialogId + ' .conflict').length
- var title = n('core',
- '{count} file conflict',
- '{count} file conflicts',
- count,
- { 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) {
- var title = t('core', 'One file conflict')
- var $dlg = $tmpl.octemplate({
- dialog_name: dialogName,
- title: 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) {
- var $conflicts = $dlg.find('.conflicts')
- addConflict($conflicts, original, replacement)
- }
-
- var 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
- $(this).ocdialog('destroy').remove()
- }
- })
-
- $(dialogId).css('height', 'auto')
-
- var $primaryButton = $dlg.closest('.oc-dialog').find('button.continue')
- $primaryButton.prop('disabled', true)
-
- function updatePrimaryButton() {
- var checkedCount = $dlg.find('.conflicts .checkbox:checked').length
- $primaryButton.prop('disabled', checkedCount === 0)
- }
-
- // add checkbox toggling actions
- $(dialogId).find('.allnewfiles').on('click', function() {
- var $checkboxes = $(dialogId).find('.conflict .replacement input[type="checkbox"]')
- $checkboxes.prop('checked', $(this).prop('checked'))
- })
- $(dialogId).find('.allexistingfiles').on('click', function() {
- var $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() {
- var $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() {
- var $checkbox = $(this)
- $checkbox.prop('checked', !$checkbox.prop('checked'))
- })
-
- // update counters
- $(dialogId).on('click', '.replacement,.allnewfiles', function() {
- var 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: count }))
- } else {
- $(dialogId).find('.allnewfiles').prop('checked', false)
- $(dialogId).find('.allnewfiles + .count').text('')
- }
- updatePrimaryButton()
- })
- $(dialogId).on('click', '.original,.allexistingfiles', function() {
- var 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: 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()
- },
- // get the gridview setting and set the input accordingly
- _getGridSettings: function() {
- var self = this
- $.get(OC.generateUrl('/apps/files/api/v1/showgridview'), function(response) {
- self.$showGridView.get(0).checked = response.gridview
- self.$showGridView.next('#picker-view-toggle')
- .removeClass('icon-toggle-filelist icon-toggle-pictures')
- .addClass(response.gridview ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
- $('.list-container').toggleClass('view-grid', response.gridview)
- })
- },
- _onGridviewChange: function() {
- var show = this.$showGridView.is(':checked')
- // only save state if user is logged in
- if (OC.currentUser) {
- $.post(OC.generateUrl('/apps/files/api/v1/showgridview'), {
- show: show
- })
- }
- this.$showGridView.next('#picker-view-toggle')
- .removeClass('icon-toggle-filelist icon-toggle-pictures')
- .addClass(show ? 'icon-toggle-filelist' : 'icon-toggle-pictures')
- $('.list-container').toggleClass('view-grid', show)
- },
- _getFilePickerTemplate: function() {
- var defer = $.Deferred()
- if (!this.$filePickerTemplate) {
- var self = this
- $.get(OC.filePath('core', 'templates', 'filepicker.html'), function(tmpl) {
- self.$filePickerTemplate = $(tmpl)
- self.$listTmpl = self.$filePickerTemplate.find('.filelist tbody tr:first-child').detach()
- defer.resolve(self.$filePickerTemplate)
- })
- .fail(function(jqXHR, textStatus, errorThrown) {
- defer.reject(jqXHR.status, errorThrown)
- })
- } else {
- defer.resolve(this.$filePickerTemplate)
- }
- return defer.promise()
- },
- _getMessageTemplate: function() {
- var defer = $.Deferred()
- if (!this.$messageTemplate) {
- var self = this
- $.get(OC.filePath('core', 'templates', 'message.html'), function(tmpl) {
- self.$messageTemplate = $(tmpl)
- defer.resolve(self.$messageTemplate)
- })
- .fail(function(jqXHR, textStatus, errorThrown) {
- defer.reject(jqXHR.status, errorThrown)
- })
- } else {
- defer.resolve(this.$messageTemplate)
- }
- return defer.promise()
- },
- _getFileExistsTemplate: function() {
- var defer = $.Deferred()
- if (!this.$fileexistsTemplate) {
- var self = this
- $.get(OC.filePath('files', 'templates', 'fileexists.html'), function(tmpl) {
- self.$fileexistsTemplate = $(tmpl)
- defer.resolve(self.$fileexistsTemplate)
- })
- .fail(function() {
- defer.reject()
- })
- } else {
- defer.resolve(this.$fileexistsTemplate)
- }
- return defer.promise()
- },
- _getFileList: function(dir, mimeType) { // this is only used by the spreedme app atm
- if (typeof (mimeType) === 'string') {
- mimeType = [mimeType]
- }
-
- return $.getJSON(
- OC.filePath('files', 'ajax', 'list.php'),
- {
- dir: dir,
- mimetypes: JSON.stringify(mimeType)
- }
- )
- },
-
- /**
- * fills the filepicker with files
- */
- _fillFilePicker: function(dir) {
- var self = this
- this.$filelist.empty()
- this.$filePicker.find('.emptycontent').hide()
- this.$filelistContainer.addClass('icon-loading')
- this.$filePicker.data('path', dir)
- var filter = this.$filePicker.data('mimetype')
- if (typeof (filter) === 'string') {
- filter = [filter]
- }
- self.$fileListHeader.find('.sort-indicator').addClass('hidden').removeClass('icon-triangle-n').removeClass('icon-triangle-s')
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').removeClass('hidden')
- if (self.filepicker.sortOrder === 'asc') {
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-n')
- } else {
- self.$fileListHeader.find('[data-sort=' + self.filepicker.sortField + '] .sort-indicator').addClass('icon-triangle-s')
- }
- self.filepicker.filesClient.getFolderContents(dir).then(function(status, files) {
- self.filelist = files
- if (filter && filter.length > 0 && filter.indexOf('*') === -1) {
- files = files.filter(function(file) {
- return file.type === 'dir' || filter.indexOf(file.mimetype) !== -1
- })
- }
-
- var Comparators = {
- name: function(fileInfo1, fileInfo2) {
- if (fileInfo1.type === 'dir' && fileInfo2.type !== 'dir') {
- return -1
- }
- if (fileInfo1.type !== 'dir' && fileInfo2.type === 'dir') {
- return 1
- }
- return OC.Util.naturalSortCompare(fileInfo1.name, fileInfo2.name)
- },
- size: function(fileInfo1, fileInfo2) {
- return fileInfo1.size - fileInfo2.size
- },
- mtime: function(fileInfo1, fileInfo2) {
- return fileInfo1.mtime - fileInfo2.mtime
- }
- }
- var comparator = Comparators[self.filepicker.sortField] || Comparators.name
- files = files.sort(function(file1, file2) {
- var isFavorite = function(fileInfo) {
- return fileInfo.tags && fileInfo.tags.indexOf(OC.TAG_FAVORITE) >= 0
- }
-
- if (isFavorite(file1) && !isFavorite(file2)) {
- return -1
- } else if (!isFavorite(file1) && isFavorite(file2)) {
- return 1
- }
-
- return self.filepicker.sortOrder === 'asc' ? comparator(file1, file2) : -comparator(file1, file2)
- })
-
- self._fillSlug()
-
- if (files.length === 0) {
- self.$filePicker.find('.emptycontent').show()
- self.$fileListHeader.hide()
- } else {
- self.$filePicker.find('.emptycontent').hide()
- self.$fileListHeader.show()
- }
-
- $.each(files, function(idx, entry) {
- entry.icon = OC.MimeType.getIconUrl(entry.mimetype)
- var simpleSize, sizeColor
- if (typeof (entry.size) !== 'undefined' && entry.size >= 0) {
- simpleSize = humanFileSize(parseInt(entry.size, 10), true)
- sizeColor = Math.round(160 - Math.pow((entry.size / (1024 * 1024)), 2))
- } else {
- simpleSize = t('files', 'Pending')
- sizeColor = 80
- }
-
- // split the filename in half if the size is bigger than 20 char
- // for ellipsis
- if (entry.name.length >= 10) {
- // leave maximum 10 letters
- var split = Math.min(Math.floor(entry.name.length / 2), 10)
- var filename1 = entry.name.substr(0, entry.name.length - split)
- var filename2 = entry.name.substr(entry.name.length - split)
- } else {
- var filename1 = entry.name
- var filename2 = ''
- }
-
- var $row = self.$listTmpl.octemplate({
- type: entry.type,
- dir: dir,
- filename: entry.name,
- filename1: filename1,
- filename2: filename2,
- date: OC.Util.relativeModifiedDate(entry.mtime),
- size: simpleSize,
- sizeColor: sizeColor,
- icon: entry.icon
- })
- if (entry.type === 'file') {
- var urlSpec = {
- file: dir + '/' + entry.name,
- x: 100,
- y: 100
- }
- var img = new Image()
- var previewUrl = OC.generateUrl('/core/preview.png?') + $.param(urlSpec)
- img.onload = function() {
- if (img.width > 5) {
- $row.find('td.filename').attr('style', 'background-image:url(' + previewUrl + ')')
- }
- }
- img.src = previewUrl
- }
- self.$filelist.append($row)
- })
-
- self.$filelistContainer.removeClass('icon-loading')
- })
- },
- /**
- * fills the tree list with directories
- */
- _fillSlug: function() {
- this.$dirTree.empty()
- var self = this
- var dir
- var path = this.$filePicker.data('path')
- var $template = $('<div data-dir="{dir}"><a>{name}</a></div>').addClass('crumb')
- if (path) {
- var paths = path.split('/')
- $.each(paths, function(index, dir) {
- dir = paths.pop()
- if (dir === '') {
- return false
- }
- self.$dirTree.prepend($template.octemplate({
- dir: paths.join('/') + '/' + dir,
- name: dir
- }))
- })
- }
- $template.octemplate({
- dir: '',
- name: '' // Ugly but works ;)
- }, { escapeFunction: null }).prependTo(this.$dirTree)
- },
- /**
- * handle selection made in the tree list
- */
- _handleTreeListSelect: function(event, type) {
- var self = event.data
- var dir = $(event.target).closest('.crumb').data('dir')
- self._fillFilePicker(dir)
- var getOcDialog = (event.target).closest('.oc-dialog')
- var buttonEnableDisable = $('.primary', getOcDialog)
- this._changeButtonsText(type, dir.split(/[/]+/).pop())
- if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
- }
- },
- /**
- * handle clicks made in the filepicker
- */
- _handlePickerClick: function(event, $element, type) {
- var getOcDialog = this.$filePicker.closest('.oc-dialog')
- var buttonEnableDisable = getOcDialog.find('.primary')
- if ($element.data('type') === 'file') {
- if (this.$filePicker.data('multiselect') !== true || !event.ctrlKey) {
- this.$filelist.find('.filepicker_element_selected').removeClass('filepicker_element_selected')
- }
- $element.toggleClass('filepicker_element_selected')
- buttonEnableDisable.prop('disabled', false)
- } else if ($element.data('type') === 'dir') {
- this._fillFilePicker(this.$filePicker.data('path') + '/' + $element.data('entryname'))
- this._changeButtonsText(type, $element.data('entryname'))
- if (this.$filePicker.data('mimetype').indexOf('httpd/unix-directory') !== -1 || this.$filePicker.data('allowDirectoryChooser')) {
- buttonEnableDisable.prop('disabled', false)
- } else {
- buttonEnableDisable.prop('disabled', true)
- }
- }
- },
-
- /**
- * Handle
- * @param type of action
- * @param dir on which to change buttons text
- * @private
- */
- _changeButtonsText: function(type, dir) {
- var copyText = dir === '' ? t('core', 'Copy') : t('core', 'Copy to {folder}', { folder: dir })
- var moveText = dir === '' ? t('core', 'Move') : t('core', 'Move to {folder}', { folder: dir })
- var buttons = $('.oc-dialog-buttonrow button')
- switch (type) {
- case this.FILEPICKER_TYPE_CHOOSE:
- break
- case this.FILEPICKER_TYPE_COPY:
- buttons.text(copyText)
- break
- case this.FILEPICKER_TYPE_MOVE:
- buttons.text(moveText)
- break
- case this.FILEPICKER_TYPE_COPY_MOVE:
- buttons.eq(0).text(copyText)
- buttons.eq(1).text(moveText)
- break
- }
- }
- }
-
- export default Dialogs
|