slate/common/user-behaviors.js

408 lines
11 KiB
JavaScript
Raw Normal View History

2020-11-19 21:14:09 +03:00
import * as Websockets from "~/common/browser-websockets";
import * as Credentials from "~/common/credentials";
import * as Actions from "~/common/actions";
import * as Window from "~/common/window";
2020-11-24 09:31:52 +03:00
import * as Validations from "~/common/validations";
import * as Strings from "~/common/strings";
2020-11-20 07:03:30 +03:00
import * as Store from "~/common/store";
import * as FileUtilities from "~/common/file-utilities";
import * as Events from "~/common/custom-events";
2020-11-19 21:14:09 +03:00
import Cookies from "universal-cookie";
2020-12-25 02:44:47 +03:00
import JSZip from "jszip";
2021-01-21 00:50:29 +03:00
2021-02-09 12:56:24 +03:00
import { v4 as uuid } from "uuid";
2020-12-25 02:44:47 +03:00
import { saveAs } from "file-saver";
2020-11-19 21:14:09 +03:00
2021-01-21 00:50:29 +03:00
//NOTE(martina): this file is for utility *API-calling* functions
//For non API related utility functions, see common/utilities.js
//And for uploading related utility functions, see common/file-utilities.js
2020-11-19 21:14:09 +03:00
const cookies = new Cookies();
export const authenticate = async (state) => {
2020-11-20 07:03:30 +03:00
// NOTE(jim): Kills existing session cookie if there is one.
const jwt = cookies.get(Credentials.session.key);
if (jwt) {
2021-05-06 03:08:14 +03:00
cookies.remove(Credentials.session.key, {
path: "/",
maxAge: 3600 * 24 * 7,
sameSite: "strict",
});
2020-11-20 07:03:30 +03:00
}
let response = await Actions.signIn(state);
if (!response || response.error) {
return response;
2020-11-20 07:03:30 +03:00
}
if (response.token) {
// NOTE(jim):
// + One week.
// + Only requests to the same site.
// + Not using sessionStorage so the cookie doesn't leave when the browser dies.
2021-05-06 03:08:14 +03:00
cookies.set(Credentials.session.key, response.token, {
2020-11-20 07:03:30 +03:00
path: "/",
maxAge: 3600 * 24 * 7,
sameSite: "strict",
});
}
return response;
};
2021-05-06 03:08:14 +03:00
// NOTE(jim): Signs a user out
2021-04-07 01:08:42 +03:00
export const signOut = async ({ viewer }) => {
2020-11-19 21:14:09 +03:00
let wsclient = Websockets.getClient();
if (wsclient) {
2021-04-07 01:08:42 +03:00
wsclient.send(JSON.stringify({ type: "UNSUBSCRIBE_VIEWER", data: viewer }));
2020-11-19 21:14:09 +03:00
await Websockets.deleteClient();
wsclient = null;
}
const jwt = cookies.get(Credentials.session.key);
if (jwt) {
2021-05-06 03:08:14 +03:00
cookies.remove(Credentials.session.key, {
path: "/",
maxAge: 3600 * 24 * 7,
sameSite: "strict",
});
2020-11-19 21:14:09 +03:00
}
2021-05-06 03:08:14 +03:00
window.location.replace("/_/auth");
2020-11-19 21:14:09 +03:00
return;
};
// NOTE(jim): Permanently deletes you, forever.
2021-04-20 01:28:57 +03:00
export const deleteMe = async ({ viewer }) => {
2020-11-19 21:14:09 +03:00
await Actions.updateSearch("delete-user");
let response = await Actions.deleteViewer();
if (Events.hasError(response)) {
2020-11-19 21:14:09 +03:00
return response;
}
2021-04-20 01:28:57 +03:00
await signOut({ viewer });
2020-11-19 21:14:09 +03:00
2021-05-06 03:08:14 +03:00
// let wsclient = Websockets.getClient();
// if (wsclient) {
// await Websockets.deleteClient();
// wsclient = null;
// }
2020-11-19 21:14:09 +03:00
return response;
};
2020-11-20 07:03:30 +03:00
export const hydrate = async () => {
const response = await Actions.hydrateAuthenticatedUser();
if (Events.hasError(response)) {
2020-11-20 07:03:30 +03:00
return null;
}
2020-11-22 05:24:26 +03:00
2020-11-20 07:03:30 +03:00
return JSON.parse(JSON.stringify(response.data));
};
2021-02-15 20:32:44 +03:00
export const formatPastedImages = ({ clipboardItems }) => {
2021-02-11 13:31:39 +03:00
let files = [];
let fileLoading = {};
for (let i = 0; i < clipboardItems.length; i++) {
// Note(Amine): skip content if it's not an image
if (clipboardItems[i].type.indexOf("image") === -1) continue;
const file = clipboardItems[i].getAsFile();
files.push(file);
fileLoading[`${file.lastModified}-${file.name}`] = {
name: file.name,
loaded: 0,
total: file.size,
};
}
return { fileLoading, toUpload: files };
};
2021-02-09 11:02:29 +03:00
export const formatDroppedFiles = async ({ dataTransfer }) => {
2020-11-20 07:03:30 +03:00
// NOTE(jim): If this is true, then drag and drop came from a slate object.
const data = dataTransfer.getData("slate-object-drag-data");
if (data) {
return;
}
const files = [];
let fileLoading = {};
if (dataTransfer.items && dataTransfer.items.length) {
for (var i = 0; i < dataTransfer.items.length; i++) {
2021-02-09 12:56:24 +03:00
const data = dataTransfer.items[i];
let file = null;
if (data.kind === "file") {
file = data.getAsFile();
} else if (data.kind == "string" && data.type == "text/uri-list") {
try {
const dataAsString = new Promise((resolve, reject) =>
data.getAsString((d) => resolve(d))
);
const resp = await fetch(await dataAsString);
const blob = resp.blob();
file = new File(blob, `data-${uuid()}`);
file.name = `data-${uuid()}`;
} catch (e) {
Events.dispatchMessage({
message: "File type not supported. Please try a different file",
});
return { error: true };
}
2020-11-20 07:03:30 +03:00
}
2021-02-09 11:02:29 +03:00
files.push(file);
fileLoading[`${file.lastModified}-${file.name}`] = {
name: file.name,
loaded: 0,
total: file.size,
};
2020-11-20 07:03:30 +03:00
}
}
2020-11-24 09:31:52 +03:00
if (!files.length) {
Events.dispatchMessage({ message: "File type not supported. Please try a different file" });
2020-11-24 09:31:52 +03:00
}
2020-11-20 07:03:30 +03:00
return { fileLoading, files, numFailed: dataTransfer.items.length - files.length };
};
export const formatUploadedFiles = ({ files }) => {
let toUpload = [];
let fileLoading = {};
for (let i = 0; i < files.length; i++) {
let file = files[i];
if (!file) {
continue;
}
toUpload.push(file);
fileLoading[`${file.lastModified}-${file.name}`] = {
name: file.name,
loaded: 0,
total: file.size,
};
}
2020-11-24 09:31:52 +03:00
if (!toUpload.length) {
Events.dispatchMessage({ message: "We could not find any files to upload." });
2020-11-24 09:31:52 +03:00
return false;
}
2020-11-20 07:03:30 +03:00
return { toUpload, fileLoading, numFailed: files.length - toUpload.length };
};
2020-11-30 02:47:08 +03:00
export const uploadImage = async (file, resources, excludeFromLibrary) => {
if (!file) {
Events.dispatchMessage({ message: "Something went wrong with the upload. Please try again" });
return;
}
if (!Validations.isPreviewableImage(file.type)) {
Events.dispatchMessage({ message: "Upload failed. Only images and gifs are allowed" });
return;
}
const response = await FileUtilities.upload({ file, routes: resources });
if (Events.hasError(response)) {
return false;
}
return response;
};
export const deleteFiles = async (fileIds = [], noAlert) => {
2020-11-25 12:17:37 +03:00
let ids = Array.isArray(fileIds) ? fileIds : [fileIds];
const response = await Actions.deleteFiles({ ids });
2020-11-30 02:47:08 +03:00
if (!noAlert) {
if (Events.hasError(response)) {
return false;
}
Events.dispatchMessage({ message: "Files successfully deleted!", status: "INFO" });
2020-11-30 02:47:08 +03:00
return response;
}
};
export const removeFromSlate = async ({ slate, ids }) => {
const response = await Actions.removeFileFromSlate({
slateId: slate.id,
ids,
});
if (Events.hasError(response)) {
return false;
}
return response;
};
export const addToSlate = async ({ slate, files }) => {
const addResponse = await Actions.addFileToSlate({ slate, files });
if (Events.hasError(addResponse)) {
return false;
}
const { added, skipped } = addResponse;
let message = Strings.formatAsUploadMessage(added, skipped, true);
Events.dispatchMessage({ message, status: !added ? null : "INFO" });
return true;
};
export const saveCopy = async ({ files }) => {
let response = await Actions.saveCopy({ files });
if (Events.hasError(response)) {
return false;
}
let message = Strings.formatAsUploadMessage(response.data.added, response.data.skipped);
Events.dispatchMessage({ message, status: !response.data.added ? null : "INFO" });
return response;
};
export const download = async (file) => {
Actions.createDownloadActivity({ file });
if (file.data.type === "application/unity") {
return await downloadZip(file);
}
let uri = Strings.getURLfromCID(file.cid);
Window.saveAs(uri, file.filename);
return { data: true };
};
2020-12-25 02:44:47 +03:00
export const downloadZip = async (file) => {
try {
const { data } = await Actions.getZipFilePaths(file);
const filesPaths = data.filesPaths.map((item) => item.replace(`/${file.id}/`, ""));
const baseUrl = Strings.getURLfromCID(file.cid);
const zipFileName = file.filename;
2020-12-25 02:44:47 +03:00
let zip = new JSZip();
2020-12-25 02:44:47 +03:00
2021-03-03 21:36:37 +03:00
await Promise.all(
filesPaths.map(async (filePath) => {
let url = `${baseUrl}/${filePath}`;
const blob = await Window.getBlobFromUrl(url);
zip.file(filePath, blob);
})
);
2020-12-25 02:44:47 +03:00
zip.generateAsync({ type: "blob" }).then((blob) => {
saveAs(blob, zipFileName);
});
return {
decorator: "UNITY_ZIP_DOWNLOAD_SUCCESS",
error: false,
};
} catch (e) {
return {
decorator: "UNITY_ZIP_DOWNLOAD_FAILED",
error: true,
};
}
2020-12-25 02:44:47 +03:00
};
2021-03-05 19:37:46 +03:00
const _nativeDownload = ({ url, onError }) => {
2021-03-05 10:32:08 +03:00
const iframe = document.createElement("iframe");
iframe.style.display = "none";
2021-03-05 19:37:46 +03:00
iframe.src = url;
const ERROR_MESSAGE = "SLATE_DOWNLOAD_ERROR";
const handleIframeErrors = (e) => {
2021-03-05 19:37:46 +03:00
if (e.data === ERROR_MESSAGE && onError) {
onError(e.data);
}
};
window.addEventListener("message", handleIframeErrors);
iframe.onload = (e) => window.removeEventListener("message", handleIframeErrors);
2021-03-05 10:32:08 +03:00
document.body.appendChild(iframe);
2021-03-03 11:48:59 +03:00
};
2021-03-05 10:32:08 +03:00
export const compressAndDownloadFiles = async ({ files, name = "slate.zip", resourceURI }) => {
Actions.createDownloadActivity({ files });
2021-03-05 19:37:46 +03:00
const errorMessage = "Something went wrong with the download. Please try again";
2021-03-03 13:01:34 +03:00
try {
if (!(files && files.length > 0)) {
Events.dispatchMessage({ message: "No files in collection to download" });
return;
}
2021-03-03 13:01:34 +03:00
Events.dispatchMessage({ message: "We're preparing your files to download", status: "INFO" });
let downloadFiles = [];
for (const file of files) {
if (file.type === "application/unity") {
const { data } = await Actions.getZipFilePaths(file);
const unityFiles = data.filesPaths.map((item) => ({
url: item.replace(`/${file.id}/`, `${Strings.getURLfromCID(file.cid)}/`),
name: item.replace(`/${file.id}/`, `/${file.filename}/`),
2021-03-03 13:01:34 +03:00
}));
downloadFiles = downloadFiles.concat(unityFiles);
continue;
}
downloadFiles.push({
name: file.filename,
url: Strings.getURLfromCID(file.cid),
2021-03-03 13:01:34 +03:00
});
2021-03-03 11:48:59 +03:00
}
2021-03-05 10:32:08 +03:00
const res = await Actions.createZipToken({ files: downloadFiles, resourceURI });
const downloadLink = Actions.downloadZip({ token: res.data.token, name, resourceURI });
2021-03-05 19:37:46 +03:00
await _nativeDownload({
2021-03-03 13:01:34 +03:00
url: downloadLink,
2021-03-05 19:37:46 +03:00
onError: (err) =>
Events.dispatchMessage({
message: errorMessage,
}),
2021-03-03 11:48:59 +03:00
});
2021-03-03 13:01:34 +03:00
} catch (e) {
2021-03-05 10:32:08 +03:00
console.error(e);
2021-03-05 19:37:46 +03:00
Events.dispatchMessage({ message: errorMessage });
2021-03-03 11:48:59 +03:00
}
2021-03-02 16:33:10 +03:00
};
2020-11-20 07:03:30 +03:00
// export const createSlate = async (data) => {
// let response = await Actions.createSlate({
// name: data.name,
// isPublic: data.isPublic,
2020-11-20 07:03:30 +03:00
// body: data.body,
// });
// return response;
// }
// export const createWalletAddress = async (data) => {
// let response = await Actions.updateViewer({
// type: "CREATE_FILECOIN_ADDRESS",
// address: {
// name: data.name,
// type: data.wallet_type,
// makeDefault: data.makeDefault,
// },
// });
// return response;
// }
// export const sendWalletAddressFilecoin = (data) => {
// let response = await Actions.sendFilecoin({
// source: data.source,
// target: data.target,
// amount: data.amount,
// });
// return response;
// }