201 lines
9.1 KiB
JavaScript
201 lines
9.1 KiB
JavaScript
|
define([
|
||
|
"jquery",
|
||
|
"underscore",
|
||
|
"constants",
|
||
|
"utils",
|
||
|
"storage",
|
||
|
"logger",
|
||
|
"classes/Provider",
|
||
|
"settings",
|
||
|
"eventMgr",
|
||
|
"fileMgr",
|
||
|
"editor",
|
||
|
"helpers/teamserverHelper"
|
||
|
], function($, _, constants, utils, storage, logger, Provider, settings, eventMgr, fileMgr, editor, teamserverHelper) {
|
||
|
|
||
|
return function(providerId, providerName) {
|
||
|
var repo = 'teamserver';
|
||
|
|
||
|
var teamserverProvider = new Provider(providerId, providerName);
|
||
|
|
||
|
function createSyncIndex(id) {
|
||
|
return "sync." + providerId + "." + id;
|
||
|
}
|
||
|
|
||
|
var merge = settings.conflictMode == 'merge';
|
||
|
function createSyncAttributes(id, sha, content, title, discussionListJSON) {
|
||
|
discussionListJSON = discussionListJSON || '{}';
|
||
|
var syncAttributes = {};
|
||
|
syncAttributes.provider = teamserverProvider;
|
||
|
syncAttributes.id = id;
|
||
|
syncAttributes.sha = sha;
|
||
|
syncAttributes.contentCRC = utils.crc32(content);
|
||
|
syncAttributes.titleCRC = utils.crc32(title);
|
||
|
syncAttributes.discussionListCRC = utils.crc32(discussionListJSON);
|
||
|
syncAttributes.syncIndex = createSyncIndex(id);
|
||
|
if(merge === true) {
|
||
|
// Need to store the whole content for merge
|
||
|
syncAttributes.content = content;
|
||
|
syncAttributes.title = title;
|
||
|
syncAttributes.discussionList = discussionListJSON;
|
||
|
}
|
||
|
return syncAttributes;
|
||
|
}
|
||
|
|
||
|
function importFilesFromIds(ids) {
|
||
|
teamserverHelper.download(repo, ids, function(error, result) {
|
||
|
if(error) {
|
||
|
return;
|
||
|
}
|
||
|
var fileDescList = [];
|
||
|
var fileDesc;
|
||
|
_.each(result, function(file) {
|
||
|
var parsedContent = teamserverProvider.parseContent(file.content);
|
||
|
var syncLocations;
|
||
|
var syncAttributes = createSyncAttributes(file.id, file.sha, parsedContent.content, file.title, parsedContent.discussionListJSON);
|
||
|
syncLocations = {};
|
||
|
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||
|
fileDesc = fileMgr.createFile(file.title, parsedContent.content, parsedContent.discussionListJSON, syncLocations);
|
||
|
fileDescList.push(fileDesc);
|
||
|
});
|
||
|
if(fileDesc !== undefined) {
|
||
|
eventMgr.onSyncImportSuccess(fileDescList, teamserverProvider);
|
||
|
fileMgr.selectFile(fileDesc);
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
teamserverProvider.importFiles = function() {
|
||
|
teamserverHelper.picker(repo, 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);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
teamserverProvider.exportFile = function(event, title, content, discussionListJSON, callback) {
|
||
|
var data = teamserverProvider.serializeContent(content, discussionListJSON);
|
||
|
teamserverHelper.upload(repo, undefined, title, data, function(error, result) {
|
||
|
if(error) {
|
||
|
return callback(error);
|
||
|
}
|
||
|
var syncAttributes = createSyncAttributes(result.id, result.sha, content, title, discussionListJSON);
|
||
|
callback(undefined, syncAttributes);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
teamserverProvider.syncUp = function(content, contentCRC, title, titleCRC, discussionList, discussionListCRC, syncAttributes, callback) {
|
||
|
if(
|
||
|
(syncAttributes.contentCRC == contentCRC) && // Content CRC hasn't changed
|
||
|
(syncAttributes.titleCRC == titleCRC) && // Title CRC hasn't changed
|
||
|
(syncAttributes.discussionListCRC == discussionListCRC) // Discussion list CRC hasn't changed
|
||
|
) {
|
||
|
return callback(undefined, false);
|
||
|
}
|
||
|
|
||
|
var data = teamserverProvider.serializeContent(content, discussionList);
|
||
|
teamserverHelper.upload(repo, syncAttributes.id, title, data, function(error, result) {
|
||
|
if(error) {
|
||
|
callback(error, true);
|
||
|
return;
|
||
|
}
|
||
|
syncAttributes.etag = result.etag;
|
||
|
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);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
teamserverProvider.syncDown = function(callback) {
|
||
|
var lastChangeId = parseInt(storage["teamserver.lastChangeId"], 10);
|
||
|
teamserverHelper.checkChanges(repo, lastChangeId, function(error, changes, newChangeId) {
|
||
|
if(error) {
|
||
|
return callback(error);
|
||
|
}
|
||
|
var interestingChanges = [];
|
||
|
_.each(changes, function(change) {
|
||
|
var syncIndex = createSyncIndex(change.id);
|
||
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||
|
var syncAttributes = fileDesc && fileDesc.syncLocations[syncIndex];
|
||
|
if(!syncAttributes) {
|
||
|
return;
|
||
|
}
|
||
|
// Store fileDesc and syncAttributes references to avoid 2 times search
|
||
|
change.fileDesc = fileDesc;
|
||
|
change.syncAttributes = syncAttributes;
|
||
|
// Delete
|
||
|
if(change.deleted === true) {
|
||
|
interestingChanges.push(change);
|
||
|
return;
|
||
|
}
|
||
|
// Modify
|
||
|
if(syncAttributes.sha != change.sha) {
|
||
|
interestingChanges.push(change);
|
||
|
}
|
||
|
});
|
||
|
teamserverHelper.downloadContent(repo, interestingChanges, function(error, changes) {
|
||
|
if(error) {
|
||
|
return callback(error);
|
||
|
}
|
||
|
function mergeChange() {
|
||
|
if(changes.length === 0) {
|
||
|
storage["teamserver.lastChangeId"] = newChangeId;
|
||
|
return callback();
|
||
|
}
|
||
|
var change = changes.pop();
|
||
|
var fileDesc = change.fileDesc;
|
||
|
var syncAttributes = change.syncAttributes;
|
||
|
// File deleted
|
||
|
if(change.deleted === true) {
|
||
|
eventMgr.onError('"' + fileDesc.title + '" has been removed from ' + providerName + '.');
|
||
|
fileDesc.removeSyncLocation(syncAttributes);
|
||
|
return eventMgr.onSyncRemoved(fileDesc, syncAttributes);
|
||
|
}
|
||
|
var parsedContent = teamserverProvider.parseContent(change.content);
|
||
|
var remoteContent = parsedContent.content;
|
||
|
var remoteTitle = change.title;
|
||
|
var remoteDiscussionListJSON = parsedContent.discussionListJSON;
|
||
|
var remoteDiscussionList = parsedContent.discussionList;
|
||
|
var remoteCRC = teamserverProvider.syncMerge(fileDesc, syncAttributes, remoteContent, remoteTitle, remoteDiscussionList, remoteDiscussionListJSON);
|
||
|
|
||
|
// Update syncAttributes
|
||
|
syncAttributes.sha = change.sha;
|
||
|
if(merge === true) {
|
||
|
// Need to store the whole content for merge
|
||
|
syncAttributes.content = remoteContent;
|
||
|
syncAttributes.title = remoteTitle;
|
||
|
syncAttributes.discussionList = remoteDiscussionListJSON;
|
||
|
}
|
||
|
syncAttributes.contentCRC = remoteCRC.contentCRC;
|
||
|
syncAttributes.titleCRC = remoteCRC.titleCRC;
|
||
|
syncAttributes.discussionListCRC = remoteCRC.discussionListCRC;
|
||
|
utils.storeAttributes(syncAttributes);
|
||
|
setTimeout(mergeChange, 5);
|
||
|
}
|
||
|
setTimeout(mergeChange, 5);
|
||
|
});
|
||
|
});
|
||
|
};
|
||
|
|
||
|
return teamserverProvider;
|
||
|
};
|
||
|
});
|