2017-12-10 23:49:20 +00:00
|
|
|
import store from '../../store';
|
|
|
|
import googleHelper from './helpers/googleHelper';
|
2018-04-27 14:37:05 +00:00
|
|
|
import Provider from './common/Provider';
|
2017-12-10 23:49:20 +00:00
|
|
|
import utils from '../utils';
|
|
|
|
|
2018-02-01 22:39:14 +00:00
|
|
|
const getSyncData = (fileId) => {
|
|
|
|
const syncData = store.getters['data/syncDataByItemId'][`${fileId}/content`];
|
|
|
|
return syncData
|
|
|
|
? Promise.resolve(syncData)
|
|
|
|
: Promise.reject(); // No need for a proper error message.
|
|
|
|
};
|
|
|
|
|
2018-04-27 14:37:05 +00:00
|
|
|
let fileIdToOpen;
|
|
|
|
let syncStartPageToken;
|
|
|
|
|
|
|
|
export default new Provider({
|
2017-12-10 23:49:20 +00:00
|
|
|
id: 'googleDriveWorkspace',
|
|
|
|
getToken() {
|
2017-12-17 15:08:52 +00:00
|
|
|
return store.getters['workspace/syncToken'];
|
2017-12-10 23:49:20 +00:00
|
|
|
},
|
|
|
|
initWorkspace() {
|
2018-04-27 14:37:05 +00:00
|
|
|
const makeWorkspaceParams = folderId => ({
|
2017-12-17 15:08:52 +00:00
|
|
|
providerId: this.id,
|
|
|
|
folderId,
|
2018-01-04 20:19:10 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
const makeWorkspaceId = folderId => folderId && utils.makeWorkspaceId(
|
2018-04-27 14:37:05 +00:00
|
|
|
makeWorkspaceParams(folderId));
|
2017-12-17 15:08:52 +00:00
|
|
|
|
2018-01-04 20:19:10 +00:00
|
|
|
const getWorkspace = folderId =>
|
|
|
|
store.getters['data/sanitizedWorkspaces'][makeWorkspaceId(folderId)];
|
2017-12-17 15:08:52 +00:00
|
|
|
|
2017-12-10 23:49:20 +00:00
|
|
|
const initFolder = (token, folder) => Promise.resolve({
|
2017-12-17 15:08:52 +00:00
|
|
|
folderId: folder.id,
|
2017-12-10 23:49:20 +00:00
|
|
|
dataFolderId: folder.appProperties.dataFolderId,
|
|
|
|
trashFolderId: folder.appProperties.trashFolderId,
|
|
|
|
})
|
|
|
|
.then((properties) => {
|
|
|
|
// Make sure data folder exists
|
|
|
|
if (properties.dataFolderId) {
|
|
|
|
return properties;
|
|
|
|
}
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
'.stackedit-data',
|
|
|
|
[folder.id],
|
2017-12-17 15:08:52 +00:00
|
|
|
{ folderId: folder.id },
|
2017-12-10 23:49:20 +00:00
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
googleHelper.folderMimeType,
|
2017-12-10 23:49:20 +00:00
|
|
|
)
|
|
|
|
.then(dataFolder => ({
|
|
|
|
...properties,
|
|
|
|
dataFolderId: dataFolder.id,
|
|
|
|
}));
|
|
|
|
})
|
|
|
|
.then((properties) => {
|
|
|
|
// Make sure trash folder exists
|
|
|
|
if (properties.trashFolderId) {
|
|
|
|
return properties;
|
|
|
|
}
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
'.stackedit-trash',
|
|
|
|
[folder.id],
|
2017-12-17 15:08:52 +00:00
|
|
|
{ folderId: folder.id },
|
2017-12-10 23:49:20 +00:00
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
googleHelper.folderMimeType,
|
2017-12-10 23:49:20 +00:00
|
|
|
)
|
|
|
|
.then(trashFolder => ({
|
|
|
|
...properties,
|
|
|
|
trashFolderId: trashFolder.id,
|
|
|
|
}));
|
|
|
|
})
|
|
|
|
.then((properties) => {
|
|
|
|
// Update workspace if some properties are missing
|
2017-12-17 15:08:52 +00:00
|
|
|
if (properties.folderId === folder.appProperties.folderId
|
2017-12-10 23:49:20 +00:00
|
|
|
&& properties.dataFolderId === folder.appProperties.dataFolderId
|
|
|
|
&& properties.trashFolderId === folder.appProperties.trashFolderId
|
|
|
|
) {
|
|
|
|
return properties;
|
|
|
|
}
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
properties,
|
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
googleHelper.folderMimeType,
|
2017-12-10 23:49:20 +00:00
|
|
|
folder.id,
|
|
|
|
)
|
|
|
|
.then(() => properties);
|
|
|
|
})
|
|
|
|
.then((properties) => {
|
|
|
|
// Update workspace in the store
|
2017-12-17 15:08:52 +00:00
|
|
|
const workspaceId = makeWorkspaceId(folder.id);
|
2017-12-10 23:49:20 +00:00
|
|
|
store.dispatch('data/patchWorkspaces', {
|
2017-12-17 15:08:52 +00:00
|
|
|
[workspaceId]: {
|
|
|
|
id: workspaceId,
|
2017-12-10 23:49:20 +00:00
|
|
|
sub: token.sub,
|
|
|
|
name: folder.name,
|
|
|
|
providerId: this.id,
|
2018-01-04 20:19:10 +00:00
|
|
|
url: location.href,
|
2017-12-10 23:49:20 +00:00
|
|
|
folderId: folder.id,
|
2018-04-11 09:17:53 +00:00
|
|
|
teamDriveId: folder.teamDriveId,
|
2017-12-10 23:49:20 +00:00
|
|
|
dataFolderId: properties.dataFolderId,
|
|
|
|
trashFolderId: properties.trashFolderId,
|
|
|
|
},
|
|
|
|
});
|
2017-12-17 15:08:52 +00:00
|
|
|
|
|
|
|
// Return the workspace
|
2018-01-24 07:31:54 +00:00
|
|
|
return store.getters['data/sanitizedWorkspaces'][workspaceId];
|
2017-12-10 23:49:20 +00:00
|
|
|
});
|
|
|
|
|
2017-12-17 15:08:52 +00:00
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
2018-01-04 20:19:10 +00:00
|
|
|
const workspace = getWorkspace(utils.queryParams.folderId);
|
2017-12-17 15:08:52 +00:00
|
|
|
// See if we already have a token
|
|
|
|
const googleTokens = store.getters['data/googleTokens'];
|
|
|
|
// Token sub is in the workspace or in the url if workspace is about to be created
|
|
|
|
const token = workspace ? googleTokens[workspace.sub] : googleTokens[utils.queryParams.sub];
|
2017-12-23 18:25:14 +00:00
|
|
|
if (token && token.isDrive && token.driveFullAccess) {
|
2017-12-17 15:08:52 +00:00
|
|
|
return token;
|
|
|
|
}
|
|
|
|
// If no token has been found, popup an authorize window and get one
|
|
|
|
return store.dispatch('modal/workspaceGoogleRedirection', {
|
2018-01-04 20:19:10 +00:00
|
|
|
onResolve: () => googleHelper.addDriveAccount(true, utils.queryParams.sub),
|
2017-12-17 15:08:52 +00:00
|
|
|
});
|
|
|
|
})
|
2017-12-10 23:49:20 +00:00
|
|
|
.then(token => Promise.resolve()
|
2017-12-17 15:08:52 +00:00
|
|
|
// If no folderId is provided, create one
|
2017-12-10 23:49:20 +00:00
|
|
|
.then(() => utils.queryParams.folderId || googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
'StackEdit workspace',
|
|
|
|
[],
|
|
|
|
undefined,
|
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
googleHelper.folderMimeType,
|
2017-12-17 15:08:52 +00:00
|
|
|
)
|
|
|
|
.then(folder => initFolder(token, {
|
|
|
|
...folder,
|
|
|
|
appProperties: {},
|
|
|
|
})
|
|
|
|
.then(() => folder.id)))
|
|
|
|
// If workspace does not exist, initialize one
|
|
|
|
.then(folderId => getWorkspace(folderId) || googleHelper.getFile(token, folderId)
|
|
|
|
.then((folder) => {
|
2017-12-23 18:25:14 +00:00
|
|
|
folder.appProperties = folder.appProperties || {};
|
2017-12-17 15:08:52 +00:00
|
|
|
const folderIdProperty = folder.appProperties.folderId;
|
|
|
|
if (folderIdProperty && folderIdProperty !== folderId) {
|
2018-01-04 20:19:10 +00:00
|
|
|
throw new Error(`Folder ${folderId} is part of another workspace.`);
|
2017-12-17 15:08:52 +00:00
|
|
|
}
|
|
|
|
return initFolder(token, folder);
|
|
|
|
}, () => {
|
2017-12-23 18:25:14 +00:00
|
|
|
throw new Error(`Folder ${folderId} is not accessible. Make sure you have the right permissions.`);
|
2018-01-04 20:19:10 +00:00
|
|
|
}))
|
|
|
|
.then((workspace) => {
|
|
|
|
// Fix the URL hash
|
2018-04-27 14:37:05 +00:00
|
|
|
utils.setQueryParams(makeWorkspaceParams(workspace.folderId));
|
2018-01-24 07:31:54 +00:00
|
|
|
if (workspace.url !== location.href) {
|
|
|
|
store.dispatch('data/patchWorkspaces', {
|
|
|
|
[workspace.id]: {
|
|
|
|
...workspace,
|
|
|
|
url: location.href,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return store.getters['data/sanitizedWorkspaces'][workspace.id];
|
2018-01-04 20:19:10 +00:00
|
|
|
}));
|
|
|
|
},
|
|
|
|
performAction() {
|
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
const state = googleHelper.driveState || {};
|
|
|
|
const token = this.getToken();
|
|
|
|
switch (token && state.action) {
|
|
|
|
case 'create':
|
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
const driveFolder = googleHelper.driveActionFolder;
|
|
|
|
let syncData = store.getters['data/syncData'][driveFolder.id];
|
|
|
|
if (!syncData && driveFolder.appProperties.id) {
|
|
|
|
// Create folder if not already synced
|
|
|
|
store.commit('folder/setItem', {
|
|
|
|
id: driveFolder.appProperties.id,
|
|
|
|
name: driveFolder.name,
|
|
|
|
});
|
|
|
|
const item = store.state.folder.itemMap[driveFolder.appProperties.id];
|
|
|
|
syncData = {
|
|
|
|
id: driveFolder.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
};
|
|
|
|
store.dispatch('data/patchSyncData', {
|
|
|
|
[syncData.id]: syncData,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return store.dispatch('createFile', {
|
|
|
|
parentId: syncData && syncData.itemId,
|
|
|
|
})
|
|
|
|
.then((file) => {
|
|
|
|
store.commit('file/setCurrentId', file.id);
|
|
|
|
// File will be created on next workspace sync
|
|
|
|
});
|
|
|
|
});
|
|
|
|
case 'open':
|
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
// open first file only
|
|
|
|
const firstFile = googleHelper.driveActionFiles[0];
|
|
|
|
const syncData = store.getters['data/syncData'][firstFile.id];
|
|
|
|
if (!syncData) {
|
|
|
|
fileIdToOpen = firstFile.id;
|
|
|
|
} else {
|
|
|
|
store.commit('file/setCurrentId', syncData.itemId);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
default:
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
});
|
2017-12-10 23:49:20 +00:00
|
|
|
},
|
2017-12-23 18:25:14 +00:00
|
|
|
getChanges() {
|
|
|
|
const workspace = store.getters['workspace/currentWorkspace'];
|
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
2017-12-17 15:08:52 +00:00
|
|
|
const startPageToken = store.getters['data/localSettings'].syncStartPageToken;
|
2018-04-11 09:17:53 +00:00
|
|
|
return googleHelper.getChanges(syncToken, startPageToken, false, workspace.teamDriveId)
|
2017-12-10 23:49:20 +00:00
|
|
|
.then((result) => {
|
2017-12-23 18:25:14 +00:00
|
|
|
// Collect possible parent IDs
|
|
|
|
const parentIds = {};
|
|
|
|
Object.entries(store.getters['data/syncDataByItemId']).forEach(([id, syncData]) => {
|
|
|
|
parentIds[syncData.id] = id;
|
|
|
|
});
|
|
|
|
result.changes.forEach((change) => {
|
|
|
|
const id = ((change.file || {}).appProperties || {}).id;
|
|
|
|
if (id) {
|
|
|
|
parentIds[change.fileId] = id;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
// Collect changes
|
|
|
|
const changes = [];
|
|
|
|
result.changes.forEach((change) => {
|
|
|
|
// Ignore changes on StackEdit own folders
|
|
|
|
if (change.fileId === workspace.folderId
|
|
|
|
|| change.fileId === workspace.dataFolderId
|
|
|
|
|| change.fileId === workspace.trashFolderId
|
|
|
|
) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
let contentChange;
|
2017-12-10 23:49:20 +00:00
|
|
|
if (change.file) {
|
2017-12-23 18:25:14 +00:00
|
|
|
// Ignore changes in files that are not in the workspace
|
2018-01-04 20:19:10 +00:00
|
|
|
const appProperties = change.file.appProperties;
|
|
|
|
if (!appProperties || appProperties.folderId !== workspace.folderId
|
2017-12-23 18:25:14 +00:00
|
|
|
) {
|
|
|
|
return;
|
2017-12-10 23:49:20 +00:00
|
|
|
}
|
2017-12-23 18:25:14 +00:00
|
|
|
|
|
|
|
// If change is on a data item
|
|
|
|
if (change.file.parents[0] === workspace.dataFolderId) {
|
2018-04-11 14:50:46 +00:00
|
|
|
// Data item has a JSON filename
|
2017-12-23 18:25:14 +00:00
|
|
|
try {
|
|
|
|
change.item = JSON.parse(change.file.name);
|
|
|
|
} catch (e) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Change on a file or folder
|
|
|
|
const type = change.file.mimeType === googleHelper.folderMimeType
|
|
|
|
? 'folder'
|
|
|
|
: 'file';
|
|
|
|
const item = {
|
2018-01-04 20:19:10 +00:00
|
|
|
id: appProperties.id,
|
2017-12-23 18:25:14 +00:00
|
|
|
type,
|
|
|
|
name: change.file.name,
|
|
|
|
parentId: null,
|
|
|
|
};
|
|
|
|
|
|
|
|
// Fill parentId
|
|
|
|
if (change.file.parents.some(parentId => parentId === workspace.trashFolderId)) {
|
|
|
|
item.parentId = 'trash';
|
|
|
|
} else {
|
|
|
|
change.file.parents.some((parentId) => {
|
|
|
|
if (!parentIds[parentId]) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
item.parentId = parentIds[parentId];
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
change.item = utils.addItemHash(item);
|
|
|
|
|
|
|
|
if (type === 'file') {
|
|
|
|
// create a fake change as a file content change
|
|
|
|
contentChange = {
|
|
|
|
item: {
|
2018-01-04 20:19:10 +00:00
|
|
|
id: `${appProperties.id}/content`,
|
2017-12-23 18:25:14 +00:00
|
|
|
type: 'content',
|
|
|
|
// Need a truthy value to force saving sync data
|
|
|
|
hash: 1,
|
|
|
|
},
|
|
|
|
syncData: {
|
|
|
|
id: `${change.fileId}/content`,
|
2018-01-04 20:19:10 +00:00
|
|
|
itemId: `${appProperties.id}/content`,
|
2017-12-23 18:25:14 +00:00
|
|
|
type: 'content',
|
|
|
|
// Need a truthy value to force downloading the content
|
|
|
|
hash: 1,
|
|
|
|
},
|
|
|
|
syncDataId: `${change.fileId}/content`,
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-10 23:49:20 +00:00
|
|
|
// Build sync data
|
|
|
|
change.syncData = {
|
|
|
|
id: change.fileId,
|
2018-04-11 14:50:46 +00:00
|
|
|
parentIds: change.file.parents,
|
2017-12-10 23:49:20 +00:00
|
|
|
itemId: change.item.id,
|
|
|
|
type: change.item.type,
|
|
|
|
hash: change.item.hash,
|
|
|
|
};
|
2017-12-23 18:25:14 +00:00
|
|
|
} else {
|
|
|
|
// Item was removed
|
|
|
|
const syncData = store.getters['data/syncData'][change.fileId];
|
|
|
|
if (syncData && syncData.type === 'file') {
|
|
|
|
// create a fake change as a file content change
|
|
|
|
contentChange = {
|
|
|
|
syncDataId: `${change.fileId}/content`,
|
|
|
|
};
|
|
|
|
}
|
2017-12-10 23:49:20 +00:00
|
|
|
}
|
2017-12-23 18:25:14 +00:00
|
|
|
|
|
|
|
// Push change
|
2017-12-17 15:08:52 +00:00
|
|
|
change.syncDataId = change.fileId;
|
2017-12-23 18:25:14 +00:00
|
|
|
changes.push(change);
|
|
|
|
if (contentChange) {
|
|
|
|
changes.push(contentChange);
|
|
|
|
}
|
2017-12-10 23:49:20 +00:00
|
|
|
});
|
2018-04-27 14:37:05 +00:00
|
|
|
syncStartPageToken = result.startPageToken;
|
2017-12-10 23:49:20 +00:00
|
|
|
return changes;
|
|
|
|
});
|
|
|
|
},
|
2018-04-27 14:37:05 +00:00
|
|
|
onChangesApplied() {
|
2017-12-23 18:25:14 +00:00
|
|
|
store.dispatch('data/patchLocalSettings', {
|
2018-04-27 14:37:05 +00:00
|
|
|
syncStartPageToken,
|
2017-12-23 18:25:14 +00:00
|
|
|
});
|
|
|
|
},
|
|
|
|
saveSimpleItem(item, syncData, ifNotTooLate) {
|
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
const workspace = store.getters['workspace/currentWorkspace'];
|
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
if (item.type !== 'file' && item.type !== 'folder') {
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
syncToken,
|
|
|
|
JSON.stringify(item),
|
|
|
|
[workspace.dataFolderId],
|
|
|
|
{
|
|
|
|
folderId: workspace.folderId,
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
syncData && syncData.id,
|
2018-04-11 14:50:46 +00:00
|
|
|
syncData && syncData.parentIds,
|
2017-12-23 18:25:14 +00:00
|
|
|
ifNotTooLate,
|
|
|
|
);
|
|
|
|
}
|
2018-04-11 15:19:20 +00:00
|
|
|
|
|
|
|
// For type `file` or `folder`
|
2017-12-23 18:25:14 +00:00
|
|
|
const parentSyncData = store.getters['data/syncDataByItemId'][item.parentId];
|
2018-04-11 15:19:20 +00:00
|
|
|
let parentId;
|
|
|
|
if (item.parentId === 'trash') {
|
|
|
|
parentId = workspace.trashFolderId;
|
|
|
|
} else if (parentSyncData) {
|
|
|
|
parentId = parentSyncData.id;
|
|
|
|
} else {
|
|
|
|
parentId = workspace.folderId;
|
|
|
|
}
|
|
|
|
|
2017-12-23 18:25:14 +00:00
|
|
|
return googleHelper.uploadFile(
|
|
|
|
syncToken,
|
|
|
|
item.name,
|
2018-04-11 15:19:20 +00:00
|
|
|
[parentId],
|
2017-12-23 18:25:14 +00:00
|
|
|
{
|
|
|
|
id: item.id,
|
|
|
|
folderId: workspace.folderId,
|
|
|
|
},
|
|
|
|
undefined,
|
|
|
|
item.type === 'folder' ? googleHelper.folderMimeType : undefined,
|
|
|
|
syncData && syncData.id,
|
2018-04-11 14:50:46 +00:00
|
|
|
syncData && syncData.parentIds,
|
2017-12-23 18:25:14 +00:00
|
|
|
ifNotTooLate,
|
|
|
|
);
|
|
|
|
})
|
|
|
|
.then(file => ({
|
|
|
|
// Build sync data
|
|
|
|
id: file.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
removeItem(syncData, ifNotTooLate) {
|
|
|
|
// Ignore content deletion
|
|
|
|
if (syncData.type === 'content') {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
return googleHelper.removeFile(syncToken, syncData.id, ifNotTooLate);
|
|
|
|
},
|
|
|
|
downloadContent(token, syncLocation) {
|
|
|
|
const syncData = store.getters['data/syncDataByItemId'][syncLocation.fileId];
|
|
|
|
const contentSyncData = store.getters['data/syncDataByItemId'][`${syncLocation.fileId}/content`];
|
|
|
|
if (!syncData || !contentSyncData) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
return googleHelper.downloadFile(token, syncData.id)
|
|
|
|
.then((content) => {
|
2018-04-27 14:37:05 +00:00
|
|
|
const item = Provider.parseContent(content, `${syncLocation.fileId}/content`);
|
2017-12-23 18:25:14 +00:00
|
|
|
if (item.hash !== contentSyncData.hash) {
|
|
|
|
store.dispatch('data/patchSyncData', {
|
|
|
|
[contentSyncData.id]: {
|
|
|
|
...contentSyncData,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
2018-04-27 14:37:05 +00:00
|
|
|
// Open the file requested by action if it wasn't synced yet
|
2018-01-04 20:19:10 +00:00
|
|
|
if (fileIdToOpen && fileIdToOpen === syncData.id) {
|
|
|
|
fileIdToOpen = null;
|
|
|
|
// Open the file once downloaded content has been stored
|
|
|
|
setTimeout(() => {
|
|
|
|
store.commit('file/setCurrentId', syncData.itemId);
|
|
|
|
}, 10);
|
|
|
|
}
|
2017-12-23 18:25:14 +00:00
|
|
|
return item;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
downloadData(dataId) {
|
|
|
|
const syncData = store.getters['data/syncDataByItemId'][dataId];
|
|
|
|
if (!syncData) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
return googleHelper.downloadFile(syncToken, syncData.id)
|
|
|
|
.then((content) => {
|
|
|
|
const item = JSON.parse(content);
|
|
|
|
if (item.hash !== syncData.hash) {
|
|
|
|
store.dispatch('data/patchSyncData', {
|
|
|
|
[syncData.id]: {
|
|
|
|
...syncData,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
}
|
|
|
|
return item;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
uploadContent(token, content, syncLocation, ifNotTooLate) {
|
|
|
|
const contentSyncData = store.getters['data/syncDataByItemId'][`${syncLocation.fileId}/content`];
|
|
|
|
if (contentSyncData && contentSyncData.hash === content.hash) {
|
2018-02-01 22:39:14 +00:00
|
|
|
return Promise.resolve(syncLocation);
|
2017-12-23 18:25:14 +00:00
|
|
|
}
|
|
|
|
return Promise.resolve()
|
|
|
|
.then(() => {
|
|
|
|
const syncData = store.getters['data/syncDataByItemId'][syncLocation.fileId];
|
|
|
|
if (syncData) {
|
|
|
|
// Only update file media
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
|
|
|
undefined,
|
2018-04-27 14:37:05 +00:00
|
|
|
Provider.serializeContent(content),
|
2017-12-23 18:25:14 +00:00
|
|
|
undefined,
|
|
|
|
syncData.id,
|
2018-04-11 14:50:46 +00:00
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
ifNotTooLate,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
// Create file with media
|
|
|
|
const workspace = store.getters['workspace/currentWorkspace'];
|
|
|
|
// Use deepCopy to freeze objects
|
|
|
|
const item = utils.deepCopy(store.state.file.itemMap[syncLocation.fileId]);
|
|
|
|
const parentSyncData = store.getters['data/syncDataByItemId'][item.parentId];
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
token,
|
|
|
|
item.name,
|
|
|
|
[parentSyncData ? parentSyncData.id : workspace.folderId],
|
|
|
|
{
|
|
|
|
id: item.id,
|
|
|
|
folderId: workspace.folderId,
|
|
|
|
},
|
2018-04-27 14:37:05 +00:00
|
|
|
Provider.serializeContent(content),
|
2017-12-23 18:25:14 +00:00
|
|
|
undefined,
|
|
|
|
undefined,
|
2018-04-11 14:50:46 +00:00
|
|
|
undefined,
|
2017-12-23 18:25:14 +00:00
|
|
|
ifNotTooLate,
|
|
|
|
)
|
|
|
|
.then((file) => {
|
|
|
|
store.dispatch('data/patchSyncData', {
|
|
|
|
[file.id]: {
|
|
|
|
id: file.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
});
|
|
|
|
return file;
|
|
|
|
});
|
|
|
|
})
|
|
|
|
.then(file => store.dispatch('data/patchSyncData', {
|
|
|
|
[`${file.id}/content`]: {
|
|
|
|
// Build sync data
|
|
|
|
id: `${file.id}/content`,
|
|
|
|
itemId: content.id,
|
|
|
|
type: content.type,
|
|
|
|
hash: content.hash,
|
|
|
|
},
|
|
|
|
}))
|
|
|
|
.then(() => syncLocation);
|
|
|
|
},
|
2018-04-27 14:37:05 +00:00
|
|
|
uploadData(item, ifNotTooLate) {
|
|
|
|
const syncData = store.getters['data/syncDataByItemId'][item.id];
|
2017-12-23 18:25:14 +00:00
|
|
|
if (syncData && syncData.hash === item.hash) {
|
|
|
|
return Promise.resolve();
|
|
|
|
}
|
|
|
|
const workspace = store.getters['workspace/currentWorkspace'];
|
|
|
|
const syncToken = store.getters['workspace/syncToken'];
|
|
|
|
return googleHelper.uploadFile(
|
|
|
|
syncToken,
|
|
|
|
JSON.stringify({
|
|
|
|
id: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
}),
|
|
|
|
[workspace.dataFolderId],
|
|
|
|
{
|
|
|
|
folderId: workspace.folderId,
|
|
|
|
},
|
|
|
|
JSON.stringify(item),
|
|
|
|
undefined,
|
|
|
|
syncData && syncData.id,
|
2018-04-11 14:50:46 +00:00
|
|
|
syncData && syncData.parentIds,
|
2017-12-23 18:25:14 +00:00
|
|
|
ifNotTooLate,
|
|
|
|
)
|
|
|
|
.then(file => store.dispatch('data/patchSyncData', {
|
|
|
|
[file.id]: {
|
|
|
|
// Build sync data
|
|
|
|
id: file.id,
|
|
|
|
itemId: item.id,
|
|
|
|
type: item.type,
|
|
|
|
hash: item.hash,
|
|
|
|
},
|
|
|
|
}));
|
|
|
|
},
|
|
|
|
listRevisions(token, fileId) {
|
2018-02-01 22:39:14 +00:00
|
|
|
return getSyncData(fileId)
|
|
|
|
.then(syncData => googleHelper.getFileRevisions(token, syncData.id))
|
2017-12-23 18:25:14 +00:00
|
|
|
.then(revisions => revisions.map(revision => ({
|
|
|
|
id: revision.id,
|
|
|
|
sub: revision.lastModifyingUser && revision.lastModifyingUser.permissionId,
|
|
|
|
created: new Date(revision.modifiedTime).getTime(),
|
2018-01-30 07:36:33 +00:00
|
|
|
}))
|
|
|
|
.sort((revision1, revision2) => revision2.created - revision1.created));
|
2017-12-23 18:25:14 +00:00
|
|
|
},
|
|
|
|
getRevisionContent(token, fileId, revisionId) {
|
2018-02-01 22:39:14 +00:00
|
|
|
return getSyncData(fileId)
|
|
|
|
.then(syncData => googleHelper.downloadFileRevision(token, syncData.id, revisionId))
|
2018-04-27 14:37:05 +00:00
|
|
|
.then(content => Provider.parseContent(content, `${fileId}/content`));
|
2017-12-23 18:25:14 +00:00
|
|
|
},
|
2017-12-10 23:49:20 +00:00
|
|
|
});
|