2013-04-21 00:07:27 +00:00
|
|
|
define(["jquery", "core", "dropbox-provider", "gdrive-provider", "underscore"], function($, core) {
|
2013-04-01 16:46:48 +00:00
|
|
|
var synchronizer = {};
|
2013-04-01 23:12:28 +00:00
|
|
|
|
2013-04-21 00:07:27 +00:00
|
|
|
// Create a map with providerId: providerObject
|
2013-04-20 00:14:20 +00:00
|
|
|
var providerMap = _.chain(arguments)
|
|
|
|
.map(function(argument) {
|
2013-04-20 17:40:05 +00:00
|
|
|
return argument && argument.providerId && [argument.providerId, argument];
|
2013-04-20 00:14:20 +00:00
|
|
|
}).compact().object().value();
|
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
// Used to know if user can force synchronization
|
|
|
|
var uploadPending = false;
|
2013-04-01 23:12:28 +00:00
|
|
|
|
2013-04-10 23:13:31 +00:00
|
|
|
// Allows external modules to update uploadPending flag
|
2013-04-10 18:14:59 +00:00
|
|
|
synchronizer.notifyChange = function(fileIndex) {
|
2013-04-01 23:12:28 +00:00
|
|
|
// Check that file has synchronized locations
|
2013-04-10 23:13:31 +00:00
|
|
|
if(localStorage[fileIndex + ".sync"].length !== 1) {
|
|
|
|
uploadPending = true;
|
|
|
|
synchronizer.updateSyncButton();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Used to enable/disable the synchronization button
|
|
|
|
synchronizer.updateSyncButton = function() {
|
|
|
|
if(syncRunning === true || uploadPending === false || core.isOffline) {
|
|
|
|
$(".action-force-sync").addClass("disabled");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$(".action-force-sync").removeClass("disabled");
|
2013-04-01 16:46:48 +00:00
|
|
|
}
|
|
|
|
};
|
2013-04-21 14:36:53 +00:00
|
|
|
// Run updateSyncButton on online/offline event
|
|
|
|
core.addOfflineListener(synchronizer.updateSyncButton);
|
2013-04-01 16:46:48 +00:00
|
|
|
|
2013-04-10 23:13:31 +00:00
|
|
|
// Force the synchronization
|
|
|
|
synchronizer.forceSync = function() {
|
|
|
|
lastSync = 0;
|
|
|
|
synchronizer.sync();
|
|
|
|
};
|
|
|
|
|
2013-04-01 16:46:48 +00:00
|
|
|
// Recursive function to upload a single file on multiple locations
|
2013-04-10 18:14:59 +00:00
|
|
|
var uploadFileSyncIndexList = [];
|
|
|
|
var uploadContent = undefined;
|
|
|
|
var uploadContentCRC = undefined;
|
|
|
|
var uploadTitle = undefined;
|
|
|
|
var uploadTitleCRC = undefined;
|
|
|
|
function locationUp(callback) {
|
|
|
|
|
|
|
|
// No more synchronized location for this document
|
|
|
|
if (uploadFileSyncIndexList.length === 0) {
|
|
|
|
fileUp(callback);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dequeue a synchronized location
|
2013-04-20 00:14:20 +00:00
|
|
|
var syncIndex = uploadFileSyncIndexList.pop();
|
2013-04-20 17:40:05 +00:00
|
|
|
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;
|
2013-04-21 00:51:07 +00:00
|
|
|
// When page is refreshed, this flag is false but should be true here
|
2013-04-20 17:40:05 +00:00
|
|
|
uploadPending = true;
|
|
|
|
}
|
2013-04-20 00:14:20 +00:00
|
|
|
if(error) {
|
|
|
|
callback(error);
|
2013-04-07 15:22:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-04-20 17:40:05 +00:00
|
|
|
if(uploadFlag) {
|
|
|
|
// Update syncAttributes in localStorage
|
|
|
|
localStorage[syncIndex] = JSON.stringify(syncAttributes);
|
2013-04-01 16:46:48 +00:00
|
|
|
}
|
2013-04-16 15:02:24 +00:00
|
|
|
locationUp(callback);
|
2013-04-20 17:40:05 +00:00
|
|
|
}
|
|
|
|
);
|
2013-04-01 16:46:48 +00:00
|
|
|
}
|
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
// Recursive function to upload multiple files
|
|
|
|
var uploadFileIndexList = [];
|
|
|
|
function fileUp(callback) {
|
|
|
|
|
|
|
|
// No more fileIndex to synchronize
|
|
|
|
if (uploadFileIndexList.length === 0) {
|
|
|
|
syncUp(callback);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Dequeue a fileIndex
|
|
|
|
var fileIndex = uploadFileIndexList.pop();
|
|
|
|
var fileSyncIndexes = localStorage[fileIndex + ".sync"];
|
2013-04-20 17:40:05 +00:00
|
|
|
if(fileSyncIndexes.length === 1) {
|
2013-04-10 18:14:59 +00:00
|
|
|
fileUp(callback);
|
2013-04-01 16:46:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
// Get document title/content
|
|
|
|
uploadContent = localStorage[fileIndex + ".content"];
|
|
|
|
uploadContentCRC = core.crc32(uploadContent);
|
|
|
|
uploadTitle = localStorage[fileIndex + ".title"];
|
|
|
|
uploadTitleCRC = core.crc32(uploadTitle);
|
2013-04-01 16:46:48 +00:00
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
// Parse the list of synchronized locations associated to the document
|
2013-04-20 00:14:20 +00:00
|
|
|
uploadFileSyncIndexList = _.compact(fileSyncIndexes.split(";"));
|
2013-04-10 18:14:59 +00:00
|
|
|
locationUp(callback);
|
|
|
|
}
|
2013-04-01 16:46:48 +00:00
|
|
|
|
2013-04-21 00:07:27 +00:00
|
|
|
// Entry point for up synchronization (upload changes)
|
2013-04-10 18:14:59 +00:00
|
|
|
var uploadCycle = false;
|
|
|
|
function syncUp(callback) {
|
|
|
|
if(uploadCycle === true) {
|
|
|
|
// New upload cycle
|
|
|
|
uploadCycle = false;
|
2013-04-20 17:40:05 +00:00
|
|
|
uploadFileIndexList = _.compact(localStorage["file.list"].split(";"));
|
2013-04-10 18:14:59 +00:00
|
|
|
fileUp(callback);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
callback();
|
|
|
|
}
|
|
|
|
}
|
2013-04-01 16:46:48 +00:00
|
|
|
|
2013-04-20 17:40:05 +00:00
|
|
|
// Recursive function to download changes from multiple providers
|
|
|
|
var providerList = [];
|
|
|
|
function providerDown(callback) {
|
|
|
|
if(providerList.length === 0) {
|
2013-04-07 15:22:13 +00:00
|
|
|
callback();
|
2013-04-21 00:07:27 +00:00
|
|
|
return;
|
2013-04-07 15:22:13 +00:00
|
|
|
}
|
2013-04-20 17:40:05 +00:00
|
|
|
var provider = providerList.pop();
|
|
|
|
provider.syncDown(function(error) {
|
|
|
|
if(error) {
|
2013-04-16 15:02:24 +00:00
|
|
|
callback(error);
|
2013-04-07 15:22:13 +00:00
|
|
|
return;
|
|
|
|
}
|
2013-04-20 17:40:05 +00:00
|
|
|
providerDown(callback);
|
2013-04-07 15:22:13 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2013-04-21 00:07:27 +00:00
|
|
|
// Entry point for down synchronization (download changes)
|
2013-04-01 16:46:48 +00:00
|
|
|
function syncDown(callback) {
|
2013-04-20 17:40:05 +00:00
|
|
|
providerList = _.values(providerMap);
|
|
|
|
providerDown(callback);
|
2013-04-01 16:46:48 +00:00
|
|
|
};
|
2013-04-21 00:07:27 +00:00
|
|
|
|
|
|
|
// Main entry point for synchronization
|
2013-04-01 16:46:48 +00:00
|
|
|
var syncRunning = false;
|
|
|
|
var lastSync = 0;
|
|
|
|
synchronizer.sync = function() {
|
|
|
|
// If sync is already running or timeout is not reached or offline
|
2013-04-02 18:42:47 +00:00
|
|
|
if (syncRunning || lastSync + SYNC_PERIOD > core.currentTime || core.isOffline) {
|
2013-04-01 16:46:48 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
syncRunning = true;
|
2013-04-10 18:14:59 +00:00
|
|
|
uploadCycle = true;
|
2013-04-02 18:42:47 +00:00
|
|
|
lastSync = core.currentTime;
|
2013-04-10 18:14:59 +00:00
|
|
|
synchronizer.updateSyncButton();
|
|
|
|
|
|
|
|
function isError(error) {
|
|
|
|
if(error !== undefined) {
|
2013-04-20 17:40:05 +00:00
|
|
|
console.error(error);
|
2013-04-10 18:14:59 +00:00
|
|
|
syncRunning = false;
|
|
|
|
synchronizer.updateSyncButton();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2013-04-01 16:46:48 +00:00
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
syncDown(function(error) {
|
|
|
|
if(isError(error)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
syncUp(function(error) {
|
|
|
|
if(isError(error)) {
|
|
|
|
return;
|
|
|
|
}
|
2013-04-01 16:46:48 +00:00
|
|
|
syncRunning = false;
|
2013-04-10 18:14:59 +00:00
|
|
|
uploadPending = false;
|
2013-04-01 16:46:48 +00:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
2013-04-21 14:36:53 +00:00
|
|
|
// Run sync function periodically
|
2013-05-04 00:05:58 +00:00
|
|
|
if(viewerMode === false) {
|
|
|
|
core.addPeriodicCallback(synchronizer.sync);
|
|
|
|
}
|
2013-04-01 23:12:28 +00:00
|
|
|
|
2013-04-20 00:14:20 +00:00
|
|
|
// Used to populate the "Manage synchronization" dialog
|
|
|
|
var lineTemplate = ['<div class="input-prepend input-append">',
|
|
|
|
'<span class="add-on" title="<%= provider.providerName %>">',
|
|
|
|
'<i class="icon-<%= provider.providerId %>"></i></span>',
|
|
|
|
'<input class="span5" type="text" value="<%= syncDesc %>" disabled />',
|
|
|
|
'</div>'].join("");
|
|
|
|
var removeButtonTemplate = '<a class="btn" title="Remove this location"><i class="icon-trash"></i></a>';
|
|
|
|
synchronizer.refreshManageSync = function() {
|
2013-04-21 00:07:27 +00:00
|
|
|
var fileIndex = core.fileManager.getCurrentFileIndex();
|
2013-04-20 00:14:20 +00:00
|
|
|
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
|
|
|
|
$(".msg-no-sync, .msg-sync-list").addClass("hide");
|
2013-05-04 00:05:58 +00:00
|
|
|
var syncList = $("#manage-sync-list").empty();
|
2013-04-20 00:14:20 +00:00
|
|
|
if (syncIndexList.length > 0) {
|
|
|
|
$(".msg-sync-list").removeClass("hide");
|
|
|
|
} else {
|
|
|
|
$(".msg-no-sync").removeClass("hide");
|
|
|
|
}
|
|
|
|
_.each(syncIndexList, function(syncIndex) {
|
|
|
|
var syncAttributes = JSON.parse(localStorage[syncIndex]);
|
|
|
|
var syncDesc = syncAttributes.id || syncAttributes.path;
|
2013-05-04 00:05:58 +00:00
|
|
|
var lineElement = $(_.template(lineTemplate, {
|
2013-04-20 00:14:20 +00:00
|
|
|
provider: providerMap[syncAttributes.provider],
|
|
|
|
syncDesc: syncDesc
|
|
|
|
}));
|
|
|
|
lineElement.append($(removeButtonTemplate).click(function() {
|
2013-04-21 00:07:27 +00:00
|
|
|
core.fileManager.removeSync(syncIndex);
|
|
|
|
core.fileManager.updateFileTitles();
|
2013-04-20 00:14:20 +00:00
|
|
|
}));
|
2013-05-04 00:05:58 +00:00
|
|
|
syncList.append(lineElement);
|
2013-04-20 00:14:20 +00:00
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2013-04-28 23:08:54 +00:00
|
|
|
// Used to enable/disable provider synchronization
|
2013-04-20 17:40:05 +00:00
|
|
|
synchronizer.resetSyncFlags = function() {
|
|
|
|
_.each(providerMap, function(provider) {
|
|
|
|
provider.useSync = false;
|
|
|
|
});
|
|
|
|
};
|
2013-05-02 00:02:57 +00:00
|
|
|
synchronizer.getSyncAttributesFromFile = function(fileIndex) {
|
2013-04-29 21:41:10 +00:00
|
|
|
var syncIndexList = _.compact(localStorage[fileIndex + ".sync"].split(";"));
|
2013-05-02 00:02:57 +00:00
|
|
|
var attributesList = [];
|
2013-04-29 21:41:10 +00:00
|
|
|
_.each(syncIndexList, function(syncIndex) {
|
|
|
|
var syncAttributes = JSON.parse(localStorage[syncIndex]);
|
2013-05-02 00:02:57 +00:00
|
|
|
attributesList.push(syncAttributes);
|
2013-04-29 21:41:10 +00:00
|
|
|
providerMap[syncAttributes.provider].useSync = true;
|
2013-04-20 17:40:05 +00:00
|
|
|
});
|
2013-05-02 00:02:57 +00:00
|
|
|
return attributesList;
|
2013-04-20 17:40:05 +00:00
|
|
|
};
|
|
|
|
|
2013-05-22 21:54:14 +00:00
|
|
|
// Initialize the export dialog
|
|
|
|
function initExportDialog(provider) {
|
|
|
|
|
|
|
|
// Reset fields
|
|
|
|
core.resetModalInputs();
|
|
|
|
|
|
|
|
// Load preferences
|
|
|
|
var serializedPreferences = localStorage[provider.providerId + ".exportPreferences"];
|
|
|
|
if(serializedPreferences) {
|
|
|
|
var exportPreferences = JSON.parse(serializedPreferences);
|
|
|
|
_.each(provider.exportPreferencesInputIds, function(inputId) {
|
|
|
|
$("#input-sync-export-" + inputId).val(exportPreferences[inputId]);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open dialog box
|
|
|
|
$("#modal-upload-" + provider.providerId).modal();
|
|
|
|
}
|
|
|
|
|
2013-04-22 01:04:12 +00:00
|
|
|
core.onReady(function() {
|
2013-04-20 00:14:20 +00:00
|
|
|
// Init each provider
|
|
|
|
_.each(providerMap, function(provider) {
|
|
|
|
// Provider's import button
|
|
|
|
$(".action-sync-import-" + provider.providerId).click(function(event) {
|
|
|
|
provider.importFiles(event);
|
|
|
|
});
|
2013-05-22 21:54:14 +00:00
|
|
|
// Provider's export action
|
|
|
|
$(".action-sync-export-dialog-" + provider.providerId).click(function() {
|
|
|
|
initExportDialog(provider);
|
|
|
|
});
|
2013-04-20 00:14:20 +00:00
|
|
|
$(".action-sync-export-" + provider.providerId).click(function(event) {
|
2013-05-22 21:54:14 +00:00
|
|
|
|
|
|
|
// Perform the provider's export
|
2013-04-21 00:07:27 +00:00
|
|
|
var fileIndex = core.fileManager.getCurrentFileIndex();
|
2013-04-20 00:14:20 +00:00
|
|
|
var title = localStorage[fileIndex + ".title"];
|
|
|
|
var content = localStorage[fileIndex + ".content"];
|
|
|
|
provider.exportFile(event, title, content, function(error, syncIndex) {
|
|
|
|
if(error) {
|
|
|
|
return;
|
|
|
|
}
|
2013-05-22 21:54:14 +00:00
|
|
|
// Link syncIndex with fileIndex
|
2013-04-20 00:14:20 +00:00
|
|
|
localStorage[fileIndex + ".sync"] += syncIndex + ";";
|
|
|
|
synchronizer.refreshManageSync();
|
2013-04-21 00:07:27 +00:00
|
|
|
core.fileManager.updateFileTitles();
|
2013-04-20 00:14:20 +00:00
|
|
|
core.showMessage('"' + title
|
|
|
|
+ '" will now be synchronized on ' + provider.providerName + '.');
|
|
|
|
});
|
2013-05-22 21:54:14 +00:00
|
|
|
|
|
|
|
// Store input values as preferences for next time we open the export dialog
|
|
|
|
var exportPreferences = {};
|
|
|
|
_.each(provider.exportPreferencesInputIds, function(inputId) {
|
|
|
|
exportPreferences[inputId] = $("#input-sync-export-" + inputId).val();
|
|
|
|
});
|
|
|
|
localStorage[provider.providerId + ".exportPreferences"] = JSON.stringify(exportPreferences);
|
2013-04-20 00:14:20 +00:00
|
|
|
});
|
2013-05-22 21:54:14 +00:00
|
|
|
// Provider's manual export button
|
2013-04-20 00:14:20 +00:00
|
|
|
$(".action-sync-manual-" + provider.providerId).click(function(event) {
|
2013-04-21 00:07:27 +00:00
|
|
|
var fileIndex = core.fileManager.getCurrentFileIndex();
|
2013-04-20 00:14:20 +00:00
|
|
|
var title = localStorage[fileIndex + ".title"];
|
|
|
|
var content = localStorage[fileIndex + ".content"];
|
|
|
|
provider.exportManual(event, title, content, function(error, syncIndex) {
|
|
|
|
if(error) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
localStorage[fileIndex + ".sync"] += syncIndex + ";";
|
|
|
|
synchronizer.refreshManageSync();
|
2013-04-21 00:07:27 +00:00
|
|
|
core.fileManager.updateFileTitles();
|
2013-04-20 00:14:20 +00:00
|
|
|
core.showMessage('"' + title
|
|
|
|
+ '" will now be synchronized on ' + provider.providerName + '.');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
2013-04-10 18:14:59 +00:00
|
|
|
synchronizer.updateSyncButton();
|
|
|
|
$(".action-force-sync").click(function() {
|
|
|
|
if(!$(this).hasClass("disabled")) {
|
|
|
|
synchronizer.forceSync();
|
|
|
|
}
|
|
|
|
});
|
2013-04-21 00:07:27 +00:00
|
|
|
});
|
2013-04-10 18:14:59 +00:00
|
|
|
|
2013-04-01 16:46:48 +00:00
|
|
|
return synchronizer;
|
2013-04-02 18:42:47 +00:00
|
|
|
});
|