define([ '/common/common-feedback.js', '/common/common-hash.js', '/common/common-util.js', '/bower_components/nthen/index.js', ], function (Feedback, Hash, Util, nThen) { // Start migration check // Versions: // 1: migrate pad attributes // 2: migrate indent settings (codemirror) return function (userObject, cb, progress) { var version = userObject.version || 0; nThen(function () { // DEPRECATED // Migration 1: pad attributes moved to filesData var migratePadAttributesToData = function () { return true; }; if (version < 1) { migratePadAttributesToData(); } }).nThen(function () { // Migration 2: global attributes from root to 'settings' subobjects var migrateAttributes = function () { var drawer = 'cryptpad.userlist-drawer'; var polls = 'cryptpad.hide_poll_text'; var indentKey = 'cryptpad.indentUnit'; var useTabsKey = 'cryptpad.indentWithTabs'; var settings = userObject.settings = userObject.settings || {}; if (typeof(userObject[indentKey]) !== "undefined") { settings.codemirror = settings.codemirror || {}; settings.codemirror.indentUnit = userObject[indentKey]; delete userObject[indentKey]; } if (typeof(userObject[useTabsKey]) !== "undefined") { settings.codemirror = settings.codemirror || {}; settings.codemirror.indentWithTabs = userObject[useTabsKey]; delete userObject[useTabsKey]; } if (typeof(userObject[drawer]) !== "undefined") { settings.toolbar = settings.toolbar || {}; settings.toolbar['userlist-drawer'] = userObject[drawer]; delete userObject[drawer]; } if (typeof(userObject[polls]) !== "undefined") { settings.poll = settings.poll || {}; settings.poll['hide-text'] = userObject[polls]; delete userObject[polls]; } }; if (version < 2) { migrateAttributes(); Feedback.send('Migrate-2', true); userObject.version = version = 2; } }).nThen(function () { // Migration 3: language from localStorage to settings var migrateLanguage = function () { if (!localStorage.CRYPTPAD_LANG) { return; } var l = localStorage.CRYPTPAD_LANG; userObject.settings.language = l; }; if (version < 3) { migrateLanguage(); Feedback.send('Migrate-3', true); userObject.version = version = 3; } }).nThen(function () { // Migration 4: allowUserFeedback to settings var migrateFeedback = function () { var settings = userObject.settings = userObject.settings || {}; if (typeof(userObject['allowUserFeedback']) !== "undefined") { settings.general = settings.general || {}; settings.general.allowUserFeedback = userObject['allowUserFeedback']; delete userObject['allowUserFeedback']; } }; if (version < 4) { migrateFeedback(); Feedback.send('Migrate-4', true); userObject.version = version = 4; } }).nThen(function () { // Migration 5: dates to Number var migrateDates = function () { var data = userObject.drive && userObject.drive.filesData; if (data) { for (var id in data) { if (typeof data[id].ctime !== "number") { data[id].ctime = +new Date(data[id].ctime); } if (typeof data[id].atime !== "number") { data[id].atime = +new Date(data[id].atime); } } } }; if (version < 5) { migrateDates(); Feedback.send('Migrate-5', true); userObject.version = version = 5; } }).nThen(function (waitFor) { var addChannelId = function () { var data = userObject.drive.filesData; var el, parsed; var n = nThen(function () {}); var padsLength = Object.keys(data).length; Object.keys(data).forEach(function (k, i) { n = n.nThen(function (w) { setTimeout(w(function () { el = data[k]; parsed = Hash.parsePadUrl(el.href); if (!el.href) { return; } if (!el.channel) { var secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); el.channel = secret.channel; progress(6, Math.round(100*i/padsLength)); console.log('Adding missing channel in filesData ', el.channel); } })); }); }); n.nThen(waitFor(function () { Feedback.send('Migrate-6', true); userObject.version = version = 6; })); }; if (version < 6) { addChannelId(); } }).nThen(function (waitFor) { var addRoHref = function () { var data = userObject.drive.filesData; var el, parsed; var n = nThen(function () {}); var padsLength = Object.keys(data).length; Object.keys(data).forEach(function (k, i) { n = n.nThen(function (w) { setTimeout(w(function () { el = data[k]; if (!el.href || (el.roHref && false)) { // Already migrated return void progress(7, Math.round(100*i/padsLength)); } parsed = Hash.parsePadUrl(el.href); if (parsed.hashData.type !== "pad") { // No read-only mode for files return void progress(7, Math.round(100*i/padsLength)); } if (parsed.hashData.mode === "view") { // This is a read-only pad in our drive el.roHref = el.href; delete el.href; console.log('Move href to roHref in filesData ', el.roHref); } else { var secret = Hash.getSecrets(parsed.type, parsed.hash, el.password); var hash = Hash.getViewHashFromKeys(secret); if (hash) { // Version 0 won't have a view hash available el.roHref = '/' + parsed.type + '/#' + hash; console.log('Adding missing roHref in filesData ', el.href); } } progress(6, Math.round(100*i/padsLength)); })); }); }); n.nThen(waitFor(function () { Feedback.send('Migrate-7', true); userObject.version = version = 7; })); }; if (version < 7) { addRoHref(); } }).nThen(function () { // Migration 8: remove duplicate entries in proxy.FS_hashes (list of migrated anon drives) var fixDuplicate = function () { userObject.FS_hashes = Util.deduplicateString(userObject.FS_hashes || []); }; if (version < 8) { fixDuplicate(); Feedback.send('Migrate-8', true); userObject.version = version = 8; } /*}).nThen(function (waitFor) { // Test progress bar in the loading screen var i = 0; var w = waitFor(); var it = setInterval(function () { i += 5; if (i >= 100) { w(); clearInterval(it); i = 100;} progress(0, i); }, 500); progress(0, 0);*/ }).nThen(function () { setTimeout(cb); }); }; });