define([ 'jquery', '/common/toolbar.js', '/common/drive-ui.js', '/common/common-util.js', '/common/common-hash.js', '/common/common-interface.js', '/common/common-ui-elements.js', '/common/common-feedback.js', '/bower_components/nthen/index.js', '/common/sframe-common.js', '/common/proxy-manager.js', '/customize/application_config.js', '/customize/messages.js', 'css!/bower_components/bootstrap/dist/css/bootstrap.min.css', 'css!/bower_components/components-font-awesome/css/font-awesome.min.css', 'less!/drive/app-drive.less', ], function ( $, Toolbar, DriveUI, Util, Hash, UI, UIElements, Feedback, nThen, SFCommon, ProxyManager, AppConfig, Messages) { var APP = {}; var SHARED_FOLDER_NAME = Messages.fm_sharedFolderName; var copyObjectValue = function (objRef, objToCopy) { for (var k in objRef) { delete objRef[k]; } $.extend(true, objRef, objToCopy); }; var updateSharedFolders = function (sframeChan, manager, drive, folders, cb) { if (!drive || !drive.sharedFolders) { return void cb(); } var r = drive.restrictedFolders = {}; var oldIds = Object.keys(folders); nThen(function (waitFor) { Object.keys(drive.sharedFolders).forEach(function (fId) { var sfData = drive.sharedFolders[fId] || {}; var href = (sfData.href && sfData.href.indexOf('#') !== -1) ? sfData.href : sfData.roHref; var parsed = Hash.parsePadUrl(href); var secret = Hash.getSecrets('drive', parsed.hash, sfData.password); sframeChan.query('Q_DRIVE_GETOBJECT', { sharedFolder: fId }, waitFor(function (err, newObj) { if (!APP.loggedIn && APP.newSharedFolder) { if (!newObj || !Object.keys(newObj).length) { // Empty anon drive: deleted var msg = Messages.deletedError + '<br>' + Messages.errorRedirectToHome; setTimeout(function () { UI.errorLoadingScreen(msg, false, function () {}); }); APP.newSharedFolder = null; } } if (newObj && newObj.restricted) { r[fId] = drive.sharedFolders[fId]; if (!r[fId].title) { r[fId].title = r[fId].lastTitle; } } if (newObj && (newObj.deprecated /*|| newObj.restricted*/)) { delete folders[fId]; delete drive.sharedFolders[fId]; if (manager && manager.folders) { delete manager.folders[fId]; } return; } folders[fId] = folders[fId] || {}; copyObjectValue(folders[fId], newObj); folders[fId].readOnly = !secret.keys.secondaryKey; if (manager && oldIds.indexOf(fId) === -1) { manager.addProxy(fId, { proxy: folders[fId] }, null, secret.keys.secondaryKey); } var readOnly = !secret.keys.editKeyStr; if (!manager || !manager.folders[fId]) { return; } manager.folders[fId].userObject.setReadOnly(readOnly, secret.keys.secondaryKey); manager.folders[fId].offline = newObj.offline; })); }); // Remove from memory folders that have been deleted from the drive remotely oldIds.forEach(function (fId) { if (!drive.sharedFolders[fId]) { delete folders[fId]; delete drive.sharedFolders[fId]; if (manager && manager.folders) { delete manager.folders[fId]; } } }); }).nThen(function () { cb(); }); }; var updateObject = function (sframeChan, obj, cb) { sframeChan.query('Q_DRIVE_GETOBJECT', null, function (err, newObj) { copyObjectValue(obj, newObj); // If anon shared folder, make a virtual drive containing this folder if (!APP.loggedIn && APP.newSharedFolder) { obj.drive.root = { sf: APP.newSharedFolder }; obj.drive.sharedFolders = obj.drive.sharedFolders || {}; obj.drive.sharedFolders[APP.newSharedFolder] = { href: APP.anonSFHref, password: APP.anonSFPassword }; } cb(); }); }; var history = { isHistoryMode: false, }; var setEditable = DriveUI.setEditable; var setHistory = function (bool, update) { history.isHistoryMode = bool; setEditable(!bool, true); if (!bool && update) { history.onLeaveHistory(); } return true; }; var main = function () { var common; var proxy = {}; var folders = {}; var readOnly; var startOnline = false; var onReco; nThen(function (waitFor) { $(waitFor(function () { UI.addLoadingScreen(); })); window.cryptpadStore.getAll(waitFor(function (val) { APP.store = JSON.parse(JSON.stringify(val)); })); SFCommon.create(waitFor(function (c) { common = c; })); }).nThen(function (waitFor) { onReco = common.getSframeChannel().on('EV_NETWORK_RECONNECT', function () { startOnline = true; }); $('#cp-app-drive-connection-state').text(Messages.disconnected); var privReady = Util.once(waitFor()); var metadataMgr = common.getMetadataMgr(); if (JSON.stringify(metadataMgr.getPrivateData()) !== '{}') { privReady(); return; } metadataMgr.onChange(function () { if (typeof(metadataMgr.getPrivateData().readOnly) === 'boolean') { readOnly = APP.readOnly = metadataMgr.getPrivateData().readOnly; privReady(); } }); }).nThen(function (waitFor) { APP.loggedIn = common.isLoggedIn(); if (!APP.loggedIn) { Feedback.send('ANONYMOUS_DRIVE'); } APP.$body = $('body'); APP.$bar = $('#cp-toolbar'); common.setTabTitle(Messages.type.drive); var metadataMgr = common.getMetadataMgr(); var privateData = metadataMgr.getPrivateData(); if (privateData.newSharedFolder) { APP.newSharedFolder = privateData.newSharedFolder; APP.anonSFHref = privateData.anonSFHref; APP.anonSFPassword = privateData.password; } var sframeChan = common.getSframeChannel(); updateObject(sframeChan, proxy, waitFor(function () { updateSharedFolders(sframeChan, null, proxy.drive, folders, waitFor()); })); }).nThen(function () { var sframeChan = common.getSframeChannel(); var metadataMgr = common.getMetadataMgr(); var privateData = metadataMgr.getPrivateData(); var user = metadataMgr.getUserData(); APP.disableSF = !privateData.enableSF && AppConfig.disableSharedFolders; if (APP.newSharedFolder && !APP.loggedIn) { readOnly = APP.readOnly = true; var data = folders[APP.newSharedFolder]; if (data) { sframeChan.query('Q_SET_PAD_TITLE_IN_DRIVE', { title: data.metadata && data.metadata.title, }, function () {}); } } // ANON_SHARED_FOLDER var pageTitle = (!APP.loggedIn && APP.newSharedFolder) ? SHARED_FOLDER_NAME : Messages.type.drive; var configTb = { displayed: ['useradmin', 'pageTitle', 'newpad', 'limit', 'notifications'], pageTitle: pageTitle, metadataMgr: metadataMgr, readOnly: privateData.readOnly, sfCommon: common, $container: APP.$bar }; var toolbar = Toolbar.create(configTb); var helpMenu = common.createHelpMenu(['drive']); APP.help = helpMenu.menu; $('#cp-app-drive-content-container').prepend(helpMenu.menu); var $displayName = APP.$bar.find('.' + Toolbar.constants.username); metadataMgr.onChange(function () { var name = metadataMgr.getUserData().name || Messages.anonymous; $displayName.text(name); }); $displayName.text(user.name || Messages.anonymous); /* add the usage */ var usageBar; if (APP.loggedIn) { usageBar = common.createUsageBar(null, function (err) { if (err) { return void DriveUI.logError(err); } }, true); } /* add a history button */ APP.histConfig = { onLocal: function () { UI.addLoadingScreen({ loadingText: Messages.fm_restoreDrive }); var data = {}; if (history.sfId) { copyObjectValue(folders[history.sfId], history.currentObj); data.sfId = history.sfId; data.drive = history.currentObj; } else { proxy.drive = history.currentObj.drive; data.drive = history.currentObj.drive; } sframeChan.query("Q_DRIVE_RESTORE", data, function () { UI.removeLoadingScreen(); }, { timeout: 5 * 60 * 1000 }); }, onOpen: function () {}, onRemote: function () {}, setHistory: setHistory, applyVal: function (val) { var obj = JSON.parse(val || '{}'); history.currentObj = obj; history.onEnterHistory(obj); }, drive: true, $toolbar: APP.$bar, }; // Add a "Burn this drive" button if (!APP.loggedIn && !APP.readOnly) { APP.$burnThisDrive = common.createButton(null, true, { text: '', name: 'burn-anon-drive', icon: 'fa-ban', tippy: Messages.fm_burnThisDriveButton, drawer: false }, function () { var confirmContent = UIElements.fixInlineBRs(Messages.fm_burnThisDrive); UI.confirm(confirmContent, function (yes) { if (!yes) { return; } common.getSframeChannel().event('EV_BURN_ANON_DRIVE'); }); }); } $('body').css('display', ''); if (!proxy.drive || typeof(proxy.drive) !== 'object') { throw new Error("Corrupted drive"); } APP.online = startOnline || !privateData.offline; var drive = DriveUI.create(common, { $limit: usageBar && usageBar.$container, proxy: proxy, folders: folders, updateObject: updateObject, updateSharedFolders: updateSharedFolders, history: history, toolbar: toolbar, APP: APP }); var onDisconnect = function (noAlert) { setEditable(false); if (drive.refresh) { drive.refresh(); } toolbar.failed(); if (!noAlert) { UIElements.disconnectAlert(); } }; var onReconnect = function () { setEditable(true); if (drive.refresh) { drive.refresh(); } toolbar.reconnecting(); UIElements.reconnectAlert(); }; sframeChan.on('EV_DRIVE_LOG', function (msg) { UI.log(msg); }); sframeChan.on('EV_NETWORK_DISCONNECT', function () { onDisconnect(); }); onReco.stop(); sframeChan.on('EV_NETWORK_RECONNECT', function () { onReconnect(); }); common.onLogout(function () { setEditable(false); }); // Check if our drive history needs to be trimmed common.checkTrimHistory(null, true); }); }; main(); });