2014-01-30 09:41:04 +00:00
/ *
* Copyright ( c ) 2014
*
* This file is licensed under the Affero General Public License version 3
* or later .
*
* See the COPYING - README file .
*
* /
2014-04-28 14:51:57 +00:00
/* global getURLParameter */
2014-05-08 20:06:30 +00:00
/ * *
* Utility class for file related operations
* /
( function ( ) {
var Files = {
// file space size sync
2014-05-12 17:54:20 +00:00
_updateStorageStatistics : function ( currentDir ) {
var state = Files . updateStorageStatistics ;
2014-05-08 20:06:30 +00:00
if ( state . dir ) {
if ( state . dir === currentDir ) {
return ;
}
// cancel previous call, as it was for another dir
state . call . abort ( ) ;
}
state . dir = currentDir ;
state . call = $ . getJSON ( OC . filePath ( 'files' , 'ajax' , 'getstoragestats.php' ) + '?dir=' + encodeURIComponent ( currentDir ) , function ( response ) {
state . dir = null ;
state . call = null ;
Files . updateMaxUploadFilesize ( response ) ;
} ) ;
} ,
2014-05-12 17:54:20 +00:00
/ * *
* Update storage statistics such as free space , max upload ,
* etc based on the given directory .
*
* Note this function is debounced to avoid making too
* many ajax calls in a row .
*
* @ param dir directory
* @ param force whether to force retrieving
* /
updateStorageStatistics : function ( dir , force ) {
2014-05-08 20:06:30 +00:00
if ( ! OC . currentUser ) {
2013-11-06 09:55:19 +00:00
return ;
}
2013-11-06 09:15:05 +00:00
2014-05-08 20:06:30 +00:00
if ( force ) {
2014-05-12 17:54:20 +00:00
Files . _updateStorageStatistics ( dir ) ;
2014-05-08 20:06:30 +00:00
}
else {
2014-05-12 17:54:20 +00:00
Files . _updateStorageStatisticsDebounced ( dir ) ;
2014-05-08 20:06:30 +00:00
}
} ,
2013-11-06 09:15:05 +00:00
2014-05-08 20:06:30 +00:00
updateMaxUploadFilesize : function ( response ) {
if ( response === undefined ) {
return ;
}
if ( response . data !== undefined && response . data . uploadMaxFilesize !== undefined ) {
$ ( '#max_upload' ) . val ( response . data . uploadMaxFilesize ) ;
$ ( '#free_space' ) . val ( response . data . freeSpace ) ;
$ ( '#upload.button' ) . attr ( 'original-title' , response . data . maxHumanFilesize ) ;
$ ( '#usedSpacePercent' ) . val ( response . data . usedSpacePercent ) ;
Files . displayStorageWarnings ( ) ;
}
if ( response [ 0 ] === undefined ) {
return ;
}
if ( response [ 0 ] . uploadMaxFilesize !== undefined ) {
$ ( '#max_upload' ) . val ( response [ 0 ] . uploadMaxFilesize ) ;
$ ( '#upload.button' ) . attr ( 'original-title' , response [ 0 ] . maxHumanFilesize ) ;
$ ( '#usedSpacePercent' ) . val ( response [ 0 ] . usedSpacePercent ) ;
Files . displayStorageWarnings ( ) ;
}
2013-01-18 19:09:03 +00:00
2014-05-08 20:06:30 +00:00
} ,
2013-10-28 10:22:34 +00:00
2014-05-08 20:06:30 +00:00
/ * *
* Fix path name by removing double slash at the beginning , if any
* /
fixPath : function ( fileName ) {
if ( fileName . substr ( 0 , 2 ) == '//' ) {
return fileName . substr ( 1 ) ;
}
return fileName ;
} ,
/ * *
* Checks whether the given file name is valid .
* @ param name file name to check
* @ return true if the file name is valid .
* Throws a string exception with an error message if
* the file name is not valid
* /
isFileNameValid : function ( name ) {
var trimmedName = name . trim ( ) ;
if ( trimmedName === '.' || trimmedName === '..' )
{
throw t ( 'files' , '"{name}" is an invalid file name.' , { name : name } ) ;
} else if ( trimmedName . length === 0 ) {
throw t ( 'files' , 'File name cannot be empty.' ) ;
}
// check for invalid characters
var invalidCharacters =
[ '\\' , '/' , '<' , '>' , ':' , '"' , '|' , '?' , '*' , '\n' ] ;
for ( var i = 0 ; i < invalidCharacters . length ; i ++ ) {
if ( trimmedName . indexOf ( invalidCharacters [ i ] ) !== - 1 ) {
throw t ( 'files' , "Invalid name, '\\', '/', '<', '>', ':', '\"', '|', '?' and '*' are not allowed." ) ;
}
}
return true ;
} ,
displayStorageWarnings : function ( ) {
if ( ! OC . Notification . isHidden ( ) ) {
return ;
}
2013-10-28 10:22:34 +00:00
2014-05-08 20:06:30 +00:00
var usedSpacePercent = $ ( '#usedSpacePercent' ) . val ( ) ;
if ( usedSpacePercent > 98 ) {
OC . Notification . show ( t ( 'files' , 'Your storage is full, files can not be updated or synced anymore!' ) ) ;
return ;
2012-11-22 12:03:17 +00:00
}
2014-05-08 20:06:30 +00:00
if ( usedSpacePercent > 90 ) {
OC . Notification . show ( t ( 'files' , 'Your storage is almost full ({usedSpacePercent}%)' ,
{ usedSpacePercent : usedSpacePercent } ) ) ;
}
} ,
2013-01-18 23:31:49 +00:00
2014-05-08 20:06:30 +00:00
displayEncryptionWarning : function ( ) {
2013-08-12 15:25:27 +00:00
2014-05-08 20:06:30 +00:00
if ( ! OC . Notification . isHidden ( ) ) {
return ;
}
2013-08-12 15:25:27 +00:00
2014-05-08 20:06:30 +00:00
var encryptedFiles = $ ( '#encryptedFiles' ) . val ( ) ;
var initStatus = $ ( '#encryptionInitStatus' ) . val ( ) ;
if ( initStatus === '0' ) { // enc not initialized, but should be
OC . Notification . show ( t ( 'files' , 'Encryption App is enabled but your keys are not initialized, please log-out and log-in again' ) ) ;
return ;
}
if ( initStatus === '1' ) { // encryption tried to init but failed
OC . Notification . show ( t ( 'files' , 'Invalid private key for Encryption App. Please update your private key password in your personal settings to recover access to your encrypted files.' ) ) ;
return ;
}
if ( encryptedFiles === '1' ) {
OC . Notification . show ( t ( 'files' , 'Encryption was disabled but your files are still encrypted. Please go to your personal settings to decrypt your files.' ) ) ;
return ;
}
} ,
2013-08-12 15:25:27 +00:00
2014-05-08 20:06:30 +00:00
/ * *
* Returns the download URL of the given file ( s )
* @ param filename string or array of file names to download
* @ param dir optional directory in which the file name is , defaults to the current directory
* /
getDownloadUrl : function ( filename , dir ) {
if ( $ . isArray ( filename ) ) {
filename = JSON . stringify ( filename ) ;
2013-08-17 11:07:18 +00:00
}
2014-05-08 20:06:30 +00:00
var params = {
dir : dir ,
files : filename
} ;
return this . getAjaxUrl ( 'download' , params ) ;
} ,
/ * *
* Returns the ajax URL for a given action
* @ param action action string
* @ param params optional params map
* /
getAjaxUrl : function ( action , params ) {
var q = '' ;
if ( params ) {
q = '?' + OC . buildQueryString ( params ) ;
2013-08-17 11:07:18 +00:00
}
2014-05-08 20:06:30 +00:00
return OC . filePath ( 'files' , 'ajax' , action + '.php' ) + q ;
} ,
getMimeIcon : function ( mime , ready ) {
if ( Files . getMimeIcon . cache [ mime ] ) {
ready ( Files . getMimeIcon . cache [ mime ] ) ;
} else {
$ . get ( OC . filePath ( 'files' , 'ajax' , 'mimeicon.php' ) , { mime : mime } , function ( path ) {
if ( OC . Util . hasSVGSupport ( ) ) {
path = path . substr ( 0 , path . length - 4 ) + '.svg' ;
}
Files . getMimeIcon . cache [ mime ] = path ;
ready ( Files . getMimeIcon . cache [ mime ] ) ;
} ) ;
}
} ,
/ * *
* Generates a preview URL based on the URL space .
2014-06-23 21:56:10 +00:00
* @ param urlSpec attributes for the URL
* @ param { int } urlSpec . x width
* @ param { int } urlSpec . y height
* @ param { String } urlSpec . file path to the file
2014-05-08 20:06:30 +00:00
* @ return preview URL
* @ deprecated used OCA . Files . FileList . generatePreviewUrl instead
* /
generatePreviewUrl : function ( urlSpec ) {
console . warn ( 'DEPRECATED: please use generatePreviewUrl() from an OCA.Files.FileList instance' ) ;
return OCA . Files . App . fileList . generatePreviewUrl ( urlSpec ) ;
} ,
/ * *
* Lazy load preview
* @ deprecated used OCA . Files . FileList . lazyLoadPreview instead
* /
lazyLoadPreview : function ( path , mime , ready , width , height , etag ) {
console . warn ( 'DEPRECATED: please use lazyLoadPreview() from an OCA.Files.FileList instance' ) ;
return OCA . Files . App . fileList . lazyLoadPreview ( {
path : path ,
mime : mime ,
callback : ready ,
width : width ,
height : height ,
etag : etag
} ) ;
} ,
2013-08-27 11:13:00 +00:00
2014-05-08 20:06:30 +00:00
/ * *
* Initialize the files view
* /
initialize : function ( ) {
Files . getMimeIcon . cache = { } ;
Files . displayEncryptionWarning ( ) ;
2014-05-12 17:54:20 +00:00
Files . bindKeyboardShortcuts ( document , $ ) ;
2013-08-17 11:07:18 +00:00
2014-05-08 20:06:30 +00:00
// TODO: move file list related code (upload) to OCA.Files.FileList
$ ( '#file_action_panel' ) . attr ( 'activeAction' , false ) ;
2012-03-16 15:25:41 +00:00
2014-05-08 20:06:30 +00:00
// Triggers invisible file input
$ ( '#upload a' ) . on ( 'click' , function ( ) {
$ ( this ) . parent ( ) . children ( '#file_upload_start' ) . trigger ( 'click' ) ;
return false ;
} ) ;
2013-02-22 16:21:57 +00:00
2014-05-08 20:06:30 +00:00
// Trigger cancelling of file upload
$ ( '#uploadprogresswrapper .stop' ) . on ( 'click' , function ( ) {
OC . Upload . cancelUploads ( ) ;
} ) ;
2013-04-28 21:25:58 +00:00
2014-05-08 20:06:30 +00:00
// drag&drop support using jquery.fileupload
// TODO use OC.dialogs
$ ( document ) . bind ( 'drop dragover' , function ( e ) {
e . preventDefault ( ) ; // prevent browser from doing anything, if file isn't dropped in dropZone
} ) ;
//do a background scan if needed
scanFiles ( ) ;
// display storage warnings
setTimeout ( Files . displayStorageWarnings , 100 ) ;
OC . Notification . setDefault ( Files . displayStorageWarnings ) ;
2014-05-12 17:54:20 +00:00
// only possible at the moment if user is logged in or the files app is loaded
if ( OC . currentUser && OCA . Files . App ) {
2014-05-08 20:06:30 +00:00
// start on load - we ask the server every 5 minutes
2014-05-23 14:13:35 +00:00
var func = _ . bind ( OCA . Files . App . fileList . updateStorageStatistics , OCA . Files . App . fileList ) ;
2014-05-08 20:06:30 +00:00
var updateStorageStatisticsInterval = 5 * 60 * 1000 ;
2014-05-23 14:13:35 +00:00
var updateStorageStatisticsIntervalId = setInterval ( func , updateStorageStatisticsInterval ) ;
2014-05-08 20:06:30 +00:00
2014-05-12 17:54:20 +00:00
// TODO: this should also stop when switching to another view
2014-05-08 20:06:30 +00:00
// Use jquery-visibility to de-/re-activate file stats sync
if ( $ . support . pageVisibility ) {
$ ( document ) . on ( {
'show.visibility' : function ( ) {
if ( ! updateStorageStatisticsIntervalId ) {
2014-05-23 14:13:35 +00:00
updateStorageStatisticsIntervalId = setInterval ( func , updateStorageStatisticsInterval ) ;
2014-05-08 20:06:30 +00:00
}
} ,
'hide.visibility' : function ( ) {
clearInterval ( updateStorageStatisticsIntervalId ) ;
updateStorageStatisticsIntervalId = 0 ;
}
} ) ;
}
}
2011-08-11 20:22:32 +00:00
2014-06-04 17:11:04 +00:00
2014-05-29 13:28:14 +00:00
$ ( '#webdavurl' ) . on ( 'click' , function ( ) {
$ ( '#webdavurl' ) . select ( ) ;
} ) ;
2013-09-20 12:59:17 +00:00
2013-09-19 14:14:37 +00:00
//FIXME scroll to and highlight preselected file
2014-05-08 20:06:30 +00:00
/ *
if ( getURLParameter ( 'scrollto' ) ) {
FileList . scrollTo ( getURLParameter ( 'scrollto' ) ) ;
}
* /
2013-12-09 12:32:28 +00:00
}
2013-07-31 20:24:52 +00:00
}
2014-05-08 20:06:30 +00:00
2014-05-12 17:54:20 +00:00
Files . _updateStorageStatisticsDebounced = _ . debounce ( Files . _updateStorageStatistics , 250 ) ;
2014-05-08 20:06:30 +00:00
OCA . Files . Files = Files ;
} ) ( ) ;
2011-04-16 20:56:40 +00:00
2013-10-22 16:11:03 +00:00
function scanFiles ( force , dir , users ) {
2013-01-31 22:26:40 +00:00
if ( ! OC . currentUser ) {
return ;
}
2013-10-22 16:11:03 +00:00
if ( ! dir ) {
2012-11-22 23:20:46 +00:00
dir = '' ;
2012-04-25 20:42:00 +00:00
}
2012-11-22 23:20:46 +00:00
force = ! ! force ; //cast to bool
scanFiles . scanning = true ;
2013-06-18 23:26:08 +00:00
var scannerEventSource ;
if ( users ) {
var usersString ;
if ( users === 'all' ) {
usersString = users ;
} else {
2013-06-19 13:02:18 +00:00
usersString = JSON . stringify ( users ) ;
2013-06-18 23:26:08 +00:00
}
scannerEventSource = new OC . EventSource ( OC . filePath ( 'files' , 'ajax' , 'scan.php' ) , { force : force , dir : dir , users : usersString } ) ;
} else {
scannerEventSource = new OC . EventSource ( OC . filePath ( 'files' , 'ajax' , 'scan.php' ) , { force : force , dir : dir } ) ;
}
2012-11-22 23:20:46 +00:00
scanFiles . cancel = scannerEventSource . close . bind ( scannerEventSource ) ;
2013-10-22 16:11:03 +00:00
scannerEventSource . listen ( 'count' , function ( count ) {
console . log ( count + ' files scanned' ) ;
2012-11-22 23:20:46 +00:00
} ) ;
2013-10-22 16:11:03 +00:00
scannerEventSource . listen ( 'folder' , function ( path ) {
console . log ( 'now scanning ' + path ) ;
2012-01-30 22:32:55 +00:00
} ) ;
2013-10-22 16:11:03 +00:00
scannerEventSource . listen ( 'done' , function ( count ) {
2012-02-01 14:33:12 +00:00
scanFiles . scanning = false ;
2013-05-24 12:31:06 +00:00
console . log ( 'done after ' + count + ' files' ) ;
2014-05-12 17:54:20 +00:00
if ( OCA . Files . App ) {
OCA . Files . App . fileList . updateStorageStatistics ( true ) ;
}
2012-01-30 22:32:55 +00:00
} ) ;
2013-10-22 16:11:03 +00:00
scannerEventSource . listen ( 'user' , function ( user ) {
2013-06-18 23:26:08 +00:00
console . log ( 'scanning files for ' + user ) ;
} ) ;
2011-11-10 15:40:09 +00:00
}
2012-02-01 14:33:12 +00:00
scanFiles . scanning = false ;
2011-11-10 15:40:09 +00:00
2014-04-11 10:46:12 +00:00
// TODO: move to FileList
2013-10-22 16:11:03 +00:00
var createDragShadow = function ( event ) {
2013-01-18 20:49:38 +00:00
//select dragged file
2014-05-12 17:54:20 +00:00
var FileList = OCA . Files . App . fileList ;
2013-01-21 13:58:55 +00:00
var isDragSelected = $ ( event . target ) . parents ( 'tr' ) . find ( 'td input:first' ) . prop ( 'checked' ) ;
if ( ! isDragSelected ) {
//select dragged file
2014-04-04 16:46:08 +00:00
FileList . _selectFileEl ( $ ( event . target ) . parents ( 'tr:first' ) , true ) ;
2013-01-21 13:58:55 +00:00
}
2013-02-22 16:21:57 +00:00
2014-04-04 16:46:08 +00:00
// do not show drag shadow for too many files
2014-10-15 12:55:24 +00:00
var selectedFiles = _ . first ( FileList . getSelectedFiles ( ) , FileList . pageSize ( ) ) ;
2014-05-16 09:25:36 +00:00
selectedFiles = _ . sortBy ( selectedFiles , FileList . _fileInfoCompare ) ;
2013-02-22 16:21:57 +00:00
2013-10-22 16:11:03 +00:00
if ( ! isDragSelected && selectedFiles . length === 1 ) {
2013-01-21 13:58:55 +00:00
//revert the selection
2014-04-04 16:46:08 +00:00
FileList . _selectFileEl ( $ ( event . target ) . parents ( 'tr:first' ) , false ) ;
2013-01-18 20:49:38 +00:00
}
2013-02-22 16:21:57 +00:00
2013-01-18 20:49:38 +00:00
// build dragshadow
var dragshadow = $ ( '<table class="dragshadow"></table>' ) ;
var tbody = $ ( '<tbody></tbody>' ) ;
dragshadow . append ( tbody ) ;
2013-02-22 16:21:57 +00:00
2014-05-08 20:06:30 +00:00
var dir = FileList . getCurrentDirectory ( ) ;
2013-02-22 16:21:57 +00:00
2013-10-22 16:11:03 +00:00
$ ( selectedFiles ) . each ( function ( i , elem ) {
2014-04-11 10:46:12 +00:00
var newtr = $ ( '<tr/>' )
. attr ( 'data-dir' , dir )
. attr ( 'data-file' , elem . name )
. attr ( 'data-origin' , elem . origin ) ;
2013-04-22 19:54:25 +00:00
newtr . append ( $ ( '<td/>' ) . addClass ( 'filename' ) . text ( elem . name ) ) ;
2014-04-11 10:46:12 +00:00
newtr . append ( $ ( '<td/>' ) . addClass ( 'size' ) . text ( OC . Util . humanFileSize ( elem . size ) ) ) ;
2013-01-18 20:49:38 +00:00
tbody . append ( newtr ) ;
if ( elem . type === 'dir' ) {
newtr . find ( 'td.filename' ) . attr ( 'style' , 'background-image:url(' + OC . imagePath ( 'core' , 'filetypes/folder.png' ) + ')' ) ;
} else {
2014-05-08 20:06:30 +00:00
var path = dir + '/' + elem . name ;
2014-05-12 17:54:20 +00:00
OCA . Files . App . files . lazyLoadPreview ( path , elem . mime , function ( previewpath ) {
2013-07-02 09:13:22 +00:00
newtr . find ( 'td.filename' ) . attr ( 'style' , 'background-image:url(' + previewpath + ')' ) ;
2013-10-28 10:22:34 +00:00
} , null , null , elem . etag ) ;
2013-01-18 20:49:38 +00:00
}
} ) ;
2013-02-22 16:21:57 +00:00
2013-01-18 20:49:38 +00:00
return dragshadow ;
2013-10-22 16:11:03 +00:00
} ;
2013-01-18 20:49:38 +00:00
//options for file drag/drop
2013-12-04 17:27:24 +00:00
//start&stop handlers needs some cleaning up
2014-04-11 10:46:12 +00:00
// TODO: move to FileList class
2011-07-07 19:43:35 +00:00
var dragOptions = {
2014-05-08 20:06:30 +00:00
revert : 'invalid' ,
revertDuration : 300 ,
opacity : 0.7 ,
zIndex : 100 ,
appendTo : 'body' ,
cursorAt : { left : 24 , top : 18 } ,
helper : createDragShadow ,
cursor : 'move' ,
2014-04-28 14:51:57 +00:00
start : function ( event , ui ) {
var $selectedFiles = $ ( 'td.filename input:checkbox:checked' ) ;
if ( $selectedFiles . length > 1 ) {
$selectedFiles . parents ( 'tr' ) . fadeTo ( 250 , 0.2 ) ;
}
else {
$ ( this ) . fadeTo ( 250 , 0.2 ) ;
}
} ,
stop : function ( event , ui ) {
var $selectedFiles = $ ( 'td.filename input:checkbox:checked' ) ;
if ( $selectedFiles . length > 1 ) {
$selectedFiles . parents ( 'tr' ) . fadeTo ( 250 , 1 ) ;
2013-12-04 17:27:24 +00:00
}
2014-04-28 14:51:57 +00:00
else {
$ ( this ) . fadeTo ( 250 , 1 ) ;
}
$ ( '#fileList tr td.filename' ) . addClass ( 'ui-draggable' ) ;
}
2013-10-22 16:11:03 +00:00
} ;
2013-02-25 14:08:14 +00:00
// sane browsers support using the distance option
2013-03-28 18:13:37 +00:00
if ( $ ( 'html.ie' ) . length === 0 ) {
2013-02-25 14:08:14 +00:00
dragOptions [ 'distance' ] = 20 ;
2013-06-25 10:24:14 +00:00
}
2013-01-18 20:49:38 +00:00
2014-04-11 10:46:12 +00:00
// TODO: move to FileList class
var folderDropOptions = {
2013-12-04 17:27:24 +00:00
hoverClass : "canDrop" ,
2011-07-07 19:43:35 +00:00
drop : function ( event , ui ) {
2014-04-11 10:46:12 +00:00
// don't allow moving a file into a selected folder
2014-05-12 17:54:20 +00:00
var FileList = OCA . Files . App . fileList ;
2013-01-18 20:49:38 +00:00
if ( $ ( event . target ) . parents ( 'tr' ) . find ( 'td input:first' ) . prop ( 'checked' ) === true ) {
return false ;
}
2013-02-22 16:21:57 +00:00
2014-09-04 17:58:49 +00:00
var $tr = $ ( this ) . closest ( 'tr' ) ;
if ( ( $tr . data ( 'permissions' ) & OC . PERMISSION _CREATE ) === 0 ) {
FileList . _showPermissionDeniedNotification ( ) ;
return false ;
}
var targetPath = FileList . getCurrentDirectory ( ) + '/' + $tr . data ( 'file' ) ;
2014-04-11 10:46:12 +00:00
var files = FileList . getSelectedFiles ( ) ;
if ( files . length === 0 ) {
// single one selected without checkbox?
files = _ . map ( ui . helper . find ( 'tr' ) , FileList . elementToFile ) ;
}
FileList . move ( _ . pluck ( files , 'name' ) , targetPath ) ;
2013-01-18 20:49:38 +00:00
} ,
tolerance : 'pointer'
2013-10-22 16:11:03 +00:00
} ;
2013-01-18 20:49:38 +00:00
2013-10-28 19:22:06 +00:00
// override core's fileDownloadPath (legacy)
function fileDownloadPath ( dir , file ) {
2014-05-08 20:06:30 +00:00
return OCA . Files . Files . getDownloadUrl ( file , dir ) ;
2013-08-17 11:07:18 +00:00
}
2013-12-04 17:27:24 +00:00
2014-05-08 20:06:30 +00:00
// for backward compatibility
window . Files = OCA . Files . Files ;