257 lines
8.1 KiB
JavaScript
257 lines
8.1 KiB
JavaScript
|
import store from '../../store';
|
||
|
import googleHelper from './helpers/googleHelper';
|
||
|
import providerRegistry from './providerRegistry';
|
||
|
import utils from '../utils';
|
||
|
|
||
|
let workspaceFolderId;
|
||
|
|
||
|
const makeWorkspaceId = () => {
|
||
|
|
||
|
};
|
||
|
|
||
|
export default providerRegistry.register({
|
||
|
id: 'googleDriveWorkspace',
|
||
|
getToken() {
|
||
|
return store.getters['data/loginToken'];
|
||
|
},
|
||
|
initWorkspace() {
|
||
|
const initFolder = (token, folder) => Promise.resolve({
|
||
|
workspaceId: this.makeWorkspaceId(folder.id),
|
||
|
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],
|
||
|
{ workspaceId: properties.workspaceId },
|
||
|
undefined,
|
||
|
'application/vnd.google-apps.folder',
|
||
|
)
|
||
|
.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],
|
||
|
{ workspaceId: properties.workspaceId },
|
||
|
undefined,
|
||
|
'application/vnd.google-apps.folder',
|
||
|
)
|
||
|
.then(trashFolder => ({
|
||
|
...properties,
|
||
|
trashFolderId: trashFolder.id,
|
||
|
}));
|
||
|
})
|
||
|
.then((properties) => {
|
||
|
// Update workspace if some properties are missing
|
||
|
if (properties.workspaceId === folder.appProperties.workspaceId
|
||
|
&& properties.dataFolderId === folder.appProperties.dataFolderId
|
||
|
&& properties.trashFolderId === folder.appProperties.trashFolderId
|
||
|
) {
|
||
|
return properties;
|
||
|
}
|
||
|
return googleHelper.uploadFile(
|
||
|
token,
|
||
|
undefined,
|
||
|
undefined,
|
||
|
properties,
|
||
|
undefined,
|
||
|
'application/vnd.google-apps.folder',
|
||
|
folder.id,
|
||
|
)
|
||
|
.then(() => properties);
|
||
|
})
|
||
|
.then((properties) => {
|
||
|
// Update workspace in the store
|
||
|
store.dispatch('data/patchWorkspaces', {
|
||
|
[properties.workspaceId]: {
|
||
|
id: properties.workspaceId,
|
||
|
sub: token.sub,
|
||
|
name: folder.name,
|
||
|
providerId: this.id,
|
||
|
folderId: folder.id,
|
||
|
dataFolderId: properties.dataFolderId,
|
||
|
trashFolderId: properties.trashFolderId,
|
||
|
},
|
||
|
});
|
||
|
return store.getters['data/workspaces'][properties.workspaceId];
|
||
|
});
|
||
|
|
||
|
return Promise.resolve(store.getters['data/googleTokens'][utils.queryParams.sub])
|
||
|
.then(token => token || this.$store.dispatch('modal/workspaceGoogleRedirection', {
|
||
|
onResolve: () => googleHelper.addDriveAccount(),
|
||
|
}))
|
||
|
.then(token => Promise.resolve()
|
||
|
.then(() => utils.queryParams.folderId || googleHelper.uploadFile(
|
||
|
token,
|
||
|
'StackEdit workspace',
|
||
|
[],
|
||
|
undefined,
|
||
|
undefined,
|
||
|
'application/vnd.google-apps.folder',
|
||
|
).then(folder => initFolder(token, folder).then(() => folder.id)))
|
||
|
.then((folderId) => {
|
||
|
const workspaceId = this.makeWorkspaceId(folderId);
|
||
|
const workspace = store.getters['data/workspaces'][workspaceId];
|
||
|
return workspace || googleHelper.getFile(token, folderId)
|
||
|
.then((folder) => {
|
||
|
const folderWorkspaceId = folder.appProperties.workspaceId;
|
||
|
if (folderWorkspaceId && folderWorkspaceId !== workspaceId) {
|
||
|
throw new Error(`Google Drive folder ${folderId} is part of another workspace.`);
|
||
|
}
|
||
|
return initFolder(token, folder);
|
||
|
});
|
||
|
}));
|
||
|
},
|
||
|
getChanges(token) {
|
||
|
return googleHelper.getChanges(token)
|
||
|
.then((result) => {
|
||
|
const changes = result.changes.filter((change) => {
|
||
|
if (change.file) {
|
||
|
try {
|
||
|
change.item = JSON.parse(change.file.name);
|
||
|
} catch (e) {
|
||
|
return false;
|
||
|
}
|
||
|
// Build sync data
|
||
|
change.syncData = {
|
||
|
id: change.fileId,
|
||
|
itemId: change.item.id,
|
||
|
type: change.item.type,
|
||
|
hash: change.item.hash,
|
||
|
};
|
||
|
change.file = undefined;
|
||
|
}
|
||
|
return true;
|
||
|
});
|
||
|
changes.nextPageToken = result.nextPageToken;
|
||
|
return changes;
|
||
|
});
|
||
|
},
|
||
|
setAppliedChanges(token, changes) {
|
||
|
const lastToken = store.getters['data/googleTokens'][token.sub];
|
||
|
if (changes.nextPageToken !== lastToken.nextPageToken) {
|
||
|
store.dispatch('data/setGoogleToken', {
|
||
|
...lastToken,
|
||
|
nextPageToken: changes.nextPageToken,
|
||
|
});
|
||
|
}
|
||
|
},
|
||
|
saveItem(token, item, syncData, ifNotTooLate) {
|
||
|
return googleHelper.uploadAppDataFile(
|
||
|
token,
|
||
|
JSON.stringify(item),
|
||
|
['appDataFolder'],
|
||
|
undefined,
|
||
|
undefined,
|
||
|
syncData && syncData.id,
|
||
|
ifNotTooLate,
|
||
|
)
|
||
|
.then(file => ({
|
||
|
// Build sync data
|
||
|
id: file.id,
|
||
|
itemId: item.id,
|
||
|
type: item.type,
|
||
|
hash: item.hash,
|
||
|
}));
|
||
|
},
|
||
|
removeItem(token, syncData, ifNotTooLate) {
|
||
|
return googleHelper.removeAppDataFile(token, syncData.id, ifNotTooLate)
|
||
|
.then(() => syncData);
|
||
|
},
|
||
|
downloadContent(token, syncLocation) {
|
||
|
return this.downloadData(token, `${syncLocation.fileId}/content`);
|
||
|
},
|
||
|
downloadData(token, dataId) {
|
||
|
const syncData = store.getters['data/syncDataByItemId'][dataId];
|
||
|
if (!syncData) {
|
||
|
return Promise.resolve();
|
||
|
}
|
||
|
return googleHelper.downloadAppDataFile(token, 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) {
|
||
|
return this.uploadData(token, content, `${syncLocation.fileId}/content`, ifNotTooLate)
|
||
|
.then(() => syncLocation);
|
||
|
},
|
||
|
uploadData(token, item, dataId, ifNotTooLate) {
|
||
|
const syncData = store.getters['data/syncDataByItemId'][dataId];
|
||
|
if (syncData && syncData.hash === item.hash) {
|
||
|
return Promise.resolve();
|
||
|
}
|
||
|
return googleHelper.uploadAppDataFile(
|
||
|
token,
|
||
|
JSON.stringify({
|
||
|
id: item.id,
|
||
|
type: item.type,
|
||
|
hash: item.hash,
|
||
|
}),
|
||
|
['appDataFolder'],
|
||
|
undefined,
|
||
|
JSON.stringify(item),
|
||
|
syncData && syncData.id,
|
||
|
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) {
|
||
|
const syncData = store.getters['data/syncDataByItemId'][`${fileId}/content`];
|
||
|
if (!syncData) {
|
||
|
return Promise.reject(); // No need for a proper error message.
|
||
|
}
|
||
|
return googleHelper.getFileRevisions(token, syncData.id)
|
||
|
.then(revisions => revisions.map(revision => ({
|
||
|
id: revision.id,
|
||
|
sub: revision.lastModifyingUser && revision.lastModifyingUser.permissionId,
|
||
|
created: new Date(revision.modifiedTime).getTime(),
|
||
|
})));
|
||
|
},
|
||
|
getRevisionContent(token, fileId, revisionId) {
|
||
|
const syncData = store.getters['data/syncDataByItemId'][`${fileId}/content`];
|
||
|
if (!syncData) {
|
||
|
return Promise.reject(); // No need for a proper error message.
|
||
|
}
|
||
|
return googleHelper.downloadFileRevision(token, syncData.id, revisionId)
|
||
|
.then(content => JSON.parse(content));
|
||
|
},
|
||
|
makeWorkspaceId(folderId) {
|
||
|
return Math.abs(utils.hash(utils.serializeObject({
|
||
|
providerId: this.id,
|
||
|
folderId: folderId,
|
||
|
}))).toString(36);
|
||
|
},
|
||
|
});
|