Implement merge in sync providers
This commit is contained in:
parent
533558945b
commit
0e5f198270
@ -88,7 +88,7 @@ define([
|
||||
});
|
||||
Object.defineProperty(this, 'discussionListJSON', {
|
||||
get: function() {
|
||||
return storage[this.fileIndex + ".discussionList"];
|
||||
return storage[this.fileIndex + ".discussionList"] || '{}';
|
||||
},
|
||||
set: function(discussionList) {
|
||||
this._discussionList = JSON.parse(discussionList);
|
||||
|
@ -1,10 +1,126 @@
|
||||
define(function() {
|
||||
|
||||
define([
|
||||
'underscore',
|
||||
'utils',
|
||||
'settings',
|
||||
'eventMgr',
|
||||
'fileMgr',
|
||||
'diff_match_patch_uncompressed',
|
||||
'jsondiffpatch',
|
||||
], function(_, utils, settings, eventMgr, fileMgr, diff_match_patch, jsondiffpatch) {
|
||||
|
||||
function Provider(providerId, providerName) {
|
||||
this.providerId = providerId;
|
||||
this.providerName = providerName;
|
||||
this.isPublishEnabled = true;
|
||||
}
|
||||
|
||||
|
||||
// Parse and check a JSON discussion list
|
||||
Provider.prototype.parseDiscussionList = function(discussionListJSON) {
|
||||
try {
|
||||
var discussionList = JSON.parse(discussionListJSON);
|
||||
_.each(discussionList, function(discussion, discussionIndex) {
|
||||
if(
|
||||
(discussion.discussionIndex != discussionIndex) ||
|
||||
(!_.isNumber(discussion.selectionStart)) ||
|
||||
(!_.isNumber(discussion.selectionEnd))
|
||||
) {
|
||||
throw 'invalid';
|
||||
}
|
||||
discussion.commentList.forEach(function(comment) {
|
||||
if(
|
||||
(!_.isString(comment.author)) ||
|
||||
(!_.isString(comment.content))
|
||||
) {
|
||||
throw 'invalid';
|
||||
}
|
||||
});
|
||||
});
|
||||
return discussionList;
|
||||
}
|
||||
catch(e) {
|
||||
}
|
||||
};
|
||||
|
||||
Provider.prototype.serializeContent = function(content, discussionList) {
|
||||
if(_.size(discussionList) !== 0) {
|
||||
return content + '<!--se_discussion_list:' + discussionList + '-->';
|
||||
}
|
||||
return content;
|
||||
};
|
||||
|
||||
Provider.prototype.parseSerializedContent = function(content) {
|
||||
var discussionList = '{}';
|
||||
var discussionExtractor = /<!--se_discussion_list:([\s\S]+)-->$/.exec(content);
|
||||
if(discussionExtractor && this.parseDiscussionList(discussionExtractor[1])) {
|
||||
content = content.substring(0, discussionExtractor.index);
|
||||
discussionList = discussionExtractor[1];
|
||||
}
|
||||
return {
|
||||
content: content,
|
||||
discussionList: discussionList
|
||||
};
|
||||
};
|
||||
|
||||
var diffMatchPatch = new diff_match_patch();
|
||||
var jsonDiffPatch = jsondiffpatch.create({
|
||||
objectHash: function(obj) {
|
||||
return JSON.stringify(obj);
|
||||
},
|
||||
arrays: {
|
||||
detectMove: false,
|
||||
},
|
||||
textDiff: {
|
||||
minLength: 9999999
|
||||
}
|
||||
});
|
||||
|
||||
var merge = settings.conflictMode == 'merge';
|
||||
Provider.prototype.merge = function(localContent, remoteContent, localTitle, remoteTitle, localDiscussionList, remoteDiscussionList, syncAttributes) {
|
||||
|
||||
// Local/Remote CRCs
|
||||
var localContentCRC = utils.crc32(localContent);
|
||||
var localTitleCRC = utils.crc32(localTitle);
|
||||
var localDiscussionListCRC = utils.crc32(localDiscussionList);
|
||||
var remoteContentCRC = utils.crc32(remoteContent);
|
||||
var remoteTitleCRC = utils.crc32(remoteTitle);
|
||||
var remoteDiscussionListCRC = utils.crc32(remoteDiscussionList);
|
||||
|
||||
// Check content
|
||||
var contentChanged = localContent != remoteContent;
|
||||
var localContentChanged = syncAttributes.contentCRC != localContentCRC;
|
||||
var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC;
|
||||
var contentConflict = contentChanged && localContentChanged && remoteContentChanged;
|
||||
|
||||
// Check title
|
||||
syncAttributes.titleCRC = syncAttributes.titleCRC || localTitleCRC; // Not synchronized with Dropbox
|
||||
var titleChanged = localTitle != remoteTitle;
|
||||
var localTitleChanged = syncAttributes.titleCRC != localTitleCRC;
|
||||
var remoteTitleChanged = syncAttributes.titleCRC != remoteTitleCRC;
|
||||
var titleConflict = titleChanged && localTitleChanged && remoteTitleChanged;
|
||||
|
||||
// Check discussionList
|
||||
var discussionListChanged = localDiscussionList != remoteDiscussionList;
|
||||
var localDiscussionListChanged = syncAttributes.discussionListCRC != localDiscussionListCRC;
|
||||
var remoteDiscussionListChanged = syncAttributes.discussionListCRC != remoteDiscussionListCRC;
|
||||
var discussionListConflict = discussionListChanged && localDiscussionListChanged && remoteDiscussionListChanged;
|
||||
|
||||
// Conflict detection
|
||||
if(
|
||||
(!merge && (contentConflict || titleConflict || discussionListConflict)) ||
|
||||
(contentConflict && syncAttributes.content === undefined) ||
|
||||
(titleConflict && syncAttributes.title === undefined) ||
|
||||
(discussionListConflict && syncAttributes.discussionList === undefined)
|
||||
) {
|
||||
fileMgr.createFile(localTitle + " (backup)", localContent);
|
||||
eventMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||
}
|
||||
else {
|
||||
if(contentConflict === true) {
|
||||
var patch = diffMatchPatch.patch_make(syncAttributes.content, localContent);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return Provider;
|
||||
});
|
||||
});
|
||||
|
@ -11,18 +11,6 @@ define([
|
||||
'MutationObservers',
|
||||
'libs/prism-markdown'
|
||||
], function ($, _, settings, eventMgr, Prism, diff_match_patch, jsondiffpatch, crel) {
|
||||
var diffMatchPatch = new diff_match_patch();
|
||||
var jsonDiffPatch = jsondiffpatch.create({
|
||||
objectHash: function(obj) {
|
||||
return JSON.stringify(obj);
|
||||
},
|
||||
arrays: {
|
||||
detectMove: false,
|
||||
},
|
||||
textDiff: {
|
||||
minLength: 9999999
|
||||
}
|
||||
});
|
||||
|
||||
function strSplice(str, i, remove, add) {
|
||||
remove = +remove || 0;
|
||||
@ -86,6 +74,19 @@ define([
|
||||
});
|
||||
}
|
||||
|
||||
var diffMatchPatch = new diff_match_patch();
|
||||
var jsonDiffPatch = jsondiffpatch.create({
|
||||
objectHash: function(obj) {
|
||||
return JSON.stringify(obj);
|
||||
},
|
||||
arrays: {
|
||||
detectMove: false,
|
||||
},
|
||||
textDiff: {
|
||||
minLength: 9999999
|
||||
}
|
||||
});
|
||||
|
||||
var previousTextContent;
|
||||
var currentMode;
|
||||
editor.undoManager = (function() {
|
||||
|
@ -111,7 +111,7 @@ define([
|
||||
refreshDiscussions();
|
||||
};
|
||||
|
||||
comments.onContentChanged = function(fileDesc, content) {
|
||||
comments.onContentChanged = function(fileDesc) {
|
||||
currentFileDesc === fileDesc && refreshDiscussions();
|
||||
};
|
||||
|
||||
@ -359,7 +359,7 @@ define([
|
||||
|
||||
// Focus on textarea
|
||||
context.$contentInputElt.focus().val(previousContent);
|
||||
}).on('hide.bs.popover', '#wmd-input > .editor-margin', function(evt) {
|
||||
}).on('hide.bs.popover', '#wmd-input > .editor-margin', function() {
|
||||
if(!currentContext) {
|
||||
return;
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ define([
|
||||
core.initEditor(fileDesc);
|
||||
};
|
||||
|
||||
fileMgr.createFile = function(title, content, syncLocations, isTemporary) {
|
||||
fileMgr.createFile = function(title, content, discussionListJSON, syncLocations, isTemporary) {
|
||||
content = content !== undefined ? content : settings.defaultContent;
|
||||
if(!title) {
|
||||
// Create a file title
|
||||
@ -86,6 +86,7 @@ define([
|
||||
|
||||
// Create the file descriptor
|
||||
var fileDesc = new FileDescriptor(fileIndex, title, syncLocations);
|
||||
discussionListJSON && (fileDesc.discussionListJSON = discussionListJSON);
|
||||
|
||||
// Add the index to the file list
|
||||
if(!isTemporary) {
|
||||
|
@ -2,11 +2,12 @@ define([
|
||||
"underscore",
|
||||
"utils",
|
||||
"storage",
|
||||
"settings",
|
||||
"classes/Provider",
|
||||
"eventMgr",
|
||||
"fileMgr",
|
||||
"helpers/dropboxHelper"
|
||||
], function(_, utils, storage, Provider, eventMgr, fileMgr, dropboxHelper) {
|
||||
], function(_, utils, storage, settings, Provider, eventMgr, fileMgr, dropboxHelper) {
|
||||
|
||||
var PROVIDER_DROPBOX = "dropbox";
|
||||
|
||||
@ -55,7 +56,8 @@ define([
|
||||
var syncAttributes = createSyncAttributes(file.path, file.versionTag, file.content);
|
||||
var syncLocations = {};
|
||||
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||
var fileDesc = fileMgr.createFile(file.name, file.content, syncLocations);
|
||||
var parsingResult = dropboxProvider.parseSerializedContent(file.content);
|
||||
var fileDesc = fileMgr.createFile(file.name, parsingResult.content, parsingResult.discussionList, syncLocations);
|
||||
fileMgr.selectFile(fileDesc);
|
||||
fileDescList.push(fileDesc);
|
||||
});
|
||||
@ -76,8 +78,7 @@ define([
|
||||
var syncIndex = createSyncIndex(path);
|
||||
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||
if(fileDesc !== undefined) {
|
||||
eventMgr.onError('"' + fileDesc.title + '" was already imported.');
|
||||
return;
|
||||
return eventMgr.onError('"' + fileDesc.title + '" was already imported.');
|
||||
}
|
||||
importPaths.push(path);
|
||||
});
|
||||
@ -89,8 +90,7 @@ define([
|
||||
var path = utils.getInputTextValue("#input-sync-export-dropbox-path", event);
|
||||
path = checkPath(path);
|
||||
if(path === undefined) {
|
||||
callback(true);
|
||||
return;
|
||||
return callback(true);
|
||||
}
|
||||
// Check that file is not synchronized with another one
|
||||
var syncIndex = createSyncIndex(path);
|
||||
@ -98,33 +98,39 @@ define([
|
||||
if(fileDesc !== undefined) {
|
||||
var existingTitle = fileDesc.title;
|
||||
eventMgr.onError('File path is already synchronized with "' + existingTitle + '".');
|
||||
callback(true);
|
||||
return;
|
||||
return callback(true);
|
||||
}
|
||||
dropboxHelper.upload(path, content, function(error, result) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
return;
|
||||
return callback(error);
|
||||
}
|
||||
var syncAttributes = createSyncAttributes(result.path, result.versionTag, content);
|
||||
callback(undefined, syncAttributes);
|
||||
});
|
||||
};
|
||||
|
||||
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;
|
||||
var merge = settings.conflictMode == 'merge';
|
||||
dropboxProvider.syncUp = function(content, contentCRC, title, titleCRC, discussionList, discussionListCRC, syncAttributes, callback) {
|
||||
if(
|
||||
(syncAttributes.contentCRC == contentCRC) && // Content CRC hasn't changed
|
||||
(syncAttributes.discussionListCRC == discussionListCRC) // Discussion list CRC hasn't changed
|
||||
) {
|
||||
return callback(undefined, false);
|
||||
}
|
||||
dropboxHelper.upload(syncAttributes.path, uploadContent, function(error, result) {
|
||||
var uploadedContent = dropboxProvider.serializeContent(content, discussionList);
|
||||
dropboxHelper.upload(syncAttributes.path, uploadedContent, function(error, result) {
|
||||
if(error) {
|
||||
callback(error, true);
|
||||
return;
|
||||
return callback(error, true);
|
||||
}
|
||||
syncAttributes.version = result.versionTag;
|
||||
syncAttributes.contentCRC = uploadContentCRC;
|
||||
if(merge === true) {
|
||||
// Need to store the whole content for merge
|
||||
syncAttributes.content = content;
|
||||
syncAttributes.discussionList = discussionList;
|
||||
}
|
||||
syncAttributes.contentCRC = contentCRC;
|
||||
syncAttributes.discussionListCRC = discussionListCRC;
|
||||
|
||||
callback(undefined, true);
|
||||
});
|
||||
};
|
||||
@ -133,8 +139,7 @@ define([
|
||||
var lastChangeId = storage[PROVIDER_DROPBOX + ".lastChangeId"];
|
||||
dropboxHelper.checkChanges(lastChangeId, function(error, changes, newChangeId) {
|
||||
if(error) {
|
||||
callback(error);
|
||||
return;
|
||||
return callback(error);
|
||||
}
|
||||
var interestingChanges = [];
|
||||
_.each(changes, function(change) {
|
||||
@ -164,8 +169,7 @@ define([
|
||||
var syncAttributes = change.syncAttributes;
|
||||
var syncIndex = syncAttributes.syncIndex;
|
||||
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||
// No file corresponding (file may have been deleted
|
||||
// locally)
|
||||
// No file corresponding (file may have been deleted locally)
|
||||
if(fileDesc === undefined) {
|
||||
return;
|
||||
}
|
||||
@ -174,15 +178,22 @@ define([
|
||||
if(change.wasRemoved === true) {
|
||||
eventMgr.onError('"' + localTitle + '" has been removed from Dropbox.');
|
||||
fileDesc.removeSyncLocation(syncAttributes);
|
||||
eventMgr.onSyncRemoved(fileDesc, syncAttributes);
|
||||
return;
|
||||
return eventMgr.onSyncRemoved(fileDesc, syncAttributes);
|
||||
}
|
||||
var localContent = fileDesc.content;
|
||||
var localContentChanged = syncAttributes.contentCRC != utils.crc32(localContent);
|
||||
var localDiscussionList = fileDesc.discussionListJSON;
|
||||
var localDiscussionListChanged = syncAttributes.discussionListCRC != utils.crc32(localDiscussionList);
|
||||
var file = change.stat;
|
||||
var remoteContentCRC = utils.crc32(file.content);
|
||||
var parsingResult = dropboxProvider.parseSerializedContent(file.content);
|
||||
var remoteContent = parsingResult.content;
|
||||
var remoteDiscussionList = parsingResult.discussionList;
|
||||
var remoteContentCRC = utils.crc32(remoteContent);
|
||||
var remoteContentChanged = syncAttributes.contentCRC != remoteContentCRC;
|
||||
var fileContentChanged = localContent != file.content;
|
||||
var remoteDiscussionListCRC = utils.crc32(remoteDiscussionList);
|
||||
var remoteDiscussionListChanged = syncAttributes.discussionListCRC != remoteDiscussionListCRC;
|
||||
var fileContentChanged = localContent != remoteContent;
|
||||
var fileDiscussionListChanged = localDiscussionList != remoteDiscussionList;
|
||||
// Conflict detection
|
||||
if(fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
|
||||
fileMgr.createFile(localTitle + " (backup)", localContent);
|
||||
@ -211,8 +222,7 @@ define([
|
||||
dropboxProvider.publish = function(publishAttributes, frontMatter, title, content, callback) {
|
||||
var path = checkPath(publishAttributes.path);
|
||||
if(path === undefined) {
|
||||
callback(true);
|
||||
return;
|
||||
return callback(true);
|
||||
}
|
||||
dropboxHelper.upload(path, content, callback);
|
||||
};
|
||||
|
@ -56,7 +56,8 @@ define([
|
||||
syncAttributes.isRealtime = file.isRealtime;
|
||||
var syncLocations = {};
|
||||
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||
fileDesc = fileMgr.createFile(file.title, file.content, syncLocations);
|
||||
var parsingResult = gdriveProvider.parseSerializedContent(file.content);
|
||||
fileDesc = fileMgr.createFile(file.title, parsingResult.content, parsingResult.discussionList, syncLocations);
|
||||
fileDescList.push(fileDesc);
|
||||
});
|
||||
if(fileDesc !== undefined) {
|
||||
@ -122,37 +123,48 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
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;
|
||||
var merge = settings.conflictMode == 'merge';
|
||||
gdriveProvider.syncUp = function(content, contentCRC, title, titleCRC, discussionList, discussionListCRC, syncAttributes, callback) {
|
||||
if(
|
||||
(syncAttributes.contentCRC == contentCRC) && // Content CRC hasn't changed
|
||||
(syncAttributes.titleCRC == titleCRC) && // Content CRC hasn't changed
|
||||
(syncAttributes.discussionListCRC == discussionListCRC) // Discussion list CRC hasn't changed
|
||||
) {
|
||||
return callback(undefined, false);
|
||||
}
|
||||
googleHelper.upload(syncAttributes.id, undefined, uploadTitle, uploadContent, undefined, syncAttributes.etag, accountId, function(error, result) {
|
||||
var uploadedContent = gdriveProvider.serializeContent(content, discussionList);
|
||||
googleHelper.upload(syncAttributes.id, undefined, title, uploadedContent, undefined, syncAttributes.etag, accountId, function(error, result) {
|
||||
if(error) {
|
||||
callback(error, true);
|
||||
return;
|
||||
}
|
||||
syncAttributes.etag = result.etag;
|
||||
syncAttributes.contentCRC = uploadContentCRC;
|
||||
syncAttributes.titleCRC = uploadTitleCRC;
|
||||
if(merge === true) {
|
||||
// Need to store the whole content for merge
|
||||
syncAttributes.content = content;
|
||||
syncAttributes.title = title;
|
||||
syncAttributes.discussionList = discussionList;
|
||||
}
|
||||
syncAttributes.contentCRC = contentCRC;
|
||||
syncAttributes.titleCRC = titleCRC;
|
||||
syncAttributes.discussionListCRC = discussionListCRC;
|
||||
callback(undefined, true);
|
||||
});
|
||||
};
|
||||
|
||||
gdriveProvider.syncUpRealtime = function(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, callback) {
|
||||
gdriveProvider.syncUpRealtime = function(content, contentCRC, title, titleCRC, discussionList, discussionListCRC, syncAttributes, callback) {
|
||||
// Skip if title CRC has not changed
|
||||
if(uploadTitleCRC == syncAttributes.titleCRC) {
|
||||
if(titleCRC == syncAttributes.titleCRC) {
|
||||
callback(undefined, false);
|
||||
return;
|
||||
}
|
||||
googleHelper.rename(syncAttributes.id, uploadTitle, accountId, function(error, result) {
|
||||
googleHelper.rename(syncAttributes.id, title, accountId, function(error, result) {
|
||||
if(error) {
|
||||
callback(error, true);
|
||||
return;
|
||||
}
|
||||
syncAttributes.etag = result.etag;
|
||||
syncAttributes.titleCRC = uploadTitleCRC;
|
||||
syncAttributes.titleCRC = titleCRC;
|
||||
callback(undefined, true);
|
||||
});
|
||||
};
|
||||
@ -646,7 +658,7 @@ define([
|
||||
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);
|
||||
var fileDesc = fileMgr.createFile(file.title, file.content, undefined, syncLocations);
|
||||
fileMgr.selectFile(fileDesc);
|
||||
eventMgr.onMessage('"' + file.title + '" created successfully on ' + providerName + '.');
|
||||
});
|
||||
|
@ -13,6 +13,7 @@ define([
|
||||
maxWidth: 960,
|
||||
defaultContent: "\n\n\n> Written with [StackEdit](" + constants.MAIN_URL + ").",
|
||||
commitMsg: "Published with " + constants.MAIN_URL,
|
||||
conflictMode: 'merge',
|
||||
gdriveMultiAccount: 1,
|
||||
gdriveFullAccess: true,
|
||||
dropboxFullAccess: true,
|
||||
|
@ -126,10 +126,10 @@ define([
|
||||
if(error) {
|
||||
return;
|
||||
}
|
||||
var fileDesc = fileMgr.createFile(title, content, undefined, true);
|
||||
var fileDesc = fileMgr.createFile(title, content, undefined, undefined, true);
|
||||
fileMgr.selectFile(fileDesc);
|
||||
});
|
||||
});
|
||||
|
||||
return sharing;
|
||||
});
|
||||
});
|
||||
|
@ -1041,7 +1041,6 @@ a {
|
||||
font-family: "PT Sans", sans-serif;
|
||||
line-height: @editor-line-weight;
|
||||
letter-spacing: normal;
|
||||
font-size: @font-size-base;
|
||||
border-radius: 0;
|
||||
color: @tertiary-color-dark;
|
||||
.box-shadow(none);
|
||||
|
@ -47,12 +47,12 @@ define([
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// AutoSync configuration
|
||||
_.each(providerMap, function(provider) {
|
||||
provider.autosyncConfig = utils.retrieveIgnoreError(provider.providerId + ".autosyncConfig") || {};
|
||||
});
|
||||
|
||||
|
||||
// Returns true if at least one file has synchronized location
|
||||
synchronizer.hasSync = function(provider) {
|
||||
return _.some(fileSystem, function(fileDesc) {
|
||||
@ -72,6 +72,8 @@ define([
|
||||
var uploadContentCRC;
|
||||
var uploadTitle;
|
||||
var uploadTitleCRC;
|
||||
var uploadDiscussionList;
|
||||
var uploadDiscussionListCRC;
|
||||
function locationUp(callback) {
|
||||
|
||||
// No more synchronized location for this document
|
||||
@ -90,21 +92,30 @@ define([
|
||||
}
|
||||
|
||||
// Use the specified provider to perform the upload
|
||||
providerSyncUpFunction(uploadContent, uploadContentCRC, uploadTitle, uploadTitleCRC, syncAttributes, function(error, uploadFlag) {
|
||||
if(uploadFlag === true) {
|
||||
// If uploadFlag is true, request another upload cycle
|
||||
uploadCycle = true;
|
||||
providerSyncUpFunction(
|
||||
uploadContent,
|
||||
uploadContentCRC,
|
||||
uploadTitle,
|
||||
uploadTitleCRC,
|
||||
uploadDiscussionList,
|
||||
uploadTitleCRC,
|
||||
uploadDiscussionListCRC,
|
||||
function(error, uploadFlag) {
|
||||
if(uploadFlag === true) {
|
||||
// If uploadFlag is true, request another upload cycle
|
||||
uploadCycle = true;
|
||||
}
|
||||
if(error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
if(uploadFlag) {
|
||||
// Update syncAttributes in storage
|
||||
utils.storeAttributes(syncAttributes);
|
||||
}
|
||||
locationUp(callback);
|
||||
}
|
||||
if(error) {
|
||||
callback(error);
|
||||
return;
|
||||
}
|
||||
if(uploadFlag) {
|
||||
// Update syncAttributes in storage
|
||||
utils.storeAttributes(syncAttributes);
|
||||
}
|
||||
locationUp(callback);
|
||||
});
|
||||
);
|
||||
}
|
||||
|
||||
// Recursive function to upload multiple files
|
||||
@ -130,6 +141,8 @@ define([
|
||||
uploadContentCRC = utils.crc32(uploadContent);
|
||||
uploadTitle = fileDesc.title;
|
||||
uploadTitleCRC = utils.crc32(uploadTitle);
|
||||
uploadDiscussionList = fileDesc.discussionListJSON;
|
||||
uploadDiscussionListCRC = utils.crc32(uploadDiscussionList);
|
||||
locationUp(callback);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user