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