From 4b0d5306e9a053d0998ab11eef228f5c5d0f6bf7 Mon Sep 17 00:00:00 2001 From: benweet Date: Sun, 15 Dec 2013 17:26:17 +0000 Subject: [PATCH] Secondary Google account (part1) --- public/res/helpers/googleHelper.js | 105 +++-- public/res/providers/gdriveProvider.js | 532 +------------------------ public/res/storage.js | 13 + 3 files changed, 86 insertions(+), 564 deletions(-) diff --git a/public/res/helpers/googleHelper.js b/public/res/helpers/googleHelper.js index 5864d083..12192de5 100644 --- a/public/res/helpers/googleHelper.js +++ b/public/res/helpers/googleHelper.js @@ -13,32 +13,42 @@ define([ ], function(_, $, constants, core, utils, storage, logger, settings, eventMgr, AsyncTask) { var connected = false; - var authorizationMgr = {}; - (function() { + var authorizationMgrMap = {}; + function AuthorizationMgr(accountId) { var permissionList = {}; var isAuthorized = false; - _.each((storage.gdrivePermissions || '').split(';'), function(permission) { + _.each((storage[accountId + '.permissions'] || '').split(';'), function(permission) { permission && (permissionList[permission] = true); }); - authorizationMgr.reset = function() { + this.reset = function() { isAuthorized = false; }; - authorizationMgr.isAuthorized = function(permission) { + this.isAuthorized = function(permission) { return isAuthorized && _.has(permissionList, permission); }; - authorizationMgr.add = function(permission) { + this.add = function(permission) { permissionList[permission] = true; - storage.gdrivePermissions = _.keys(permissionList).join(';'); + storage[accountId + '.permissions'] = _.keys(permissionList).join(';'); isAuthorized = true; }; - authorizationMgr.getListWithNew = function(permission) { + this.getListWithNew = function(permission) { var result = _.keys(permissionList); if(!_.has(permissionList, permission)) { result.push(permission); } return result; }; - })(); + var token = { + access_token: storage[accountId + '.token'] + }; + this.saveToken = function() { + token = gapi.auth.getToken(); + storage[accountId + '.token'] = token.access_token; + }; + this.getToken = function() { + return token; + }; + } var googleHelper = {}; @@ -93,14 +103,29 @@ define([ 'https://picasaweb.google.com/data/' ] }; - function authenticate(task, permission, force) { + function authenticate(task, permission, accountId, refresh) { + accountId = accountId || 'google.0'; + var authorizationMgr = authorizationMgrMap[accountId]; + if(!authorizationMgr) { + authorizationMgr = new AuthorizationMgr(accountId); + authorizationMgrMap[accountId] = authorizationMgr; + } task.onRun(function() { - if(!force && authorizationMgr.isAuthorized(permission)) { - task.chain(); - return; + var immediate = false; + var token = authorizationMgr.getToken(); + if(token.access_token) { + immediate = true; + gapi.auth.setToken(token); + if(!refresh && authorizationMgr.isAuthorized(permission)) { + task.chain(); + return; + } } - var immediate = true; function oauthRedirect() { + if(immediate === true) { + task.chain(localAuthenticate); + return; + } core.redirectConfirm('You are being redirected to Google authorization page.', function() { task.chain(localAuthenticate); }, function() { @@ -132,25 +157,26 @@ define([ } // Success authorizationMgr.add(permission); + authorizationMgr.saveToken(); task.chain(); }); }); } - task.chain(localAuthenticate); + task.chain(oauthRedirect); }); } - googleHelper.forceGdriveAuthenticate = function() { + googleHelper.refreshGdriveToken = function(accountId) { var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive', true); + authenticate(task, 'gdrive', accountId, true); task.enqueue(); }; - googleHelper.upload = function(fileId, parentId, title, content, contentType, etag, callback) { + googleHelper.upload = function(fileId, parentId, title, content, contentType, etag, accountId, callback) { var result; var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); task.onRun(function() { var boundary = '-------314159265358979323846'; var delimiter = "\r\n--" + boundary + "\r\n"; @@ -225,7 +251,7 @@ define([ } else if(error.code === 412) { // We may have missed a file update - storage.removeItem("gdrive.lastChangeId"); + storage.removeItem(accountId + ".gdrive.lastChangeId"); error = 'Conflict on file ID "' + fileId + '". Please restart the synchronization.'; } } @@ -241,11 +267,11 @@ define([ task.enqueue(); }; - googleHelper.rename = function(fileId, title, callback) { + googleHelper.rename = function(fileId, title, accountId, callback) { var result; var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); task.onRun(function() { var body = {'title': title}; var request = gapi.client.drive.files.patch({ @@ -278,11 +304,11 @@ define([ task.enqueue(); }; - googleHelper.createRealtimeFile = function(parentId, title, callback) { + googleHelper.createRealtimeFile = function(parentId, title, accountId, callback) { var result; var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); task.onRun(function() { var metadata = { title: title, @@ -373,12 +399,12 @@ define([ task.enqueue(); }; - googleHelper.checkChanges = function(lastChangeId, callback) { + googleHelper.checkChanges = function(lastChangeId, accountId, callback) { var changes = []; var newChangeId = lastChangeId || 0; var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); task.onRun(function() { var nextPageToken; function retrievePageOfChanges() { @@ -425,12 +451,12 @@ define([ task.enqueue(); }; - googleHelper.downloadMetadata = function(ids, callback, skipAuth) { + googleHelper.downloadMetadata = function(ids, accountId, callback, skipAuth) { var result = []; var task = new AsyncTask(); connect(task); if(!skipAuth) { - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); } task.onRun(function() { function recursiveDownloadMetadata() { @@ -479,14 +505,14 @@ define([ task.enqueue(); }; - googleHelper.downloadContent = function(objects, callback, skipAuth) { + googleHelper.downloadContent = function(objects, accountId, callback, skipAuth) { var result = []; var task = new AsyncTask(); // Add some time for user to choose his files task.timeout = constants.ASYNC_TASK_LONG_TIMEOUT; connect(task); if(!skipAuth) { - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); } task.onRun(function() { function recursiveDownloadContent() { @@ -555,11 +581,11 @@ define([ task.enqueue(); }; - googleHelper.loadRealtime = function(fileId, content, callback, errorCallback) { + googleHelper.loadRealtime = function(fileId, content, accountId, callback, errorCallback) { var doc; var task = new AsyncTask(); connect(task); - authenticate(task, 'gdrive'); + authenticate(task, 'gdrive', accountId); task.onRun(function() { gapi.drive.realtime.load(fileId, function(result) { // onFileLoaded @@ -599,14 +625,18 @@ define([ return; } else if(error.code === 401 || error.code === 403 || error.code == "token_refresh_required") { - authorizationMgr.reset(); + _.each(authorizationMgrMap, function(authorizationMgr) { + authorizationMgr.reset(); + }); errorMsg = "Access to Google account is not authorized."; task.retry(new Error(errorMsg), 1); return; } else if(error.code === 0 || error.code === -1) { connected = false; - authorizationMgr.reset(); + _.each(authorizationMgrMap, function(authorizationMgr) { + authorizationMgr.reset(); + }); core.setOffline(); errorMsg = "|stopPublish"; } @@ -646,7 +676,7 @@ define([ }); } - googleHelper.picker = function(callback, pickerType) { + googleHelper.picker = function(callback, pickerType, accountId) { var docs = []; var picker; function hidePicker() { @@ -659,6 +689,9 @@ define([ // Add some time for user to choose his files task.timeout = constants.ASYNC_TASK_LONG_TIMEOUT; connect(task); + if(pickerType == 'doc' || pickerType == 'folder') { + authenticate(task, 'gdrive', accountId); + } loadPicker(task); task.onRun(function() { var pickerBuilder = new google.picker.PickerBuilder(); @@ -676,6 +709,7 @@ define([ pickerBuilder.enableFeature(google.picker.Feature.NAV_HIDDEN); pickerBuilder.enableFeature(google.picker.Feature.MULTISELECT_ENABLED); pickerBuilder.addView(view); + pickerBuilder.setOAuthToken(gapi.auth.getToken()); } else if(pickerType == 'folder') { view = new google.picker.DocsView(google.picker.ViewId.FOLDERS); @@ -684,6 +718,7 @@ define([ view.setMimeTypes('application/vnd.google-apps.folder'); pickerBuilder.enableFeature(google.picker.Feature.NAV_HIDDEN); pickerBuilder.addView(view); + pickerBuilder.setOAuthToken(gapi.auth.getToken()); } else if(pickerType == 'img') { view = new google.picker.PhotosView(); diff --git a/public/res/providers/gdriveProvider.js b/public/res/providers/gdriveProvider.js index bf547ae2..c77068ef 100644 --- a/public/res/providers/gdriveProvider.js +++ b/public/res/providers/gdriveProvider.js @@ -1,531 +1,5 @@ -/*global gapi */ define([ - "jquery", - "underscore", - "constants", - "utils", - "storage", - "logger", - "classes/Provider", - "settings", - "eventMgr", - "fileMgr", - "helpers/googleHelper" -], function($, _, constants, utils, storage, logger, Provider, settings, eventMgr, fileMgr, googleHelper) { - - var PROVIDER_GDRIVE = "gdrive"; - - var gdriveProvider = new Provider(PROVIDER_GDRIVE, "Google Drive"); - gdriveProvider.defaultPublishFormat = "template"; - gdriveProvider.exportPreferencesInputIds = [ - "gdrive-parentid", - "gdrive-realtime", - ]; - - function createSyncIndex(id) { - return "sync." + PROVIDER_GDRIVE + "." + id; - } - - function createSyncAttributes(id, etag, content, title) { - var syncAttributes = {}; - syncAttributes.provider = gdriveProvider; - syncAttributes.id = id; - syncAttributes.etag = etag; - syncAttributes.contentCRC = utils.crc32(content); - syncAttributes.titleCRC = utils.crc32(title); - syncAttributes.syncIndex = createSyncIndex(id); - return syncAttributes; - } - - function importFilesFromIds(ids) { - googleHelper.downloadMetadata(ids, function(error, result) { - if(error) { - return; - } - googleHelper.downloadContent(result, function(error, result) { - if(error) { - return; - } - var fileDescList = []; - var fileDesc; - _.each(result, function(file) { - var syncAttributes = createSyncAttributes(file.id, file.etag, file.content, file.title); - syncAttributes.isRealtime = file.isRealtime; - var syncLocations = {}; - syncLocations[syncAttributes.syncIndex] = syncAttributes; - fileDesc = fileMgr.createFile(file.title, file.content, syncLocations); - fileDescList.push(fileDesc); - }); - if(fileDesc !== undefined) { - eventMgr.onSyncImportSuccess(fileDescList, gdriveProvider); - fileMgr.selectFile(fileDesc); - } - }); - }); - } - - gdriveProvider.importFiles = function() { - googleHelper.picker(function(error, docs) { - if(error || docs.length === 0) { - return; - } - var importIds = []; - _.each(docs, function(doc) { - var syncIndex = createSyncIndex(doc.id); - var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); - if(fileDesc !== undefined) { - eventMgr.onError('"' + fileDesc.title + '" was already imported.'); - return; - } - importIds.push(doc.id); - }); - importFilesFromIds(importIds); - }, 'doc'); - }; - - gdriveProvider.exportFile = function(event, title, content, callback) { - var fileId = utils.getInputTextValue("#input-sync-export-gdrive-fileid"); - if(fileId) { - // Check that file is not synchronized with another an existing - // document - var syncIndex = createSyncIndex(fileId); - var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); - if(fileDesc !== undefined) { - eventMgr.onError('File ID is already synchronized with "' + fileDesc.title + '".'); - callback(true); - return; - } - } - var parentId = utils.getInputTextValue("#input-sync-export-gdrive-parentid"); - googleHelper.upload(fileId, parentId, title, content, undefined, undefined, function(error, result) { - if(error) { - callback(error); - return; - } - var syncAttributes = createSyncAttributes(result.id, result.etag, content, title); - callback(undefined, syncAttributes); - }); - }; - - gdriveProvider.exportRealtimeFile = function(event, title, content, callback) { - var parentId = utils.getInputTextValue("#input-sync-export-gdrive-parentid"); - googleHelper.createRealtimeFile(parentId, title, function(error, result) { - if(error) { - callback(error); - return; - } - var syncAttributes = createSyncAttributes(result.id, result.etag, content, title); - callback(undefined, syncAttributes); - }); - }; - - gdriveProvider.syncUp = function(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, callback) { - // Skip if CRC has not changed - if(uploadContentCRC == syncAttributes.contentCRC && uploadTitleCRC == syncAttributes.titleCRC) { - callback(undefined, false); - return; - } - googleHelper.upload(syncAttributes.id, undefined, uploadTitle, uploadContent, undefined, syncAttributes.etag, function(error, result) { - if(error) { - callback(error, true); - return; - } - syncAttributes.etag = result.etag; - syncAttributes.contentCRC = uploadContentCRC; - syncAttributes.titleCRC = uploadTitleCRC; - callback(undefined, true); - }); - }; - - gdriveProvider.syncUpRealtime = function(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, callback) { - // Skip if title CRC has not changed - if(uploadTitleCRC == syncAttributes.titleCRC) { - callback(undefined, false); - return; - } - googleHelper.rename(syncAttributes.id, uploadTitle, function(error, result) { - if(error) { - callback(error, true); - return; - } - syncAttributes.etag = result.etag; - syncAttributes.titleCRC = uploadTitleCRC; - callback(undefined, true); - }); - }; - - gdriveProvider.syncDown = function(callback) { - var lastChangeId = parseInt(storage[PROVIDER_GDRIVE + ".lastChangeId"], 10); - googleHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) { - if(error) { - callback(error); - return; - } - var interestingChanges = []; - _.each(changes, function(change) { - var syncIndex = createSyncIndex(change.fileId); - var syncAttributes = fileMgr.getSyncAttributes(syncIndex); - if(syncAttributes === undefined) { - return; - } - // Store syncAttributes to avoid 2 times searching - change.syncAttributes = syncAttributes; - // Delete - if(change.deleted === true) { - interestingChanges.push(change); - return; - } - // Modify - if(syncAttributes.etag != change.file.etag) { - interestingChanges.push(change); - } - }); - googleHelper.downloadContent(interestingChanges, function(error, changes) { - if(error) { - callback(error); - return; - } - _.each(changes, function(change) { - var syncAttributes = change.syncAttributes; - var syncIndex = syncAttributes.syncIndex; - var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); - // No file corresponding (file may have been deleted - // locally) - if(fileDesc === undefined) { - return; - } - var localTitle = fileDesc.title; - // File deleted - if(change.deleted === true) { - eventMgr.onError('"' + localTitle + '" has been removed from Google Drive.'); - fileDesc.removeSyncLocation(syncAttributes); - eventMgr.onSyncRemoved(fileDesc, syncAttributes); - if(syncAttributes.isRealtime === true && fileMgr.currentFile === fileDesc) { - gdriveProvider.stopRealtimeSync(); - } - return; - } - var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle); - var localContent = fileDesc.content; - var localContentChanged = syncAttributes.contentCRC != utils.crc32(localContent); - var file = change.file; - var remoteTitleCRC = utils.crc32(file.title); - var remoteTitleChanged = syncAttributes.titleCRC != remoteTitleCRC; - var fileTitleChanged = localTitle != file.title; - var remoteContentCRC = utils.crc32(file.content); - var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC; - var fileContentChanged = localContent != file.content; - // Conflict detection - if((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true) || (!syncAttributes.isRealtime && fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) { - fileMgr.createFile(localTitle + " (backup)", localContent); - eventMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.'); - } - // If file title changed - if(fileTitleChanged && remoteTitleChanged === true) { - fileDesc.title = file.title; - eventMgr.onTitleChanged(fileDesc); - eventMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.'); - } - // If file content changed - if(!syncAttributes.isRealtime && fileContentChanged && remoteContentChanged === true) { - fileDesc.content = file.content; - eventMgr.onContentChanged(fileDesc); - eventMgr.onMessage('"' + file.title + '" has been updated from Google Drive.'); - if(fileMgr.currentFile === fileDesc) { - fileMgr.selectFile(); // Refresh editor - } - } - // Update syncAttributes - syncAttributes.etag = file.etag; - if(!syncAttributes.isRealtime) { - syncAttributes.contentCRC = remoteContentCRC; - } - syncAttributes.titleCRC = remoteTitleCRC; - utils.storeAttributes(syncAttributes); - }); - storage[PROVIDER_GDRIVE + ".lastChangeId"] = newChangeId; - callback(); - }); - }); - }; - - gdriveProvider.publish = function(publishAttributes, frontMatter, title, content, callback) { - var contentType = publishAttributes.format != "markdown" ? 'text/html' : undefined; - googleHelper.upload(publishAttributes.id, undefined, publishAttributes.fileName || title, content, contentType, undefined, function(error, result) { - if(error) { - callback(error); - return; - } - publishAttributes.id = result.id; - callback(); - }); - }; - - gdriveProvider.newPublishAttributes = function(event) { - var publishAttributes = {}; - publishAttributes.id = utils.getInputTextValue("#input-publish-gdrive-fileid"); - publishAttributes.fileName = utils.getInputTextValue("#input-publish-gdrive-filename"); - if(event.isPropagationStopped()) { - return undefined; - } - return publishAttributes; - }; - - // Keep a link to the Pagedown editor - var pagedownEditor; - var undoExecute; - var redoExecute; - var setUndoRedoButtonStates; - eventMgr.addListener("onPagedownConfigure", function(pagedownEditorParam) { - pagedownEditor = pagedownEditorParam; - }); - - // Keep a link to the ACE editor - var realtimeContext; - var aceEditor; - var isAceUpToDate = true; - eventMgr.addListener('onAceCreated', function(aceEditorParam) { - aceEditor = aceEditorParam; - // Listen to editor's changes - aceEditor.session.on('change', function() { - // Update the real time model if any - realtimeContext && realtimeContext.string && realtimeContext.string.setText(aceEditor.getValue()); - }); - }); - - // Start realtime synchronization - var Range = require('ace/range').Range; - gdriveProvider.startRealtimeSync = function(fileDesc, syncAttributes) { - var localContext = {}; - realtimeContext = localContext; - googleHelper.loadRealtime(syncAttributes.id, fileDesc.content, function(err, doc) { - if(err || !doc) { - return; - } - - // If user just switched to another document or file has just been - // reselected - if(localContext.isStopped === true) { - doc.close(); - return; - } - - logger.log("Starting Google Drive realtime synchronization"); - localContext.document = doc; - var model = doc.getModel(); - var realtimeString = model.getRoot().get('content'); - - // Saves model content checksum - function updateContentState() { - syncAttributes.contentCRC = utils.crc32(realtimeString.getText()); - utils.storeAttributes(syncAttributes); - } - - var debouncedRefreshPreview = _.debounce(pagedownEditor.refreshPreview, 100); - - // Listen to insert text events - realtimeString.addEventListener(gapi.drive.realtime.EventType.TEXT_INSERTED, function(e) { - if(aceEditor !== undefined && (isAceUpToDate === false || e.isLocal === false)) { - // Update ACE editor - var position = aceEditor.session.doc.indexToPosition(e.index); - aceEditor.session.insert(position, e.text); - isAceUpToDate = true; - } - // If modifications come down from a collaborator - if(e.isLocal === false) { - logger.log("Google Drive realtime document updated from server"); - updateContentState(); - aceEditor === undefined && debouncedRefreshPreview(); - } - }); - // Listen to delete text events - realtimeString.addEventListener(gapi.drive.realtime.EventType.TEXT_DELETED, function(e) { - if(aceEditor !== undefined && (isAceUpToDate === false || e.isLocal === false)) { - // Update ACE editor - var range = (function(posStart, posEnd) { - return new Range(posStart.row, posStart.column, posEnd.row, posEnd.column); - })(aceEditor.session.doc.indexToPosition(e.index), aceEditor.session.doc.indexToPosition(e.index + e.text.length)); - aceEditor.session.remove(range); - isAceUpToDate = true; - } - // If modifications come down from a collaborator - if(e.isLocal === false) { - logger.log("Google Drive realtime document updated from server"); - updateContentState(); - aceEditor === undefined && debouncedRefreshPreview(); - } - }); - doc.addEventListener(gapi.drive.realtime.EventType.DOCUMENT_SAVE_STATE_CHANGED, function(e) { - // Save success event - if(e.isPending === false && e.isSaving === false) { - logger.log("Google Drive realtime document successfully saved on server"); - updateContentState(); - } - }); - - // Try to merge offline modifications - var localContent = fileDesc.content; - var localContentChanged = syncAttributes.contentCRC != utils.crc32(localContent); - var remoteContent = realtimeString.getText(); - var remoteContentCRC = utils.crc32(remoteContent); - var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC; - var fileContentChanged = localContent != remoteContent; - if(fileContentChanged === true && localContentChanged === true) { - if(remoteContentChanged === true) { - // Conflict detected - fileMgr.createFile(fileDesc.title + " (backup)", localContent); - eventMgr.onMessage('Conflict detected on "' + fileDesc.title + '". A backup has been created locally.'); - } - else { - // Add local modifications if no collaborators change - realtimeString.setText(localContent); - } - } - - if(aceEditor === undefined) { - // Binds model with textarea - localContext.binding = gapi.drive.realtime.databinding.bindString(realtimeString, document.getElementById("wmd-input")); - } - - // Update content state according to collaborators changes - if(remoteContentChanged === true) { - logger.log("Google Drive realtime document updated from server"); - aceEditor !== undefined && aceEditor.setValue(remoteContent, -1); - updateContentState(); - aceEditor === undefined && debouncedRefreshPreview(); - } - - if(aceEditor !== undefined) { - // Tell ACE to update realtime string on each change - localContext.string = realtimeString; - } - - // Save undo/redo buttons default actions - undoExecute = pagedownEditor.uiManager.buttons.undo.execute; - redoExecute = pagedownEditor.uiManager.buttons.redo.execute; - setUndoRedoButtonStates = pagedownEditor.uiManager.setUndoRedoButtonStates; - - // Set temporary actions for undo/redo buttons - pagedownEditor.uiManager.buttons.undo.execute = function() { - if(model.canUndo) { - // This flag is used to avoid replaying editor's own - // modifications (assuming it's synchronous) - isAceUpToDate = false; - model.undo(); - } - }; - pagedownEditor.uiManager.buttons.redo.execute = function() { - if(model.canRedo) { - // This flag is used to avoid replaying editor's own - // modifications (assuming it's synchronous) - isAceUpToDate = false; - model.redo(); - } - }; - - // Add event handler for model's UndoRedoStateChanged events - pagedownEditor.uiManager.setUndoRedoButtonStates = function() { - setTimeout(function() { - pagedownEditor.uiManager.setButtonState(pagedownEditor.uiManager.buttons.undo, model.canUndo); - pagedownEditor.uiManager.setButtonState(pagedownEditor.uiManager.buttons.redo, model.canRedo); - }, 50); - }; - pagedownEditor.uiManager.setUndoRedoButtonStates(); - model.addEventListener(gapi.drive.realtime.EventType.UNDO_REDO_STATE_CHANGED, function() { - pagedownEditor.uiManager.setUndoRedoButtonStates(); - }); - - }, function(err) { - console.error(err); - if(err.type == "token_refresh_required") { - googleHelper.forceGdriveAuthenticate(); - } - else if(err.type == "not_found") { - eventMgr.onError('"' + fileDesc.title + '" has been removed from Google Drive.'); - fileDesc.removeSyncLocation(syncAttributes); - eventMgr.onSyncRemoved(fileDesc, syncAttributes); - gdriveProvider.stopRealtimeSync(); - } - else if(err.isFatal) { - eventMgr.onError('An error has forced real time synchronization to stop.'); - gdriveProvider.stopRealtimeSync(); - } - }); - }; - - // Stop realtime synchronization - gdriveProvider.stopRealtimeSync = function() { - logger.log("Stopping Google Drive realtime synchronization"); - if(realtimeContext !== undefined) { - realtimeContext.isStopped = true; - realtimeContext.binding && realtimeContext.binding.unbind(); - realtimeContext.document && realtimeContext.document.close(); - realtimeContext = undefined; - } - - if(setUndoRedoButtonStates !== undefined) { - // Set back original undo/redo actions - pagedownEditor.uiManager.buttons.undo.execute = undoExecute; - pagedownEditor.uiManager.buttons.redo.execute = redoExecute; - pagedownEditor.uiManager.setUndoRedoButtonStates = setUndoRedoButtonStates; - pagedownEditor.uiManager.setUndoRedoButtonStates(); - } - }; - - eventMgr.addListener("onReady", function() { - // Choose folder button in export modal - $('.export-gdrive-choose-folder').click(function() { - googleHelper.picker(function(error, docs) { - if(error || docs.length === 0) { - return; - } - // Open export dialog - $(".modal-upload-gdrive").modal(); - // Set parent ID - utils.setInputValue('#input-sync-export-gdrive-parentid', docs[0].id); - }, 'folder'); - }); - - // On export, disable file ID input if realtime is checked - var $realtimeCheckboxElt = $('#input-sync-export-gdrive-realtime'); - var $fileIdInputElt = $('#input-sync-export-gdrive-fileid'); - $('#input-sync-export-gdrive-realtime').change(function() { - $fileIdInputElt.prop('disabled', $realtimeCheckboxElt.prop('checked')); - }); - - var state = utils.retrieveIgnoreError(PROVIDER_GDRIVE + ".state"); - if(state === undefined) { - return; - } - storage.removeItem(PROVIDER_GDRIVE + ".state"); - if(state.action == "create") { - googleHelper.upload(undefined, state.folderId, constants.GDRIVE_DEFAULT_FILE_TITLE, settings.defaultContent, undefined, undefined, function(error, file) { - if(error) { - return; - } - var syncAttributes = createSyncAttributes(file.id, file.etag, file.content, file.title); - var syncLocations = {}; - syncLocations[syncAttributes.syncIndex] = syncAttributes; - var fileDesc = fileMgr.createFile(file.title, file.content, syncLocations); - fileMgr.selectFile(fileDesc); - eventMgr.onMessage('"' + file.title + '" created successfully on Google Drive.'); - }); - } - else if(state.action == "open") { - var importIds = []; - _.each(state.ids, function(id) { - var syncIndex = createSyncIndex(id); - var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex); - if(fileDesc !== undefined) { - fileDesc !== fileMgr.currentFile && fileMgr.selectFile(fileDesc); - } - else { - importIds.push(id); - } - }); - importFilesFromIds(importIds); - } - }); - - return gdriveProvider; + "providers/gdriveProviderBuilder" +], function(gdriveProviderBuilder) { + return gdriveProviderBuilder("gdrive", "Google Drive", 'google.0') }); \ No newline at end of file diff --git a/public/res/storage.js b/public/res/storage.js index 1839b29c..746fcf17 100644 --- a/public/res/storage.js +++ b/public/res/storage.js @@ -232,6 +232,19 @@ define([ version = "v15"; } + // Upgrade from v15 to v16 + if(version == "v15") { + if(_.has(localStorage, 'gdrivePermissions')) { + localStorage['google.0.permissions'] = localStorage.gdrivePermissions; + localStorage.removeItem('gdrivePermissions'); + } + if(_.has(localStorage, 'gdrive.lastChangeId')) { + localStorage['google.0.gdrive.lastChangeId'] = localStorage['gdrive.lastChangeId']; + localStorage.removeItem('gdrive.lastChangeId'); + } + version = "v16"; + } + localStorage.version = version; return localStorage; }); \ No newline at end of file