New synchronize pattern
This commit is contained in:
parent
2177785ca5
commit
717eb5c3e9
@ -4,7 +4,6 @@ define(["jquery", "google-helper"], function($, googleHelper) {
|
||||
var core = undefined;
|
||||
|
||||
var bloggerProvider = {
|
||||
providerType: PROVIDER_TYPE_PUBLISH_FLAG,
|
||||
providerId: PROVIDER_BLOGGER,
|
||||
providerName: "Blogger",
|
||||
defaultPublishFormat: "html"
|
||||
|
@ -12,10 +12,6 @@ var ASYNC_TASK_DEFAULT_TIMEOUT = 30000;
|
||||
var ASYNC_TASK_LONG_TIMEOUT = 90000;
|
||||
var SYNC_PERIOD = 180000;
|
||||
var USER_IDLE_THRESHOLD = 300000;
|
||||
var SYNC_PROVIDER_GDRIVE = "sync.gdrive.";
|
||||
var SYNC_PROVIDER_DROPBOX = "sync.dropbox.";
|
||||
var PROVIDER_TYPE_SYNC_FLAG = 1;
|
||||
var PROVIDER_TYPE_PUBLISH_FLAG = 2;
|
||||
var PROVIDER_BLOGGER = "blogger";
|
||||
var PROVIDER_DROPBOX = "dropbox";
|
||||
var PROVIDER_GDRIVE = "gdrive";
|
||||
|
@ -177,7 +177,7 @@ define(
|
||||
|
||||
// Setting management
|
||||
core.settings = {
|
||||
converterType : "markdown-extra",
|
||||
converterType : "markdown-extra-prettify",
|
||||
layoutOrientation : "horizontal",
|
||||
editorFontSize : 14,
|
||||
commitMsg : "Published by StackEdit.",
|
||||
@ -502,6 +502,12 @@ define(
|
||||
|
||||
// from v1 to v2
|
||||
if(version == "v1") {
|
||||
var gdriveLastChangeId = localStorage["sync.gdrive.lastChangeId"];
|
||||
localStorage["gdrive.lastChangeId"] = gdriveLastChangeId;
|
||||
localStorage.removeItem("sync.gdrive.lastChangeId");
|
||||
var dropboxLastChangeId = localStorage["sync.dropbox.lastChangeId"];
|
||||
localStorage["dropbox.lastChangeId"] = dropboxLastChangeId;
|
||||
localStorage.removeItem("sync.dropbox.lastChangeId");
|
||||
|
||||
var SYNC_PROVIDER_GDRIVE = "sync." + PROVIDER_GDRIVE + ".";
|
||||
var SYNC_PROVIDER_DROPBOX = "sync." + PROVIDER_DROPBOX + ".";
|
||||
|
@ -108,7 +108,7 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
asyncRunner.addTask(task);
|
||||
};
|
||||
|
||||
dropboxHelper.checkUpdates = function(lastChangeId, callback) {
|
||||
dropboxHelper.checkChanges = function(lastChangeId, callback) {
|
||||
callback = callback || core.doNothing;
|
||||
var changes = [];
|
||||
var newChangeId = lastChangeId || 0;
|
||||
@ -125,14 +125,7 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
// Retrieve success
|
||||
newChangeId = pullChanges.cursor();
|
||||
if(pullChanges.changes !== undefined) {
|
||||
for(var i=0; i<pullChanges.changes.length; i++) {
|
||||
var item = pullChanges.changes[i];
|
||||
var version = localStorage[SYNC_PROVIDER_DROPBOX
|
||||
+ encodeURIComponent(item.path.toLowerCase()) + ".version"];
|
||||
if(version && (item.wasRemoved || item.stat.versionTag != version)) {
|
||||
changes.push(item);
|
||||
}
|
||||
}
|
||||
changes = changes.concat(pullChanges.changes);
|
||||
}
|
||||
if (pullChanges.shouldPullAgain) {
|
||||
task.chain(retrievePageOfChanges);
|
||||
|
@ -5,10 +5,10 @@ define(["jquery", "dropbox-helper"], function($, dropboxHelper) {
|
||||
var fileManager = undefined;
|
||||
|
||||
var dropboxProvider = {
|
||||
providerType: PROVIDER_TYPE_SYNC_FLAG | PROVIDER_TYPE_PUBLISH_FLAG,
|
||||
providerId: PROVIDER_DROPBOX,
|
||||
providerName: "Dropbox",
|
||||
defaultPublishFormat: "template"
|
||||
defaultPublishFormat: "template",
|
||||
useSync: false
|
||||
};
|
||||
|
||||
function checkPath(path) {
|
||||
@ -110,6 +110,113 @@ define(["jquery", "dropbox-helper"], function($, dropboxHelper) {
|
||||
exportFileToPath(path);
|
||||
};
|
||||
|
||||
dropboxProvider.syncUp = function(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, callback) {
|
||||
var syncContentCRC = syncAttributes.contentCRC;
|
||||
// Skip if CRC has not changed
|
||||
if(uploadContentCRC == syncContentCRC) {
|
||||
callback(undefined, false);
|
||||
return;
|
||||
}
|
||||
dropboxHelper.upload(syncAttributes.path, uploadContent, function(error, result) {
|
||||
if(error) {
|
||||
callback(error, true);
|
||||
return;
|
||||
}
|
||||
syncAttributes.version = result.versionTag;
|
||||
syncAttributes.contentCRC = uploadContentCRC;
|
||||
callback(undefined, true);
|
||||
});
|
||||
};
|
||||
|
||||
function syncDown(callback) {
|
||||
if (dropboxProvider.useSync === false) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
var lastChangeId = parseInt(localStorage[PROVIDER_DROPBOX + ".lastChangeId"]);
|
||||
dropboxHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var interestingChanges = [];
|
||||
_.each(changes, function(change) {
|
||||
var syncIndex = "sync." + PROVIDER_DROPBOX + "." + encodeURIComponent(file.path.toLowerCase());
|
||||
var serializedAttributes = localStorage[syncIndex];
|
||||
if(serializedAttributes === undefined) {
|
||||
return;
|
||||
}
|
||||
// Store syncIndex to avoid 2 times formating
|
||||
change.syncIndex = syncIndex;
|
||||
// Delete
|
||||
if(change.wasRemoved === true) {
|
||||
interestingChanges.push(change);
|
||||
return;
|
||||
}
|
||||
// Modify
|
||||
var syncAttributes = JSON.parse(serializedAttributes);
|
||||
if(syncAttributes.version != change.stat.versionTag) {
|
||||
interestingChanges.push(change);
|
||||
// Store syncAttributes to avoid 2 times parsing
|
||||
change.syncAttributes = syncAttributes;
|
||||
}
|
||||
});
|
||||
dropboxHelper.downloadContent(changes, function(error, changes) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var updateFileTitles = false;
|
||||
_.each(changes, function(change) {
|
||||
var syncIndex = change.syncIndex;
|
||||
var fileIndex = fileManager.getFileIndexFromSync(syncIndex);
|
||||
// No file corresponding (file may have been deleted locally)
|
||||
if(fileIndex === undefined) {
|
||||
fileManager.removeSync(syncIndex);
|
||||
return;
|
||||
}
|
||||
var localTitle = localStorage[fileIndex + ".title"];
|
||||
// File deleted
|
||||
if (change.wasRemoved === true) {
|
||||
fileManager.removeSync(syncIndex);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been removed from Dropbox.');
|
||||
return;
|
||||
}
|
||||
var syncAttributes = change.syncAttributes;
|
||||
var localContent = localStorage[fileIndex + ".content"];
|
||||
var localContentChanged = syncAttributes.contentCRC != core.crc32(localContent);
|
||||
var file = change.stat;
|
||||
var fileContentChanged = localContent != file.content;
|
||||
// Conflict detection
|
||||
if (fileContentChanged === true && localContentChanged === true) {
|
||||
fileManager.createFile(localTitle + " (backup)", localContent);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||
}
|
||||
// If file content changed
|
||||
if(fileContentChanged) {
|
||||
localStorage[fileIndex + ".content"] = file.content;
|
||||
core.showMessage('"' + localTitle + '" has been updated from Dropbox.');
|
||||
if(fileManager.isCurrentFileIndex(fileIndex)) {
|
||||
updateFileTitles = false; // Done by next function
|
||||
fileManager.selectFile(); // Refresh editor
|
||||
}
|
||||
}
|
||||
// Update syncAttributes
|
||||
syncAttributes.version = file.versionTag;
|
||||
syncAttributes.contentCRC = core.crc32(file.content);
|
||||
localStorage[syncIndex] = JSON.stringify(syncAttributes);
|
||||
});
|
||||
if(updateFileTitles) {
|
||||
fileManager.updateFileTitles();
|
||||
}
|
||||
localStorage[PROVIDER_DROPBOX + ".lastChangeId"] = newChangeId;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
dropboxProvider.publish = function(publishAttributes, title, content, callback) {
|
||||
var path = checkPath(publishAttributes.path);
|
||||
if(path === undefined) {
|
||||
|
@ -136,19 +136,13 @@ define(["jquery", "google-helper", "dropbox-helper", "github-helper", "synchroni
|
||||
fileManager.setCurrentFileIndex(fileIndex);
|
||||
}
|
||||
|
||||
var useGoogleDrive = false;
|
||||
var useDropbox = false;
|
||||
synchronizer.resetSyncFlags();
|
||||
function composeTitle(fileIndex) {
|
||||
var result = " " + localStorage[fileIndex + ".title"];
|
||||
var sync = localStorage[fileIndex + ".sync"];
|
||||
if (sync.indexOf(";" + SYNC_PROVIDER_DROPBOX) !== -1) {
|
||||
useDropbox = true;
|
||||
result = '<i class="icon-dropbox"></i>' + result;
|
||||
}
|
||||
if (sync.indexOf(";" + SYNC_PROVIDER_GDRIVE) !== -1) {
|
||||
useGoogleDrive = true;
|
||||
result = '<i class="icon-gdrive"></i>' + result;
|
||||
}
|
||||
var providerIdList = synchronizer.getSyncProvidersFromFile(fileIndex);
|
||||
_.each(providerIdList, function(providerId) {
|
||||
result = '<i class="icon-' + providerId '"></i>' + result;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -175,8 +169,6 @@ define(["jquery", "google-helper", "dropbox-helper", "github-helper", "synchroni
|
||||
}
|
||||
$("#file-selector").append(li);
|
||||
});
|
||||
synchronizer.useGoogleDrive = useGoogleDrive;
|
||||
synchronizer.useDropbox = useDropbox;
|
||||
};
|
||||
|
||||
// Remove a syncIndex (synchronized location)
|
||||
|
@ -5,10 +5,10 @@ define(["jquery", "google-helper", "underscore"], function($, googleHelper) {
|
||||
var fileManager = undefined;
|
||||
|
||||
var gdriveProvider = {
|
||||
providerType: PROVIDER_TYPE_SYNC_FLAG | PROVIDER_TYPE_PUBLISH_FLAG,
|
||||
providerId: PROVIDER_GDRIVE,
|
||||
providerName: "Gdrive",
|
||||
defaultPublishFormat: "template"
|
||||
defaultPublishFormat: "template",
|
||||
useSync: false
|
||||
};
|
||||
|
||||
function createSyncAttributes(id, etag, content, title) {
|
||||
@ -63,7 +63,7 @@ define(["jquery", "google-helper", "underscore"], function($, googleHelper) {
|
||||
};
|
||||
|
||||
gdriveProvider.exportFile = function(event, title, content, callback) {
|
||||
googleHelper.upload(undefined, undefined, title, content, function(error, result) {
|
||||
googleHelper.upload(undefined, undefined, title, content, undefined, function(error, result) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
@ -87,7 +87,7 @@ define(["jquery", "google-helper", "underscore"], function($, googleHelper) {
|
||||
callback(true);
|
||||
return;
|
||||
}
|
||||
googleHelper.upload(id, undefined, title, content, function(error, result) {
|
||||
googleHelper.upload(id, undefined, title, content, undefined, function(error, result) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
@ -97,8 +97,127 @@ define(["jquery", "google-helper", "underscore"], function($, googleHelper) {
|
||||
});
|
||||
};
|
||||
|
||||
gdriveProvider.syncUp = function(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, callback) {
|
||||
var syncContentCRC = syncAttributes.contentCRC;
|
||||
var syncTitleCRC = syncAttributes.titleCRC;
|
||||
// Skip if CRC has not changed
|
||||
if(uploadContentCRC == syncContentCRC && uploadTitleCRC == syncTitleCRC) {
|
||||
callback(undefined, false);
|
||||
return;
|
||||
}
|
||||
googleHelper.upload(syncAttributes.id, undefined, uploadTitle, uploadContent, syncAttributes.etag, function(error, result) {
|
||||
if(error) {
|
||||
callback(error, true);
|
||||
return;
|
||||
}
|
||||
syncAttributes.etag = result.etag;
|
||||
syncAttributes.contentCRC = uploadContentCRC;
|
||||
syncAttributes.titleCRC = uploadTitleCRC;
|
||||
callback(undefined, true);
|
||||
});
|
||||
};
|
||||
|
||||
function syncDown(callback) {
|
||||
if (gdriveProvider.useSync === false) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
var lastChangeId = parseInt(localStorage[PROVIDER_GDRIVE + ".lastChangeId"]);
|
||||
googleHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var interestingChanges = [];
|
||||
_.each(changes, function(change) {
|
||||
var syncIndex = "sync." + PROVIDER_GDRIVE + "." + file.id;
|
||||
var serializedAttributes = localStorage[syncIndex];
|
||||
if(serializedAttributes === undefined) {
|
||||
return;
|
||||
}
|
||||
// Store syncIndex to avoid 2 times formating
|
||||
change.syncIndex = syncIndex;
|
||||
// Delete
|
||||
if(change.deleted === true) {
|
||||
interestingChanges.push(change);
|
||||
return;
|
||||
}
|
||||
// Modify
|
||||
var syncAttributes = JSON.parse(serializedAttributes);
|
||||
if(syncAttributes.etag != change.file.etag) {
|
||||
interestingChanges.push(change);
|
||||
// Store syncAttributes to avoid 2 times parsing
|
||||
change.syncAttributes = syncAttributes;
|
||||
}
|
||||
});
|
||||
googleHelper.downloadContent(changes, function(error, changes) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var updateFileTitles = false;
|
||||
_.each(changes, function(change) {
|
||||
var syncIndex = change.syncIndex;
|
||||
var fileIndex = fileManager.getFileIndexFromSync(syncIndex);
|
||||
// No file corresponding (file may have been deleted locally)
|
||||
if(fileIndex === undefined) {
|
||||
fileManager.removeSync(syncIndex);
|
||||
return;
|
||||
}
|
||||
var localTitle = localStorage[fileIndex + ".title"];
|
||||
// File deleted
|
||||
if (change.deleted === true) {
|
||||
fileManager.removeSync(syncIndex);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been removed from Google Drive.');
|
||||
return;
|
||||
}
|
||||
var syncAttributes = change.syncAttributes;
|
||||
var localTitleChanged = syncAttributes.titleCRC != core.crc32(localTitle);
|
||||
var localContent = localStorage[fileIndex + ".content"];
|
||||
var localContentChanged = syncAttributes.contentCRC != core.crc32(localContent);
|
||||
var file = change.file;
|
||||
var fileTitleChanged = localTitle != file.title;
|
||||
var fileContentChanged = localContent != file.content;
|
||||
// Conflict detection
|
||||
if ((fileTitleChanged === true && localTitleChanged === true)
|
||||
|| (fileContentChanged === true && localContentChanged === true)) {
|
||||
fileManager.createFile(localTitle + " (backup)", localContent);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||
}
|
||||
// If file title changed
|
||||
if(fileTitleChanged) {
|
||||
localStorage[fileIndex + ".title"] = file.title;
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
|
||||
}
|
||||
// If file content changed
|
||||
if(fileContentChanged) {
|
||||
localStorage[fileIndex + ".content"] = file.content;
|
||||
core.showMessage('"' + file.title + '" has been updated from Google Drive.');
|
||||
if(fileManager.isCurrentFileIndex(fileIndex)) {
|
||||
updateFileTitles = false; // Done by next function
|
||||
fileManager.selectFile(); // Refresh editor
|
||||
}
|
||||
}
|
||||
// Update syncAttributes
|
||||
syncAttributes.etag = file.etag;
|
||||
syncAttributes.contentCRC = core.crc32(file.content);
|
||||
syncAttributes.titleCRC = core.crc32(file.title);
|
||||
localStorage[syncIndex] = JSON.stringify(syncAttributes);
|
||||
});
|
||||
if(updateFileTitles) {
|
||||
fileManager.updateFileTitles();
|
||||
}
|
||||
localStorage[PROVIDER_GDRIVE + ".lastChangeId"] = newChangeId;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
gdriveProvider.publish = function(publishAttributes, title, content, callback) {
|
||||
googleHelper.upload(publishAttributes.fileId, undefined, title, content, callback);
|
||||
googleHelper.upload(publishAttributes.fileId, undefined, title, content, undefined, callback);
|
||||
};
|
||||
|
||||
gdriveProvider.newPublishAttributes = function(event) {
|
||||
@ -122,7 +241,7 @@ define(["jquery", "google-helper", "underscore"], function($, googleHelper) {
|
||||
state = JSON.parse(state);
|
||||
if (state.action == "create") {
|
||||
googleHelper.upload(undefined, state.folderId, GDRIVE_DEFAULT_FILE_TITLE,
|
||||
"", function(error, file) {
|
||||
"", undefined, function(error, file) {
|
||||
if(error) {
|
||||
return;
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ define(["jquery", "github-helper"], function($, githubHelper) {
|
||||
var core = undefined;
|
||||
|
||||
var githubProvider = {
|
||||
providerType: PROVIDER_TYPE_PUBLISH_FLAG,
|
||||
providerId: PROVIDER_GITHUB,
|
||||
providerName: "GitHub"
|
||||
};
|
||||
|
@ -76,7 +76,7 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
});
|
||||
}
|
||||
|
||||
googleHelper.upload = function(fileId, parentId, title, content, callback) {
|
||||
googleHelper.upload = function(fileId, parentId, title, content, etag, callback) {
|
||||
callback = callback || core.doNothing;
|
||||
var result = undefined;
|
||||
var task = asyncRunner.createTask();
|
||||
@ -95,13 +95,10 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
}
|
||||
var path = '/upload/drive/v2/files';
|
||||
var method = 'POST';
|
||||
var etag = undefined;
|
||||
if (fileId !== undefined) {
|
||||
// If it's an update
|
||||
path += "/" + fileId;
|
||||
method = 'PUT';
|
||||
etag = localStorage[SYNC_PROVIDER_GDRIVE
|
||||
+ fileId + ".etag"];
|
||||
}
|
||||
var headers = { 'Content-Type' : 'multipart/mixed; boundary="'
|
||||
+ boundary + '"', };
|
||||
@ -155,7 +152,7 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
asyncRunner.addTask(task);
|
||||
};
|
||||
|
||||
googleHelper.checkUpdates = function(lastChangeId, callback) {
|
||||
googleHelper.checkChanges = function(lastChangeId, callback) {
|
||||
callback = callback || core.doNothing;
|
||||
var changes = [];
|
||||
var newChangeId = lastChangeId || 0;
|
||||
@ -185,15 +182,7 @@ define(["jquery", "async-runner"], function($, asyncRunner) {
|
||||
newChangeId = response.largestChangeId;
|
||||
nextPageToken = response.nextPageToken;
|
||||
if (response.items !== undefined) {
|
||||
for ( var i = 0; i < response.items.length; i++) {
|
||||
var item = response.items[i];
|
||||
var etag = localStorage[SYNC_PROVIDER_GDRIVE
|
||||
+ item.fileId + ".etag"];
|
||||
if (etag
|
||||
&& (item.deleted === true || item.file.etag != etag)) {
|
||||
changes.push(item);
|
||||
}
|
||||
}
|
||||
changes = changes.concat(response.items);
|
||||
}
|
||||
if (nextPageToken !== undefined) {
|
||||
task.chain(retrievePageOfChanges);
|
||||
|
@ -9,7 +9,7 @@ define(["jquery", "github-provider", "blogger-provider", "dropbox-provider", "gd
|
||||
// Create a map with providerName: providerObject
|
||||
var providerMap = _.chain(arguments)
|
||||
.map(function(argument) {
|
||||
return argument && argument.providerType & PROVIDER_TYPE_PUBLISH_FLAG && [argument.providerId, argument];
|
||||
return argument && argument.providerId && [argument.providerId, argument];
|
||||
}).compact().object().value();
|
||||
|
||||
// Used to know if the current file has publications
|
||||
|
@ -8,7 +8,7 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
// Create a map with providerName: providerObject
|
||||
var providerMap = _.chain(arguments)
|
||||
.map(function(argument) {
|
||||
return argument && argument.providerType & PROVIDER_TYPE_SYNC_FLAG && [argument.providerId, argument];
|
||||
return argument && argument.providerId && [argument.providerId, argument];
|
||||
}).compact().object().value();
|
||||
|
||||
// Used to know the providers we are connected to
|
||||
@ -59,51 +59,32 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
|
||||
// Dequeue a synchronized location
|
||||
var syncIndex = uploadFileSyncIndexList.pop();
|
||||
var syncAttributes = JSON.parse(localStorage[fileSyncIndex]);
|
||||
=
|
||||
var syncContentCRC = localStorage[fileSyncIndex + ".contentCRC"];
|
||||
var syncTitleCRC = localStorage[fileSyncIndex + ".titleCRC"];
|
||||
// Skip if CRC has not changed
|
||||
if(uploadContentCRC == syncContentCRC && (syncTitleCRC === undefined || uploadTitleCRC == syncTitleCRC)) {
|
||||
locationUp(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
// If upload is going to run, go for an other upload cycle at the end
|
||||
uploadCycle = true;
|
||||
// When page is refreshed, this flag is false but should be true here
|
||||
uploadPending = true;
|
||||
|
||||
// Try to find the provider
|
||||
if (fileSyncIndex.indexOf(SYNC_PROVIDER_GDRIVE) === 0) {
|
||||
var id = fileSyncIndex.substring(SYNC_PROVIDER_GDRIVE.length);
|
||||
googleHelper.upload(id, undefined, uploadTitle, uploadContent, function(error, result) {
|
||||
var syncAttributes = JSON.parse(localStorage[syncIndex]);
|
||||
// Use the specified provider to perform the upload
|
||||
providerMap[syncAttributes.provider].syncUp(
|
||||
uploadContent,
|
||||
uploadContentCRC,
|
||||
uploadTitle,
|
||||
uploadTitleCRC,
|
||||
syncAttributes,
|
||||
function(error, uploadFlag) {
|
||||
if(uploadFlag === true) {
|
||||
// If uploadFlag is true, request another upload cycle
|
||||
uploadCycle = true;
|
||||
// When page is refreshed, this flag is false but should be true
|
||||
uploadPending = true;
|
||||
}
|
||||
if(error) {
|
||||
// If error we abort the synchronization (retry later)
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
localStorage[fileSyncIndex + ".contentCRC"] = uploadContentCRC;
|
||||
localStorage[fileSyncIndex + ".titleCRC"] = uploadTitleCRC;
|
||||
locationUp(callback);
|
||||
});
|
||||
} else if (fileSyncIndex.indexOf(SYNC_PROVIDER_DROPBOX) === 0) {
|
||||
var path = fileSyncIndex.substring(SYNC_PROVIDER_DROPBOX.length);
|
||||
path = decodeURIComponent(path);
|
||||
dropboxHelper.upload(path, uploadContent, function(error, result) {
|
||||
if (error) {
|
||||
// If error we abort the synchronization (retry later)
|
||||
callback(error);
|
||||
return;
|
||||
if(uploadFlag) {
|
||||
// Update syncAttributes in localStorage
|
||||
localStorage[syncIndex] = JSON.stringify(syncAttributes);
|
||||
}
|
||||
localStorage[fileSyncIndex + ".contentCRC"] = uploadContentCRC;
|
||||
locationUp(callback);
|
||||
});
|
||||
} else {
|
||||
// This should never happen
|
||||
console.error("Invalid fileSyncIndex: " + fileSyncIndex);
|
||||
callback("error");
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Recursive function to upload multiple files
|
||||
@ -119,7 +100,7 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
// Dequeue a fileIndex
|
||||
var fileIndex = uploadFileIndexList.pop();
|
||||
var fileSyncIndexes = localStorage[fileIndex + ".sync"];
|
||||
if(!fileIndex || fileSyncIndexes.length === 1) {
|
||||
if(fileSyncIndexes.length === 1) {
|
||||
fileUp(callback);
|
||||
return;
|
||||
}
|
||||
@ -141,7 +122,7 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
if(uploadCycle === true) {
|
||||
// New upload cycle
|
||||
uploadCycle = false;
|
||||
uploadFileIndexList = localStorage["file.list"].split(";");
|
||||
uploadFileIndexList = _.compact(localStorage["file.list"].split(";"));
|
||||
fileUp(callback);
|
||||
}
|
||||
else {
|
||||
@ -149,157 +130,25 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
}
|
||||
}
|
||||
|
||||
// Used to download file changes from Google Drive
|
||||
function syncDownGdrive(callback) {
|
||||
if (synchronizer.useGoogleDrive === false) {
|
||||
// Recursive function to download changes from multiple providers
|
||||
var providerList = [];
|
||||
function providerDown(callback) {
|
||||
if(providerList.length === 0) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
var lastChangeId = parseInt(localStorage[SYNC_PROVIDER_GDRIVE
|
||||
+ "lastChangeId"]);
|
||||
googleHelper.checkUpdates(lastChangeId, function(error, changes, newChangeId) {
|
||||
if (error) {
|
||||
var provider = providerList.pop();
|
||||
provider.syncDown(function(error) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
googleHelper.downloadContent(changes, function(error, changes) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var updateFileTitles = false;
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
var change = changes[i];
|
||||
var fileSyncIndex = SYNC_PROVIDER_GDRIVE + change.fileId;
|
||||
var fileIndex = fileManager.getFileIndexFromSync(fileSyncIndex);
|
||||
// No file corresponding (file may have been deleted locally)
|
||||
if(fileIndex === undefined) {
|
||||
fileManager.removeSync(fileSyncIndex);
|
||||
continue;
|
||||
}
|
||||
var localTitle = localStorage[fileIndex + ".title"];
|
||||
// File deleted
|
||||
if (change.deleted === true) {
|
||||
fileManager.removeSync(fileSyncIndex);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been removed from Google Drive.');
|
||||
continue;
|
||||
}
|
||||
var localTitleChanged = localStorage[fileSyncIndex + ".titleCRC"] != core.crc32(localTitle);
|
||||
var localContent = localStorage[fileIndex + ".content"];
|
||||
var localContentChanged = localStorage[fileSyncIndex + ".contentCRC"] != core.crc32(localContent);
|
||||
var file = change.file;
|
||||
var fileTitleChanged = localTitle != file.title;
|
||||
var fileContentChanged = localContent != file.content;
|
||||
// Conflict detection
|
||||
if ((fileTitleChanged === true && localTitleChanged === true)
|
||||
|| (fileContentChanged === true && localContentChanged === true)) {
|
||||
fileManager.createFile(localTitle + " (backup)", localContent);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||
}
|
||||
// If file title changed
|
||||
if(fileTitleChanged) {
|
||||
localStorage[fileIndex + ".title"] = file.title;
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
|
||||
}
|
||||
// If file content changed
|
||||
if(fileContentChanged) {
|
||||
localStorage[fileIndex + ".content"] = file.content;
|
||||
core.showMessage('"' + file.title + '" has been updated from Google Drive.');
|
||||
if(fileManager.isCurrentFileIndex(fileIndex)) {
|
||||
updateFileTitles = false; // Done by next function
|
||||
fileManager.selectFile(); // Refresh editor
|
||||
}
|
||||
}
|
||||
// Update file etag and CRCs
|
||||
localStorage[fileSyncIndex + ".etag"] = file.etag;
|
||||
localStorage[fileSyncIndex + ".contentCRC"] = core.crc32(file.content);
|
||||
localStorage[fileSyncIndex + ".titleCRC"] = core.crc32(file.title);
|
||||
}
|
||||
if(updateFileTitles) {
|
||||
fileManager.updateFileTitles();
|
||||
}
|
||||
localStorage[SYNC_PROVIDER_GDRIVE
|
||||
+ "lastChangeId"] = newChangeId;
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Used to download file changes from Dropbox
|
||||
function syncDownDropbox(callback) {
|
||||
if (synchronizer.useDropbox === false) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
var lastChangeId = localStorage[SYNC_PROVIDER_DROPBOX + "lastChangeId"];
|
||||
dropboxHelper.checkUpdates(lastChangeId, function(error, changes, newChangeId) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
dropboxHelper.downloadContent(changes, function(error, changes) {
|
||||
if (error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
var updateFileTitles = false;
|
||||
for ( var i = 0; i < changes.length; i++) {
|
||||
var change = changes[i];
|
||||
var fileSyncIndex = SYNC_PROVIDER_DROPBOX + encodeURIComponent(change.path.toLowerCase());
|
||||
var fileIndex = fileManager.getFileIndexFromSync(fileSyncIndex);
|
||||
// No file corresponding (file may have been deleted locally)
|
||||
if(fileIndex === undefined) {
|
||||
fileManager.removeSync(fileSyncIndex);
|
||||
continue;
|
||||
}
|
||||
var localTitle = localStorage[fileIndex + ".title"];
|
||||
// File deleted
|
||||
if (change.wasRemoved === true) {
|
||||
fileManager.removeSync(fileSyncIndex);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('"' + localTitle + '" has been removed from Dropbox.');
|
||||
continue;
|
||||
}
|
||||
var localContent = localStorage[fileIndex + ".content"];
|
||||
var localContentChanged = localStorage[fileSyncIndex + ".contentCRC"] != core.crc32(localContent);
|
||||
var file = change.stat;
|
||||
var fileContentChanged = localContent != file.content;
|
||||
// Conflict detection
|
||||
if (fileContentChanged === true && localContentChanged === true) {
|
||||
fileManager.createFile(localTitle + " (backup)", localContent);
|
||||
updateFileTitles = true;
|
||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||
}
|
||||
// If file content changed
|
||||
if(fileContentChanged) {
|
||||
localStorage[fileIndex + ".content"] = file.content;
|
||||
core.showMessage('"' + localTitle + '" has been updated from Dropbox.');
|
||||
if(fileManager.isCurrentFileIndex(fileIndex)) {
|
||||
updateFileTitles = false; // Done by next function
|
||||
fileManager.selectFile(); // Refresh editor
|
||||
}
|
||||
}
|
||||
// Update file version and CRC
|
||||
localStorage[fileSyncIndex + ".version"] = file.versionTag;
|
||||
localStorage[fileSyncIndex + ".contentCRC"] = core.crc32(file.content);
|
||||
}
|
||||
if(updateFileTitles) {
|
||||
fileManager.updateFileTitles();
|
||||
}
|
||||
localStorage[SYNC_PROVIDER_DROPBOX
|
||||
+ "lastChangeId"] = newChangeId;
|
||||
callback();
|
||||
});
|
||||
providerDown(callback);
|
||||
});
|
||||
}
|
||||
|
||||
function syncDown(callback) {
|
||||
syncDownGdrive(function() {
|
||||
syncDownDropbox(callback);
|
||||
});
|
||||
providerList = _.values(providerMap);
|
||||
providerDown(callback);
|
||||
};
|
||||
|
||||
var syncRunning = false;
|
||||
@ -316,6 +165,7 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
|
||||
function isError(error) {
|
||||
if(error !== undefined) {
|
||||
console.error(error);
|
||||
syncRunning = false;
|
||||
synchronizer.updateSyncButton();
|
||||
return true;
|
||||
@ -369,6 +219,24 @@ define(["jquery", "google-helper", "dropbox-helper", "dropbox-provider", "gdrive
|
||||
});
|
||||
};
|
||||
|
||||
synchronizer.resetSyncFlags = function() {
|
||||
_.each(providerMap, function(provider) {
|
||||
provider.useSync = false;
|
||||
});
|
||||
};
|
||||
|
||||
synchronizer.getSyncProvidersFromFile = function(fileIndex) {
|
||||
var sync = localStorage[fileIndex + ".sync"];
|
||||
var providerIdList = [];
|
||||
_.each(providerMap, function(provider) {
|
||||
if (sync.indexOf(";sync." + provider.providerId + ".") !== -1) {
|
||||
provider.useSync = true;
|
||||
providerIdList.push(provider.providerId);
|
||||
}
|
||||
});
|
||||
return providerIdList;
|
||||
};
|
||||
|
||||
synchronizer.init = function(coreModule, fileManagerModule) {
|
||||
core = coreModule;
|
||||
fileManager = fileManagerModule;
|
||||
|
Loading…
Reference in New Issue
Block a user