diff --git a/common/actions.js b/common/actions.js index 0dcd8196..3d14dfbd 100644 --- a/common/actions.js +++ b/common/actions.js @@ -69,7 +69,7 @@ export const sendFilecoin = async (data) => { }; export const checkUsername = async (data) => { - return await returnJSON(`/api/users/check`, { + return await returnJSON(`/api/users/check-username`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); @@ -91,13 +91,6 @@ export const removeFromBucket = async (data) => { }); }; -export const getNetworkDirectory = async () => { - await Websockets.checkWebsocket(); - return await returnJSON(`/api/directory`, { - ...DEFAULT_OPTIONS, - }); -}; - export const getSlateById = async (data) => { await Websockets.checkWebsocket(); return await returnJSON(`/api/slates/get`, { @@ -167,25 +160,18 @@ export const search = async (data) => { }); }; -export const createPendingFiles = async (data) => { +export const createFile = async (data) => { await Websockets.checkWebsocket(); - return await returnJSON(`/api/data/create-pending`, { + return await returnJSON(`/api/data/create`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); }; -export const processPendingFiles = async () => { - await Websockets.checkWebsocket(); - return await returnJSON(`/api/data/process-pending`, { - ...DEFAULT_OPTIONS, - body: JSON.stringify(), - }); -}; - export const addFileToSlate = async (data) => { + console.log(data); await Websockets.checkWebsocket(); - return await returnJSON(`/api/slates/add-url`, { + return await returnJSON(`/api/slates/add-file`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); @@ -241,12 +227,12 @@ export const updateSearch = async (data) => { }); }; -export const checkCIDStatus = async (data) => { - return await returnJSON(`/api/data/cid-status`, { - ...DEFAULT_OPTIONS, - body: JSON.stringify({ data }), - }); -}; +// export const checkCIDStatus = async (data) => { +// return await returnJSON(`/api/data/cid-status`, { +// ...DEFAULT_OPTIONS, +// body: JSON.stringify({ data }), +// }); +// }; export const createSlate = async (data) => { await Websockets.checkWebsocket(); @@ -264,6 +250,14 @@ export const updateSlate = async (data) => { }); }; +export const updateSlateLayout = async (data) => { + await Websockets.checkWebsocket(); + return await returnJSON(`/api/slates/update-layout`, { + ...DEFAULT_OPTIONS, + body: JSON.stringify({ data }), + }); +}; + export const deleteSlate = async (data) => { await Websockets.checkWebsocket(); return await returnJSON(`/api/slates/delete`, { @@ -274,7 +268,7 @@ export const deleteSlate = async (data) => { export const removeFileFromSlate = async (data) => { await Websockets.checkWebsocket(); - return await returnJSON(`/api/slates/remove`, { + return await returnJSON(`/api/slates/remove-file`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); @@ -295,15 +289,15 @@ export const deleteAPIKey = async (data) => { }); }; -export const addCIDToData = async (data) => { +export const saveCopy = async (data) => { await Websockets.checkWebsocket(); - return await returnJSON(`/api/data/add`, { + return await returnJSON(`/api/data/save-copy`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); }; -export const updateData = async (data) => { +export const updateFile = async (data) => { await Websockets.checkWebsocket(); return await returnJSON(`/api/data/update`, { ...DEFAULT_OPTIONS, @@ -319,9 +313,9 @@ export const toggleFilePrivacy = async (data) => { }); }; -export const deleteBucketItems = async (data) => { +export const deleteFiles = async (data) => { await Websockets.checkWebsocket(); - return await returnJSON(`/api/data/remove`, { + return await returnJSON(`/api/data/delete`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); @@ -349,7 +343,14 @@ export const createSupportMessage = async (data) => { }; export const getActivity = async (data) => { - return await returnJSON(`/api/activity/get`, { + return await returnJSON(`/api/activity/get-activity`, { + ...DEFAULT_OPTIONS, + body: JSON.stringify({ data }), + }); +}; + +export const getExplore = async (data) => { + return await returnJSON(`/api/activity/get-explore`, { ...DEFAULT_OPTIONS, body: JSON.stringify({ data }), }); diff --git a/common/browser-websockets.js b/common/browser-websockets.js index e86e966a..71216ea6 100644 --- a/common/browser-websockets.js +++ b/common/browser-websockets.js @@ -30,8 +30,9 @@ export const init = ({ resource = "", viewer, onUpdate, onNewActiveUser = () => return null; } - const payload = { type: "SUBSCRIBE_VIEWER", data: viewer }; - + const payload = { type: "SUBSCRIBE_VIEWER", data: { id: viewer.id } }; + console.log(payload); + console.log("inside browser websockets init"); client.send(JSON.stringify(payload)); }); diff --git a/common/file-utilities.js b/common/file-utilities.js index e902897e..50f7d55a 100644 --- a/common/file-utilities.js +++ b/common/file-utilities.js @@ -126,6 +126,7 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib }); } }; + console.log(formData); XHR.send(formData); }); @@ -152,7 +153,7 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib res = await _privateUploadMethod(`${generalRoute}${file.name}`, file); } - if (!res || res.error || !res.data) { + if (!res?.data || res.error) { if (context) { await context.setState({ fileLoading: { @@ -169,43 +170,16 @@ export const upload = async ({ file, context, bucketName, routes, excludeFromLib return !res ? { decorator: "NO_RESPONSE_FROM_SERVER", error: true } : res; } - if (res.data.data.type.startsWith("image/")) { - let url = `${Constants.gateways.ipfs}/${res.data.data.cid}`; + let item = res.data.data; + if (item.data.type.startsWith("image/")) { + let url = Strings.getURLfromCID(item.cid); try { let blurhash = await encodeImageToBlurhash(url); - res.data.data.blurhash = blurhash; + item.data.blurhash = blurhash; } catch (e) { console.log(e); } } - if (!excludeFromLibrary) { - await Actions.createPendingFiles({ data: res.data }); - } - - res.data = res.data.data; - - return { file, json: res }; -}; - -export const uploadToSlate = async ({ responses, slate }) => { - let added; - let skipped; - if (responses && responses.length) { - const addResponse = await Actions.addFileToSlate({ - slate, - data: responses.map((res) => { - return { title: res.file.name, ...res.json.data }; - }), - }); - - if (Events.hasError(addResponse)) { - return; - } - - added = addResponse.added; - skipped = addResponse.skipped; - } - let message = Strings.formatAsUploadMessage(added, skipped, true); - Events.dispatchMessage({ message, status: !added ? null : "INFO" }); + return item; }; diff --git a/common/messages.js b/common/messages.js index bdb31cc6..0d2e1071 100644 --- a/common/messages.js +++ b/common/messages.js @@ -1,354 +1,190 @@ export const error = { - //Slate Create - SERVER_FIND_USER_CREATE_SLATE: "There seems to be an issue with your account", - SERVER_FIND_USER_CREATE_SLATE_USER_NOT_FOUND: "Login to create a Slate!", - SERVER_EXISTING_SLATE: "You already have a slate with that name. Please choose another", - SERVER_CREATE_SLATE: "There was an error when creating the Slate", - FIND_USER_CREATE_SLATE: "There seems to be an issue with your account", - FIND_USER_CREATE_SLATE_USER_NOT_FOUND: "Login to create a Slate!", - EXISTING_SLATE: "A Slate with that name already exists. Please try another", - CREATE_SLATE: "There was an error when creating the Slate", - SERVER_SLATE_LIMIT: "You've reached the limit for number of slates!", + //General + SERVER_NOT_AUTHENTICATED: + "You are not currently logged in. Please refresh the page and sign in to perform this action", + SERVER_USER_NOT_FOUND: "We're having trouble locating your information right now", + SERVER_NO_BUCKET_DATA: "We ran into issues while trying to locate your data", - //Slate Add URL - ADD_TO_SLATE_USER_NOT_FOUND: "Login to add a Slate URL", - ADD_TO_SLATE_SLATE_NOT_FOUND: "Sorry, we couldn't find that Slate! Please try another", - ADD_TO_SLATE_ERROR: "There was an error retriving this Slate", + //Activity and explore + SERVER_GET_ACTIVITY_NOT_FOUND: "We're having trouble loading activity right now", + SERVER_GET_EXPLORE_NOT_FOUND: "We're having trouble loading explore right now", - //Slate remove file - SERVER_REMOVE_FROM_SLATE_USER_NOT_FOUND: "Login to manage your slates", - SERVER_REMOVE_FROM_SLATE_NO_ID_PROVIDED: "Please specify which item you would like to remove", - SERVER_REMOVE_FROM_SLATE_SLATE_NOT_FOUND: "We're having trouble locating that slate", - SERVER_REMOVE_FROM_SLATE_ERROR: "We're having trouble removing from this slate right now", + //Filecoin and archiving + SERVER_SEND_FILECOIN_ACTION_FAILURE: "We're having trouble sending out Filecoin right now", + SERVER_ARCHIVE_NO_FILES: "You have no files to archive", + SERVER_ARCHIVE_BUCKET_TOO_SMALL: + "Your deal size is too small to archive. Deals should be a minimum of 100MB", + SERVER_ARCHIVE_BUCKET_COUNT_VERIFICATION_FAILED: + "We ran into issues while verifying your ability to make storage deals", + SERVER_ARCHIVE_MAX_NUMBER_BUCKETS: + "You have reached the maximum number of storage deals for this account", + SERVER_ARCHIVE_ENCRYPTION_FAILED: + "We encountered issues while encrypting your files for archiving", + SERVER_ARCHIVE_BUCKET_CLONING_FAILED: + "We ran into issues while replicating your files for archiving", + SERVER_ARCHIVE_DEAL_FAILED: "The storage deal wasn't successful", - //Slate Delete - DELETE_SLATE_BY_ID: - "Sorry, there was an error while trying to delete that slate. Please try again", - DELETE_SLATES_FOR_USER_ID: - "Sorry, we're having trouble deleting all your slates. Please try again later", - SERVER_DELETE_SLATE: "We're having trouble deleting that at the moment. Please try again later", - SERVER_DELETE_SLATE_USER_NOT_FOUND: "Login to manage your slates!", + //Bucket remove + SERVER_BUCKET_REMOVE_NO_CID: + "We ran into issues while removing a file. There was no file specified", + SERVER_BUCKET_REMOVE_BUCKET_NOT_FOUND: "We couldn't locate your files to delete", + SERVER_BUCKET_REMOVE_NO_BUCKET_ITEMS: "We couldn't locate your files to delete", + SERVER_BUCKET_REMOVE_NO_MATCHING_CID: "There were no matching files found", + SERVER_BUCKET_REMOVE_FAILED: "We were not able to delete that file", + + //File create + CREATE_FILE_NO_FILE_PROVIDED: "We ran into issues while creating a file. No file was provided", + CREATE_FILE_DUPLICATE: "The uploaded file(s) were duplicates and were skipped", + CREATE_FILE_FAILED: "We ran into issues while creating that file", + + //File delete + SERVER_REMOVE_DATA_NO_IDS: "The file to delete was not specified", + + //Save copy + SERVER_SAVE_COPY_NO_CIDS: "The file to save was not specified", + + //Toggle file privacy + SERVER_TOGGLE_FILE_PRIVACY_NO_FILE: + "We ran into issues while editing a file's privacy. No file was specified", + SERVER_TOGGLE_FILE_PRIVACY_UPDATE_FAILED: + "We're having trouble updating the privacy of that file right now", + + //Update file + SERVER_EDIT_DATA_NO_FILE: "We ran into issues while editing a file. No file was provided", + SERVER_EDIT_DATA_FAILED: "We're having trouble updating that file right now", + + //Delete api key + SERVER_DELETE_API_KEY_NOT_FOUND: + "We weren't able to locate that API key. It may have already been deleted", + SERVER_DELETE_API_KEY_ERROR: "We weren't able to delete that API key. Please try again later", + + //Create api key + SERVER_GENERATE_API_KEY_TOO_MANY_KEYS: "You've reached the limit for number of API keys", + SERVER_GENERATE_API_KEY_ERROR: + "We're having trouble generating an API key right now, please try again later", + + //Add to slate + SERVER_ADD_TO_SLATE_NO_SLATE: + "We ran into issues while adding files to that slate. No slate was specified", + SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND: "We're having trouble locating that slate right now", + SERVER_ADD_TO_SLATE_NO_FILES: + "We ran into issues while adding files to that slate. No files selected", + SERVER_ADD_TO_SLATE_FAILED: "We're having trouble adding those files to that slate right now", + + //Slate create + SERVER_CREATE_SLATE_EXISTING_SLATE_NAME: + "You already have a slate with that name. Slate names must be unique", + SERVER_CREATE_SLATE_FAILED: + "We are having trouble creating that slate right now, please try again later", + + //Slate delete SERVER_DELETE_SLATE_SLATE_NOT_FOUND: - "We're having trouble deleting that at the moment. Please try again later", - SERVER_DELETE_SLATE: "We're having trouble deleting that at the moment. Please try again later", + "We're having difficulty locating that slate. It may have already been deleted", + SERVER_DELETE_SLATE_FAILED: + "We're having trouble deleting that slate right now, please try again later", - //Slate Get - GET_SLATE_BY_ID: - "We're having trouble retrieving information on that slate right now. Please try again later", - GET_SLATE_BY_NAME: - "We're having trouble retrieving information on that slate right now. Please try again later", - GET_SLATES_BY_USER_ID: - "We're having trouble retrieving that user's information. Please try again later", - SLATE_NOT_FOUND: "That slate could not be found. It may have been deleted", - SLATE_OWNER_NOT_FOUND: - "We're having trouble retrieving that slate's owner right now. Please try again", - SERVER_GET_SLATE_USER_NOT_FOUND: - "We're having trouble retrieving that slate's owner right now. Please try again", - SERVER_GET_SLATE: - "We're having trouble retrieving information on that slate right now. Please try again later", + //Get slate + SERVER_GET_SERIALIZED_SLATE_SLATE_NOT_FOUND: + "We were unable to locate that slate. It may be private or it may not exist", + SERVER_GET_SERIALIZED_SLATE_PRIVATE_ACCESS_DENIED: + "We were unable to locate that slate. It may be private or it may not exist", SERVER_GET_SLATE_NOT_FOUND: - "We're having trouble retrieving information on that slate right now. Please try again later", + "We were unable to locate that slate. It may be private or it may not exist", + SERVER_GET_SLATE_PRIVATE_ACCESS_DENIED: + "We were unable to locate that slate. It may be private or it may not exist", - //Slate Update - UPDATE_SLATE_BY_ID: "We ran into an issue while saving your slate. Please try again", - SERVER_ADD_TO_SLATE_USER_NOT_FOUND: "Login to upload files!", - SERVER_FIND_USER_UPDATE_SLATE_USER_NOT_FOUND: "Login to upload files!", - SERVER_ADD_TO_SLATE_SLATE_NOT_FOUND: - "We ran into issues while uploading that file. Please try again", - SERVER_ADD_TO_SLATE_ERROR: "We ran into issues while uploading that file. Please try again", - SERVER_FIND_USER_UPDATE_SLATE: "We ran into issues while uploading that file. Please try again", - SERVER_UPDATE_SLATE_NOT_FOUND: "We ran into issues while locating that slate. Please try again", - SERVER_UPDATE_SLATE_MUST_PROVIDE_DATA: "The input cannot be blank. Please check your input", - SERVER_UPDATE_SLATE_MUST_PROVIDE_NAME: "Please provide a slate name", - SERVER_UPDATE_SLATE: "We're having trouble updating that slate right now. Please try again later", - SERVER_UPDATE_SLATE_NAME_TAKEN: "You already have a slate with that name. Please choose another", - V1_SERVER_UPLOAD_SLATE_NOT_FOUND: - "We're having trouble locating that slate right now. Please try again later", - V1_SERVER_API_KEY_NOT_FOUND: - "We can't seem to find your API key right now. Please try again later", - V1_SERVER_API_UPLOAD_ERROR: - "We're having trouble uploading that right now. Please try again later", - V1_SERVER_UPLOAD_SLATE_NOT_FOUND: "We're having trouble locating that slate right now", - V1_SERVER_UPLOAD_TO_SLATE_ERROR: - "We're ran into issues while adding that to the slate. Please try again", - V1_GET_SLATE_NOT_FOUND: - "We're having trouble locating that slate right now. Please try again later", - V1_GET_SLATE_USER_NOT_FOUND: - "We're having trouble locating the owner of that slate right now. Please try again later", - V1_GET_SLATE_SLATE_NOT_FOUND: - "We're having trouble locating that slate right now. Please try again later", - V1_GET_SLATES_NOT_FOUND: - "We're having trouble locating those slates right now. Please try again later", + //Remove from slate + SERVER_REMOVE_FROM_SLATE_NO_ID_PROVIDED: + "Unable to remove from slate because no slate was specified", + SERVER_REMOVE_FROM_SLATE_SLATE_NOT_FOUND: "We are having trouble locating that slate", + SERVER_REMOVE_FROM_SLATE_FAILED: "We are having trouble removing from that slate right now", - //Address Send - SERVER_SEND_FILECOIN_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - SERVER_SEND_FILECOIN_NO_ID: "That user doesn't seem to exist. Please try another", - SERVER_SEND_FILECOIN_ACTION_FAILURE: - "There was an error sending the transaction. We're looking into it", - SEND_FILECOIN_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - SEND_FILECOIN: "There was an error sending the transaction. We're looking into it", - SEND_FILECOIN_ACTION_FAILURE: "There was an error sending the transaction. We're looking into it", + //Update slate layout + SERVER_UPDATE_SLATE_LAYOUT_MUST_PROVIDE_DATA: "No layout was provided to update", + SERVER_UPDATE_SLATE_LAYOUT_NOT_FOUND: "We are having trouble locating that slate", + SERVER_UPDATE_SLATE_LAYOUT: + "We are unable to update that slate's layout right now. Please try again later", - //Address Create - CREATE_FILECOIN_ADDRESS: "There was an error when creating the Filecoin address.", + //Update slate + SERVER_UPDATE_SLATE_MUST_PROVIDE_DATA: + "We are unable to update that slate because no data was provided", + SERVER_UPDATE_SLATE_NOT_FOUND: "We are having trouble locating that slate", + SERVER_UPDATE_SLATE_UPDATE_PRIVACY_FAILED: + "We are having trouble updating the privacy of that slate", + SERVER_UPDATE_SLATE_INVALID_NAME: "Please use a valid slate name", + SERVER_UPDATE_SLATE_NAME_TAKEN: + "You already have a slate with that name. Slate names must be unique", + SERVER_UPDATE_SLATE_FAILED: "We are having trouble updating that slate right now", - //Data Upload - UPLOAD_PARSE_FAILURE: "There was an error when parsing the upload. Please try again", - UPLOAD_NOT_IMAGE_TYPE: - "We are only accepting JPG and PNG files at this time. Try uploading a different file type!", - BUCKETS_PUSH_ISSUE: "There was an error uploading the data", - SERVER_UPLOAD_ERROR: "We're having issues uploading that file right now", - SERVER_API_KEY_MISSING: "We can't seem to find your API key right now. Please try again later", - CREATE_PENDING_DATA: "We ran into issues while uploading your data, please try again later", - CREATE_PENDING_ERROR: "We ran into issues while uploading your data, please try again later", - PROCESS_PENDING_ERROR: - "We ran into an error while updating your uploaded data. Please try again later", - PROCESS_PENDING_USER_NOT_FOUND: "Please log in to upload files", + //Create user + SERVER_CREATE_USER_NOT_ALLOWED: "You can only create users while on slate.host", + SERVER_CREATE_USER_ACCEPT_TERMS: "You must accept the terms of service to create an account", + SERVER_CREATE_USER_USERNAME_TAKEN: "There is already an account with that username", + SERVER_CREATE_USER_INVALID_USERNAME: "Please choose a valid username", + SERVER_CREATE_USER_INVALID_PASSWORD: "Please chooose a valid password", + SERVER_CREATE_USER_BUCKET_INIT_FAILURE: + "We're having trouble setting up your storage, please try again later", + SERVER_CREATE_USER_FAILED: + "We're having trouble creating your account right now. Please try again later", - //Data CID Status - NO_CIDS_TO_CHECK: "There are no CIDs to check", + //Get user + SERVER_GET_USER_NO_USER_PROVIDED: + "We were not able to fetch that user because no user was specified", + SERVER_GET_USER_USER_NOT_FOUND: "We were not able to locate that user", - //Data Get - SERVER_GET_BUCKET_DATA: "We ran into an issue fetching that data. Please try again later", + //Get user social + SERVER_USER_SOCIAL_NO_USER_ID: + "We were not able to fetch that user's subscriptions and following because no user was specified", + SERVER_USER_SOCIAL_SUBSCRIPTIONS_NOT_FOUND: + "We were not able to locate that user's subscriptions", + SERVER_USER_SOCIAL_FOLLOWING_NOT_FOUND: "We were not able to locate that user's following", + SERVER_USER_SOCIAL_FOLLOWERS_NOT_FOUND: "We were not able to locate that user's followers", - //Data Remove - SERVER_REMOVE_DATA_NO_CID: - "Slate is having trouble deleting some files right now. We're working on fixing this soon!", - SERVER_REMOVE_DATA_NOT_ALLOWED: "You aren't authorized to remove that file", - SERVER_REMOVE_DATA_NO_LINK: "We couldn't remove that data. Please try again later", + //Status update + SERVER_STATUS_UPDATE_FAILED: "We're having trouble making that change right now", + SERVER_STATUS_UPDATE_MUST_PROVIDE_UPDATE: "No update was provided", - //Data Storage Deals - SERVER_STORAGE_DEAL_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - SERVER_NO_CID: "IPFS CID is required", - SERVER_NO_IPFS: "There was a issue retriving data from IPFS", - SERVER_FILECOIN_STORAGE_DEAL_CID_ERROR: "There was a issue making a storage deal", - SERVER_NO_JOB: "Sorry, this job doesn't exist!", - STORAGE_DEAL_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - NO_CID: "IPFS CID is required", - NO_IPFS: "There was a issue retriving data from IPFS", - FILECOIN_STORAGE_DEAL_CID_ERROR: "There was a issue making a storage deal", - NO_JOB: "Sorry, this job doesn't exist!", + //Update user + SERVER_USER_UPDATE_INVALID_USERNAME: "Please choose a valid username", + SERVER_USER_UPDATE_USERNAME_IS_TAKEN: "There is already an account with that username", + SERVER_USER_UPDATE_DEFAULT_ARCHIVE_CONFIG: + "We're having trouble updating your settings right now", + SERVER_USER_UPDATE_INVALID_PASSWORD: "Please chooose a valid password", - //Archive Deal - SERVER_REMOVE_DATA_NOT_ALLOWED: "Please login first to archive a deal!", - SERVER_BUCKET_ARCHIVE_DEAL_USER_NOT_FOUND: "Please login first to archive a deal!", - SERVER_BUCKET_INIT_FAILURE: "Something went wrong while locating your storage bucket", - STORAGE_DEAL_MAKING_NO_BUCKET: "We could not locate your storage bucket", - STORAGE_DEAL_MAKING_NO_FILES: "No file selected. Please select a file to archive then try again", - STORAGE_BUCKET_TOO_SMALL: "Deal size too small. Deals must be 100MB or larger", - BUCKET_SPAWN_VERIFICATION_FAILED_FOR_BUCKET_COUNT: - "We ran into an issue while verifying how much storage space you have", - TOO_MANY_BUCKETS: "You've reached the maximum number of storage buckets for an account", - FORCED_ENCRYPTION_FAILED_FOR_DATA: "We ran into an issue while encrypting your data", - BUCKET_CLONING_FAILED: "We ran into an issue while creating a storage bucket for you", - STORAGE_DEAL_MAKING_NOT_SANITARY: "We ran into an issue while creating that storage deal", - - //CID Status - SERVER_NO_CIDS_TO_CHECK: "No CIDs were entered, please check your input", - - //Users Create - SIGN_UP_RATE_LIMITED: "Too many sign up attempts. Please try again in 10 minutes", - SERVER_EXISTING_USER_ALREADY: "That username is taken. Please try another one", - EXISTING_USER_ALREADY: "That username is taken. Please try another one", - INVALID_USERNAME: "Invalid username. Please include only letters and numbers", - SERVER_INVALID_USERNAME: "Invalid username. Please include only letters and numbers", - INVALID_PASSWORD: "Password length must be more than 8 characters", - SERVER_INVALID_PASSWORD: "Password length must be more than 8 characters", - USER_CREATE_USER_NOT_FOUND: "Sorry we weren't able to create your account. Please try again", - SERVER_USER_CREATE_USER_NOT_FOUND: - "Sorry we weren't able to create your account. Please try again", - CREATE_USER: "Sorry we weren't able to create your account. Please try again", - - //Users Delete - USER_DELETE: "That user doesn't seem to exist. Please try another", - SERVER_USER_DELETE: "That user doesn't seem to exist. Please try another", - USER_DELETE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - SERVER_USER_DELETE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - DELETE_USER_BY_USERNAME: "We're having trouble deleting your account right now", - SERVER_USER_DELETE: "We're having trouble deleting your account right now", - USER_NOT_FOUND: "We're having trouble connecting right now", - SLATES_NOT_FOUND: "We weren't able to locate the slates for that user", - - //Users Update - USER_UPDATE: "That user doesn't seem to exist. Please try another", - USER_UPDATE_USER_NOT_FOUND: "Sorry, we couldn't find that user!", - UPDATE_USER_BY_ID: "We ran into an issue while updating your information. Please try again", - USER_UPDATE_SETTINGS_CONFIG: "Error when updating user settings", - SERVER_USER_UPDATE: "Please make sure you are signed in first", - SERVER_USER_UPDATE_USER_NOT_FOUND: - "We're having trouble locating your information. Please try again", - SERVER_STATUS_UPDATE: "Please log in first to access this page", - SERVER_STATUS_UPDATE_USER_NOT_FOUND: "We're having trouble locating your information right now", - SERVER_STATUS_UPDATE_MUST_PROVIDE_UPDATE: - "We're having trouble updating your information right now", - SERVER_USERNAME_IS_TAKEN: "That username is taken", - - //Users Get - GET_USER_BY_ID: "We weren't able to fetch information on that user. Please try again later", - GET_USER_BY_USERNAME: - "We weren't able to fetch information on that user. Please check your input", - USER_NOT_FOUND: "We aren't able to locate that user at the moment. Please try again", - SERVER_USER_SUBSCRIPTIONS_NOT_FOUND: - "We weren't able to fetch information on that user. Please try again later", - SERVER_USER_SUBSCRIBERS_NOT_FOUND: - "We weren't able to fetch information on that user. Please try again later", + //Zip files + GET_ZIP_FILES_PATHS_BUCKET_CHECK_FAILED: "We're having trouble locating those files right now", //Hydrate - HYDRATE_FAILURE: "Please make sure you're logged in", - SERVER_HYDRATE_FAILURE: "Please make sure you're logged in", SERVER_VIEWER_DATA_ERROR: - "We're havign trouble fetching your information right now. Please try again", + "We're having trouble fetching your information right now, please refresh the page", - //Sign-in - SIGN_IN_RATE_LIMITED: "Too many sign in attempts. Please try again in 10 minutes", - SIGN_IN: "Your username/password can't be blank", - SERVER_SIGN_IN: "Your username/password can't be blank", - SIGN_IN_USER_NOT_FOUND: "We're having trouble logging you in right now, please try again later", - SERVER_SIGN_IN_USER_NOT_FOUND: "That username and password do not match", //no one with that username - SERVER_SIGN_IN_ERROR: "We're having trouble connecting right now. Please try again later", - SERVER_SIGN_IN_AUTH: "That username and password do not match", //incorrect password + //Get deals + SERVER_FILECOIN_NETWORK_DEALS_ERROR: + "We're having trouble fetching your deal information right now", + SERVER_FILECOIN_NETWORK_ERROR: "We're having trouble fetching your storage information right now", - //Activity - CREATE_ACTIVITY: "We're having issues posting that right now. Please try again", - DELETE_ACTIVITY_BY_ID: "We weren't able to delete that. Please try again", - GET_ACTIVITY_BY_ID: "We weren't able to fetch that information. Please try again", - GET_ACTIVITY_FOR_SLATE_ID: "We weren't able to fetch that information. Please try again", - GET_ACTIVITY_FOR_USER_ID: "We weren't able to fetch that user's information. Please try again", - SERVER_GET_ACTIVITY_NOT_FOUND: "We're having trouble fetching your feed right now", - SERVER_GET_ACTIVITY_USER_NOT_FOUND: "Please login to view your feed", + //Sign in + SERVER_SIGN_IN_NOT_ALLOWED: "You can only sign in to an account while on slate.host", + SERVER_SIGN_IN_NO_USERNAME: "Please provide a username to sign in", + SERVER_SIGN_IN_NO_PASSWORD: "Please provide a password to sign in", + SERVER_SIGN_IN_USER_NOT_FOUND: "We were unable to locate that account with those credentials", + SERVER_SIGN_IN_WRONG_PASSWORD: "We were unable to locate that account with those credentials", - //Subscription Create - CREATE_SUBSCRIPTION: "We weren't able to subscribe you. Please try again later", - SERVER_SUBSCRIBE: "Please login to subscribe", - SERVER_SUBSCRIBE_USER_NOT_FOUND: - "We're having trouble fetching your information. Please try again later", - SERVER_SUBSCRIBE_MUST_PROVIDE_SLATE_OR_USER: - "No user or slate was provided. Please check your input", - SERVER_SUBSCRIBE_CAN_NOT_SUBSCRIBE_TO_YOURSELF: "You cannot subscribe to yourself", - SERVER_SUBSCRIBE_TARGET_USER_NOT_FOUND: "That user could not be found", - SERVER_SUBSCRIBE_TARGET_SLATE_NOT_FOUND: "That slate could not be found", + //Subscribe + SERVER_SUBSCRIBE_MUST_PROVIDE_SLATE_OR_USER: "No slate or user to follow specified", + SERVER_SUBSCRIBE_CAN_NOT_SUBSCRIBE_TO_YOURSELF: "You cannot follow yourself", + SERVER_SUBSCRIBE_TARGET_USER_NOT_FOUND: "We are unable to locate that user", + SERVER_SUBSCRIBE_TARGET_SLATE_NOT_FOUND: "We are unable to locate that slate", SERVER_SUBSCRIBE_SUBSCRIPTION_CHECK_ERROR: - "We weren't able to subscribe you. Please try again later", - SERVER_UNSUBSCRIBE_NOT_FOUND: "We weren't able to unsubscribe you. Please try again", - SERVER_UNSUBSCRIBE_ERROR: "We weren't able to unsubscribe you. Please try again", - SERVER_SUBSCRIBE_NOT_FOUND: "We weren't able to subscribe you. Please try again", - SERVER_SUBSCRIBE_ERROR: "We weren't able to subscribe you. Please try again", - - //Subscription Delete - DELETE_SUBSCRIPTION_BY_ID: "We weren't able to unsubscribe you. Please try again later", - - //Subscription Get - GET_SUBSCRIBERS_BY_USER_ID: - "We weren't able to retrieve that information. Please try again later", - GET_SUBSCRIPTION_BY_ID: - "We weren't able to retrieve that subscription information. Please try again later", - GET_SUBSCRIPTIONS_BY_USER_ID: - "We weren't able to retrieve that information. Please try again later", - GET_SUBSCRIPTIONS_TO_SLATE_ID: - "We weren't able to retrieve that information. Please try again later", - GET_SUBSCRIPTIONS_TO_USER_ID: - "We weren't able to retrieve that information. Please try again later", - - //Trusted Create - CREATE_TRUSTED_RELATIONSHIP: - "We weren't able to add this user as trusted. Please try again later", - SERVER_TRUST: "Please make sure you are logged in", - SERVER_TRUSTED_RELATIONSHIP_USER_NOT_FOUND: - "We are having trouble retrieving your information right now", - SERVER_TRUSTED_RELATIONSHIP_MUST_PROVIDE_SOMEONE_TO_TRUST: "No user was specified", - SERVER_TRUSTED_RELATIONSHIP_CAN_NOT_TRUST_YOURSELF: "You cannot add yourself as trusted", - SERVER_TRUSTED_RELATIONSHIP_TARGET_USER_NOT_FOUND: - "We could not locate that user. Please try again later", - SERVER_TRUSTED_RELATIONSHIP_CHECK_ERROR: - "We're having trouble adding this person as your trusted right now", - SERVER_TRUSTED_RELATIONSHIP_INVERTED_CHECK_ERROR: - "You have already received a trust request from this person. Please accept it instead", - SERVER_DELETE_TRUSTED_RELATIONSHIP_NOT_FOUND: "There is no trust relationshp to delete", - SERVER_DELETE_TRUSTED_RELATIONSHIP_ERROR: - "We're having trouble deleting this trust relationship right now", - SERVER_TRUSTED_RELATIONSHIP_NOT_FOUND: - "We're having trouble creating this trust relationship right now", - SERVER_TRUSTED_RELATIONSHIP_ERROR: - "We're having trouble creating this trust relationship right now", - - //Trusted Delete - DELETE_TRUSTED_RELATIONSHIP_BY_ID: - "We weren't able to remove this user from your trusted. Please try again later", - SERVER_TRUST_DELETE: "Please login to manage your trusted", - SERVER_TRUST_DELETE_USER_NOT_FOUND: "We weren't able to locate this user. Please try again later", - SERVER_TRUST_DELETE_MUST_PROVIDE_ID: "Please check your input", - - //Trusted Get - GET_TRUSTED_RELATIONSHIP_BY_ID: - "We're having trouble retrieving that information right now. Please try again later", - GET_TRUSTED_RELATIONSHIP_BY_IDS: - "We're having trouble retrieving that information right now. Please try again later", - GET_TRUSTED_RELATIONSHIPS_BY_USER_ID: - "We're having trouble retrieving that information right now. Please try again later", - - //Trusted Update - UPDATE_TRUSTED_RELATIONSHIP_BY_ID: - "We ran into an issue while updating that information. Please try again later", - SERVER_TRUST_UPDATE: "Please login to mange your trusted", - SERVER_TRUST_UPDATE_USER_NOT_FOUND: - "We weren't able to locate your information. Please try again later", - SERVER_TRUST_UPDATE_MUST_PROVIDE_SOMEONE_TO_TRUST: - "Please check your input. No user was provided", - SERVER_TRUST_UPDATE_CAN_NOT_TRUST_YOURSELF: "You cannot add yourself as a trusted peer", - SERVER_TRUST_UPDATE_TARGET_USER_NOT_FOUND: - "We weren't able to locate that user. Please try again later", - SERVER_TRUST_UPDATE_CHECK_ERROR: "This person is already among your trusted peers", - - //API Key Create - CREATE_API_KEY_FOR_USER_ID: - "We're having trouble creating your API keys right now. Please try again", - SERVER_GENERATE_API_KEY_AUTH: "You aren't authorized to create that API key", - SERVER_GENERATE_API_KEY_USER_NOT_FOUND: - "We ran into issues finding your information while trying to generate that API key", - SERVER_GENERATE_API_KEY_TOO_MANY_KEYS: "You have reached the limit for number of API keys", - SERVER_GENERATE_API_KEY_ERROR: "We ran into issues while trying to generate that API key", - - //API Key Delete - DELETE_API_KEY_BY_ID: - "We're having trouble deleting that API key right now. Please try again later", - DELETE_API_KEYS_FOR_USER_ID: - "We're having trouble deleting your API keys right now. Please try again later", - SERVER_DELETE_API_KEY_AUTH: "You aren't authorized to delete that API key", - SERVER_DELETE_API_KEY_USER_NOT_FOUND: "No matching API key was found for that user", - SERVER_DELETE_API_KEY_NOT_FOUND: "No matching API key was found for that user", - SERVER_DELETE_API_KEY_ERROR: - "We ran into an issue while trying to delete that API key. Please try again", - - //API Key Get - GET_API_KEY_BY_KEY: "We weren't able to fetch that API key. Please try again later", - GET_API_KEY: "We weren't able to fetch that API key. Please try again later", - GET_API_KEYS_BY_USER_ID: - "We're having trouble retrieving your API keys right now. Please try again", - - //Query - SERVER_DEEPLINK: "This slate or profile does not exist", - SERVER_DEEPLINK_ERROR: "This slate or profile does not exist", - SERVER_SEARCH_NO_QUERY: "No query was entered. Please enter a query and try again", - - // Storage Deals - SERVER_BUCKET_INIT_FAILURE: "Something went wrong with our infrastructure. Check in later.", - STORAGE_DEAL_MAKING_NO_BUCKET: "Something went wrong with our infrastructure. Check in later.", - STORAGE_DEAL_MAKING_NO_FILES: "You must provide files before you make a deal.", + "We are having trouble editing that subscription right now", + SERVER_UNSUBSCRIBE_FAILED: "We were unable to unsubscribe, please try again later", + SERVER_SUBSCRIBE_FAILED: "We were unable to subscribe, please try again later", //Support - SERVER_SUPPORT: "You must be logged in to send a support message. Please try logging in again", - SERVER_SUPPORT_USER_NOT_FOUND: "We're having difficulty locating your information right now", - SERVER_SUPPORT_NO_DATA_PROVIDED: "We're having trouble transmitting your message right now", - SERVER_SUPPORT_MUST_PROVIDE_EMAIL: "Please provide an email where we can contact you", - SERVER_SUPPORT_MUST_PROVIDE_MESSAGE: "Please provide a message to send", - SERVER_SUPPORT: "We're having trouble sending your support message to the team right now", - - // Unity game download + SERVER_SUPPORT_NO_DATA_PROVIDED: "Please include details for us to send a support message", + SERVER_SUPPORT_MUST_PROVIDE_EMAIL: "Please include an email where we can reach you", + SERVER_SUPPORT_MUST_PROVIDE_MESSAGE: "Please include a support message", + SERVER_SUPPORT_NO_USERNAME_PROVIDED: "Please include a username", UNITY_ZIP_DOWNLOAD_FAILED: - "We're having trouble downloading you Unity game file. Please try again", - - // Delete tag - SERVER_DELETE_TAG_USER_NOT_FOUND: - "We're having trouble retrieving that slate's owner right now. Please try again", - SERVER_DELETE_TAG_SLATES_NOT_FOUND: "We weren't able to locate the slates for that user", + "We're having trouble downloading your Unity game file. Please try again later", }; diff --git a/common/navigation-data.js b/common/navigation-data.js index af44e5e9..40a09613 100644 --- a/common/navigation-data.js +++ b/common/navigation-data.js @@ -88,23 +88,6 @@ export const navigation = [ pageTitle: "Slate", ignore: true, }, - /* - { - id: "V1_NAVIGATION_LOCAL", - decorator: "LOCAL_DATA", - name: "Local", - pageTitle: "Your local data", - children: [], - ignore: false, - }, - { - id: "V1_NAVIGATION_NETWORK", - decorator: "NETWORK", - name: "Network", - pageTitle: "The Filecoin Network", - children: null, - }, - */ { id: "NAV_FILECOIN", decorator: "FILECOIN", diff --git a/common/schema.js b/common/schema.js new file mode 100644 index 00000000..526d81b5 --- /dev/null +++ b/common/schema.js @@ -0,0 +1,133 @@ +//NOTE(martina): update this file anytime you add a new item to the user, file, or slate data blobs + +export const userSchema = { + id: true, + username: true, + data: { + photo: true, + body: true, + name: true, + tokens: true, + settings: true, + onboarding: true, + status: true, + }, +}; + +export const coverImageSchema = { + id: true, + cid: true, + createdAt: true, + data: { + file: true, + name: true, + size: true, + type: true, + blurhash: true, + }, +}; + +//add: downloads, tags +export const fileSchema = { + id: true, + ownerId: true, + cid: true, + isPublic: true, + createdAt: true, + filename: true, + data: { + name: true, + size: true, + type: true, + blurhash: true, + coverImage: coverImageSchema, + body: true, + source: true, + author: true, + unity: { + config: true, + loader: true, + }, + downloads: true, + tags: true, + link: true, + }, +}; + +//add: tags +export const slateSchema = { + id: true, + slatename: true, + ownerId: true, + isPublic: true, + data: { + name: true, + body: true, + layouts: true, + preview: true, + tags: true, + }, +}; + +/* +Users +[ + 'body', + 'photo', + 'tokens', + 'library', + 'settings_deals_auto_approve', + 'allow_automatic_data_storage', + 'allow_encrypted_data_storage', + 'allow_filecoin_directory_listing', + 'name', + 'status', + 'onboarding', + 'description' +] +[ + 'id', 'cid', + 'date', 'file', + 'icon', 'ipfs', + 'name', 'size', + 'type', 'decorator', + 'blurhash', 'unityGameConfig', + 'unityGameLoader', 'url', + 'public', 'previewImage', + 'coverImage', 'settings', + 'job', 'storage', + 'networks', 'retrieval' +] +[ + 'id', 'cid', + 'url', 'date', + 'file', 'name', + 'size', 'type', + 'blurhash', 'decorator' +] + +Slates +[ + 'body', 'name', + 'public', 'objects', + 'ownerId', 'layouts', + 'preview' +] +[ + 'id', 'url', + 'name', 'type', + 'title', 'ownerId', + 'cid', 'body', + 'author', 'source', + 'size', 'deeplink', + 'blurhash', 'unityGameConfig', + 'unityGameLoader', 'coverImage' +] +[ + 'id', 'cid', + 'url', 'date', + 'file', 'name', + 'size', 'type', + 'blurhash', 'decorator' +] +*/ diff --git a/common/strings.js b/common/strings.js index 69ef01ff..70627af4 100644 --- a/common/strings.js +++ b/common/strings.js @@ -40,7 +40,7 @@ export const zeroPad = (num, places) => { return Array(+(zero > 0 && zero)).join("0") + num; }; -export const getCIDGatewayURL = (cid) => { +export const getURLfromCID = (cid) => { return `${Constants.gateways.ipfs}/${cid}`; }; @@ -55,15 +55,15 @@ export const toDateSinceEpoch = (epoch) => { return toDate(new Date().getTime() - epoch); }; -export const getCIDGatewayURLWithExtension = (cid, name) => { - const url = getCIDGatewayURL(cid); - const extension = getFileExtension(name); - if (!isEmpty(extension)) { - return `${url}.${getFileExtension(name)}`; - } +// export const getURLfromCIDWithExtension = (cid, name) => { +// const url = getURLfromCID(cid); +// const extension = getFileExtension(name); +// if (!isEmpty(extension)) { +// return `${url}.${getFileExtension(name)}`; +// } - return url; -}; +// return url; +// }; export const getURLFromPath = (path) => { return `${window.location.protocol}//${window.location.hostname}${ @@ -210,6 +210,7 @@ export const urlToCid = (url) => { return url .replace(`${Constants.gateways.ipfs}/`, "") .replace("https://", "") + .replace("undefined", "") .replace(".ipfs.slate.textile.io", "") .replace("hub.textile.io/ipfs/", ""); }; diff --git a/common/user-behaviors.js b/common/user-behaviors.js index 4944aadb..b989c504 100644 --- a/common/user-behaviors.js +++ b/common/user-behaviors.js @@ -146,7 +146,6 @@ export const formatDroppedFiles = async ({ dataTransfer }) => { file = new File(blob, `data-${uuid()}`); file.name = `data-${uuid()}`; - console.log(file); } catch (e) { Events.dispatchMessage({ message: "File type not supported. Please try a different file", @@ -209,30 +208,26 @@ export const uploadImage = async (file, resources, excludeFromLibrary) => { return; } - const response = await FileUtilities.upload({ file, routes: resources, excludeFromLibrary }); + const response = await FileUtilities.upload({ file, routes: resources }); if (Events.hasError(response)) { return false; } - delete response.json.data.icon; - delete response.json.data.ipfs; - - return response.json; + return response; }; -export const deleteFiles = async (fileCids, fileIds = [], noAlert) => { - let cids = Array.isArray(fileCids) ? fileCids : [fileCids]; +export const deleteFiles = async (fileIds = [], noAlert) => { let ids = Array.isArray(fileIds) ? fileIds : [fileIds]; - const response = await Actions.deleteBucketItems({ cids, ids }); + const response = await Actions.deleteFiles({ ids }); if (!noAlert) { if (Events.hasError(response)) { return false; } - // Events.dispatchMessage({ message: "Files successfully deleted!", status: "INFO" }); + Events.dispatchMessage({ message: "Files successfully deleted!", status: "INFO" }); return response; } @@ -251,19 +246,8 @@ export const removeFromSlate = async ({ slate, ids }) => { return response; }; -export const addToSlate = async ({ slate, files, fromSlate }) => { - let data = files.map((file) => { - return { - title: file.name || file.title || file.file, - ...file, - }; - }); - - const addResponse = await Actions.addFileToSlate({ - slate, - data, - fromSlate, - }); +export const addToSlate = async ({ slate, files }) => { + const addResponse = await Actions.addFileToSlate({ slate, files }); if (Events.hasError(addResponse)) { return false; @@ -275,14 +259,8 @@ export const addToSlate = async ({ slate, files, fromSlate }) => { return true; }; -export const addToDataFromSlate = async ({ files }) => { - let items = files.map((file) => { - return { - ownerId: file.ownerId, - cid: file.cid, - }; - }); - let response = await Actions.addCIDToData({ items }); +export const saveCopy = async ({ files }) => { + let response = await Actions.saveCopy({ files }); if (Events.hasError(response)) { return false; } @@ -292,22 +270,16 @@ export const addToDataFromSlate = async ({ files }) => { }; export const download = (file) => { - const filename = file.file || file.name || file.title; - let uri; - if (file.url) { - uri = file.url; - } else { - uri = Strings.getCIDGatewayURL(file.cid); - } - Window.saveAs(uri, filename); + let uri = Strings.getURLfromCID(file.cid); + Window.saveAs(uri, file.filename); }; export const downloadZip = async (file) => { try { const { data } = await Actions.getZipFilePaths(file); const filesPaths = data.filesPaths.map((item) => item.replace(`/${file.id}/`, "")); - const baseUrl = file.url; - const zipFileName = file.file; + const baseUrl = Strings.getURLfromCID(file.cid); + const zipFileName = file.filename; let zip = new JSZip(); @@ -363,8 +335,8 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso if (file.type === "application/unity") { const { data } = await Actions.getZipFilePaths(file); const unityFiles = data.filesPaths.map((item) => ({ - url: item.replace(`/${file.id}/`, `${file.url || Strings.getCIDGatewayURL(file.cid)}/`), - name: item.replace(`/${file.id}/`, `/${file.name}/`), + url: item.replace(`/${file.id}/`, `${Strings.getURLfromCID(file.cid)}/`), + name: item.replace(`/${file.id}/`, `/${file.filename}/`), })); downloadFiles = downloadFiles.concat(unityFiles); @@ -372,8 +344,8 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso } downloadFiles.push({ - name: file.file || file.name, - url: file.url || Strings.getCIDGatewayURL(file.cid), + name: file.filename, + url: Strings.getURLfromCID(file.cid), }); } @@ -395,7 +367,7 @@ export const compressAndDownloadFiles = async ({ files, name = "slate.zip", reso // export const createSlate = async (data) => { // let response = await Actions.createSlate({ // name: data.name, -// public: data.public, +// isPublic: data.isPublic, // body: data.body, // }); // return response; diff --git a/common/utilities.js b/common/utilities.js index 96da400a..b33d0ac5 100644 --- a/common/utilities.js +++ b/common/utilities.js @@ -5,16 +5,16 @@ export const getPublicAndPrivateFiles = ({ viewer }) => { let publicFileIds = []; for (let slate of viewer.slates) { - if (slate.data.public) { - publicFileIds.push(...slate.data.objects.map((obj) => obj.id)); + if (slate.isPublic) { + publicFileIds.push(...slate.objects.map((obj) => obj.id)); } } let publicFiles = []; let privateFiles = []; - let library = viewer.library[0]?.children || []; + let library = viewer.library || []; for (let file of library) { - if (file.public || publicFileIds.includes(file.id)) { + if (file.isPublic || publicFileIds.includes(file.id)) { publicFiles.push(file); } else { privateFiles.push(file); diff --git a/common/validations.js b/common/validations.js index 3103a7b8..4dfe72c5 100644 --- a/common/validations.js +++ b/common/validations.js @@ -149,6 +149,36 @@ export const isPreviewableImage = (type = "") => { return type.startsWith("image/"); }; +export const isImageType = (type) => { + if (type.startsWith("image/")) { + return true; + } +}; + +export const isAudioType = (type) => { + if (type.startsWith("audio/")) { + return true; + } +}; + +export const isVideoType = (type) => { + if (type.startsWith("video/")) { + return true; + } +}; + +export const isPdfType = (type) => { + if (type.startsWith("application/pdf")) { + return true; + } +}; + +export const isEpubType = (type) => { + if (type.startsWith("application/epub")) { + return true; + } +}; + export const isUnityFile = async (file) => { try { const zip = new JSZip(); diff --git a/common/window.js b/common/window.js index 2b48682b..50d72899 100644 --- a/common/window.js +++ b/common/window.js @@ -94,7 +94,7 @@ export const isIOS = (userAgent) => { export const isMobileBrowser = (userAgent) => { const navigatorAgent = getNavigatorAgent(userAgent); - const mobile = + const isMobile = /(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ipad|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test( navigatorAgent ) || @@ -102,7 +102,7 @@ export const isMobileBrowser = (userAgent) => { navigatorAgent.substr(0, 4) ); - return !!mobile; + return !!isMobile; }; //NOTE(toast): this can be switched to regex pattern matching if @@ -116,12 +116,13 @@ export const isMac = (userAgent) => { export const debounce = (func, wait) => { let timeout; - return function passedInFunction(...args) { - const later = () => { - func(...args); - }; + return function passedInFunction(params) { + if (params?.cancel) { + clearTimeout(timeout); + return; + } clearTimeout(timeout); - timeout = setTimeout(later, wait); + timeout = setTimeout(func, wait); }; }; diff --git a/components/core/Alert.js b/components/core/Alert.js index a966b5cc..c895408a 100644 --- a/components/core/Alert.js +++ b/components/core/Alert.js @@ -115,7 +115,12 @@ export class Alert extends React.Component { _handleDismissPrivacyAlert = (e) => { Actions.updateStatus({ status: { hidePrivacyAlert: true } }); - this.props.onUpdateViewer({ status: { ...this.props.viewer.status, hidePrivacyAlert: true } }); + this.props.onUpdateViewer({ + data: { + ...this.props.viewer.data, + status: { ...this.props.viewer.data.status, hidePrivacyAlert: true }, + }, + }); }; render() { diff --git a/components/core/Application.js b/components/core/Application.js index 462f23b7..7d0a763e 100644 --- a/components/core/Application.js +++ b/components/core/Application.js @@ -20,7 +20,6 @@ import SceneFile from "~/scenes/SceneFile"; import SceneFilesFolder from "~/scenes/SceneFilesFolder"; import SceneSettings from "~/scenes/SceneSettings"; import SceneSlates from "~/scenes/SceneSlates"; -import SceneLocalData from "~/scenes/SceneLocalData"; import SceneSettingsDeveloper from "~/scenes/SceneSettingsDeveloper"; import SceneSignIn from "~/scenes/SceneSignIn"; import SceneSlate from "~/scenes/SceneSlate"; @@ -87,7 +86,6 @@ const SCENES = { SETTINGS: , SLATES: , SLATES_FOLLOWING: , - LOCAL_DATA: , DIRECTORY: , DIRECTORY_FOLLOWERS: , FILECOIN: , @@ -105,7 +103,7 @@ export default class ApplicationPage extends React.Component { data: null, sidebar: null, online: null, - mobile: this.props.mobile, + isMobile: this.props.isMobile, loaded: false, activeUsers: null, }; @@ -172,10 +170,7 @@ export default class ApplicationPage extends React.Component { const current = NavigationData.getCurrent(page); let slate = null; - if ( - current.target.id === "NAV_SLATE" && - this.state.data?.data?.ownerId === this.state.viewer?.id - ) { + if (current.target.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer?.id) { slate = this.state.data; } @@ -186,7 +181,7 @@ export default class ApplicationPage extends React.Component { }); }; - _handleUpdateViewer = (newViewerState) => { + _handleUpdateViewer = (newViewerState, callback) => { // let setAsyncState = (newState) => // new Promise((resolve) => // this.setState( @@ -207,7 +202,7 @@ export default class ApplicationPage extends React.Component { if (!page || !page.id) { page = { id: "NAV_DATA", scrollTop: 0, data: null }; } - if (page.id === "NAV_SLATE" && this.state.data?.data?.ownerId === this.state.viewer.id) { + if (page.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer.id) { let data = this.state.data; for (let slate of newViewerState.slates) { if (slate.id === data.id) { @@ -215,21 +210,39 @@ export default class ApplicationPage extends React.Component { break; } } - this.setState({ - viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" }, - data, - }); + this.setState( + { + viewer: { ...this.state.viewer, ...newViewerState }, + data, + }, + () => { + if (callback) { + callback(); + } + } + ); return; } } - this.setState({ - viewer: { ...this.state.viewer, ...newViewerState, type: "VIEWER" }, - }); + this.setState( + { + viewer: { ...this.state.viewer, ...newViewerState }, + }, + () => { + if (callback) { + callback(); + } + } + ); }; - _handleUpdateData = ({ data }) => { + _handleUpdateData = (data, callback) => { //TODO(martina): maybe add a default window.history.replacestate where it pushes the new data to browser? - this.setState({ data }); + this.setState({ data }, () => { + if (callback) { + callback(); + } + }); }; _handleSetupWebsocket = async () => { @@ -243,7 +256,7 @@ export default class ApplicationPage extends React.Component { console.log("WEBSOCKET: NOT AUTHENTICATED"); return; } - + console.log("inside handle setup websocket in application.js"); wsclient = Websockets.init({ resource: this.props.resources.pubsub, viewer: this.state.viewer, @@ -269,12 +282,12 @@ export default class ApplicationPage extends React.Component { // (1) is Window.isMobileBrowser checks, that one holds. // (2) then if the viewport is smaller than the width - let mobile = width > Constants.sizes.mobile ? this.props.mobile : true; + let isMobile = width > Constants.sizes.mobile ? this.props.isMobile : true; // only change if necessary. - if (this.state.mobile !== mobile) { - console.log("changing to mobile?", mobile); - this.setState({ mobile }); + if (this.state.isMobile !== isMobile) { + console.log("changing to mobile?", isMobile); + this.setState({ isMobile }); } }; @@ -308,10 +321,7 @@ export default class ApplicationPage extends React.Component { const current = NavigationData.getCurrent(page); let slate = null; - if ( - current.target.id === "NAV_SLATE" && - this.state.data?.data?.ownerId === this.state.viewer?.id - ) { + if (current.target.id === "NAV_SLATE" && this.state.data?.ownerId === this.state.viewer?.id) { slate = this.state.data; } @@ -331,9 +341,10 @@ export default class ApplicationPage extends React.Component { }); }; - _handleUpload = async ({ files, slate, keys, numFailed }) => { + _handleUpload = async ({ files, slate, keys, numFailed = 0 }) => { if (!files || !files.length) { - return null; + this._handleRegisterLoadingFinished({ keys }); + return; } const resolvedFiles = []; @@ -346,7 +357,7 @@ export default class ApplicationPage extends React.Component { await Window.delay(3000); // NOTE(jim): Sends XHR request. - let response = null; + let response; try { response = await FileUtilities.upload({ file: files[i], @@ -364,34 +375,53 @@ export default class ApplicationPage extends React.Component { } if (!resolvedFiles.length) { - this.setState({ fileLoading: {} }); - return null; - } - - let responses = await Promise.allSettled(resolvedFiles); - let succeeded = responses - .filter((res) => { - return res.status === "fulfilled" && res.value && !res.value.error; - }) - .map((res) => res.value); - - if (slate && slate.id) { - await FileUtilities.uploadToSlate({ responses: succeeded, slate }); - } - - let processResponse = await Actions.processPendingFiles(); - if (Events.hasError(processResponse)) { + this._handleRegisterLoadingFinished({ keys }); return; } + //NOTE(martina): this commented out portion is only for if parallel uploading + // let responses = await Promise.allSettled(resolvedFiles); + // let succeeded = responses + // .filter((res) => { + // return res.status === "fulfilled" && res.value && !res.value.error; + // }) + // .map((res) => res.value); - if (!slate) { - const { added, skipped } = processResponse.data; - let message = Strings.formatAsUploadMessage(added, skipped + numFailed); - Events.dispatchMessage({ message, status: !added ? null : "INFO" }); + let createResponse = await Actions.createFile({ files: resolvedFiles }); + + if (Events.hasError(createResponse)) { + this._handleRegisterLoadingFinished({ keys }); + return; + } + console.log("no error in actions.createFile"); + + console.log(createResponse); + let uploadedFiles = createResponse.data; + + let added, skipped; + if (slate && slate.id) { + console.log(slate); + console.log(uploadedFiles); + const addResponse = await Actions.addFileToSlate({ + slate, + files: uploadedFiles, + }); + + if (Events.hasError(addResponse)) { + this._handleRegisterLoadingFinished({ keys }); + return; + } + + added = addResponse.added; + skipped = addResponse.skipped; + } else { + added = resolvedFiles.length; + skipped = files.length - resolvedFiles.length; } + let message = Strings.formatAsUploadMessage(added, skipped + numFailed); + Events.dispatchMessage({ message, status: !added ? null : "INFO" }); + this._handleRegisterLoadingFinished({ keys }); - return null; }; _handleRegisterFileLoading = ({ fileLoading }) => { @@ -473,10 +503,11 @@ export default class ApplicationPage extends React.Component { let unseenAnnouncements = []; for (let feature of announcements) { - if (!Object.keys(viewer.onboarding).includes(feature)) { + if (!viewer.data.onboarding || !Object.keys(viewer.data.onboarding).includes(feature)) { unseenAnnouncements.push(feature); } } + console.log(unseenAnnouncements); if (newAccount || unseenAnnouncements.length) { Events.dispatchCustomEvent({ @@ -622,6 +653,7 @@ export default class ApplicationPage extends React.Component { }; render() { + console.log(this.state.viewer); // NOTE(jim): Not authenticated. if (!this.state.viewer) { return ( @@ -661,8 +693,8 @@ export default class ApplicationPage extends React.Component { navigation={NavigationData.navigation} activeIds={current.activeIds} onAction={this._handleAction} - mobile={this.state.mobile} - mac={this.props.mac} + isMobile={this.state.isMobile} + isMac={this.props.isMac} /> ); @@ -679,8 +711,8 @@ export default class ApplicationPage extends React.Component { onUpdateData: this._handleUpdateData, onUpdateViewer: this._handleUpdateViewer, sceneId: current.target.id, - mobile: this.state.mobile, - mac: this.props.mac, + isMobile: this.state.isMobile, + isMac: this.props.isMac, resources: this.props.resources, activeUsers: this.state.activeUsers, userBucketCID: this.state.userBucketCID, @@ -737,8 +769,8 @@ export default class ApplicationPage extends React.Component { onDismissSidebar={this._handleDismissSidebar} fileLoading={this.state.fileLoading} filecoin={current.target.filecoin} - mobile={this.state.mobile} - mac={this.props.mac} + isMobile={this.state.isMobile} + isMac={this.props.isMac} viewer={this.state.viewer} onUpdateViewer={this._handleUpdateViewer} > @@ -748,7 +780,7 @@ export default class ApplicationPage extends React.Component { {!this.state.loaded ? ( diff --git a/components/core/ApplicationHeader.js b/components/core/ApplicationHeader.js index d33c2a64..c9dbc44e 100644 --- a/components/core/ApplicationHeader.js +++ b/components/core/ApplicationHeader.js @@ -128,7 +128,7 @@ const STYLES_STATIC = css` export default class ApplicationHeader extends React.Component { keysPressed = {}; - searchModKey = this.props.mac ? ( + searchModKey = this.props.isMac ? ( ) : ( Ctrl diff --git a/components/core/ApplicationLayout.js b/components/core/ApplicationLayout.js index 9cc4af4a..bc6b69fc 100644 --- a/components/core/ApplicationLayout.js +++ b/components/core/ApplicationLayout.js @@ -113,13 +113,13 @@ export default class ApplicationLayout extends React.Component { componentDidMount = () => { this.prevScrollPos = window.pageYOffset; - if (this.props.mobile) { + if (this.props.isMobile) { window.addEventListener("scroll", this._handleScroll); } }; componentWillUnmount = () => { - if (this.props.mobile) { + if (this.props.isMobile) { window.removeEventListener("scroll", this._handleScroll); } }; @@ -166,20 +166,23 @@ export default class ApplicationLayout extends React.Component { {/* */} -
+
{this.props.header}
{ + if (props.type) { + if (Validations.isVideoType(type)) { + return DEFAULT_VIDEO; + } else if (Validations.isAudioType(type)) { + return DEFAULT_AUDIO; + } else if (Validations.isPdfType(type)) { + return DEFAULT_DOCUMENT; + } else if (Validations.isEpubType(type)) { + return DEFAULT_BOOK; + } + } + return DEFAULT_DATA; +}; + +class CarouselSidebar extends React.Component { + state = { + name: this.props.data.data.name || this.props.data.filename, + body: this.props.data.data.body, + source: this.props.data.data.source, + author: this.props.data.data.author, + tags: this.props.data.data.tags || [], + suggestions: this.props.viewer?.tags || [], + selected: {}, + isPublic: false, + inPublicSlates: 0, + isUploading: false, + isDownloading: false, + showSavedMessage: false, + showConnectedSection: false, + showFileSection: true, + }; + + componentDidMount = () => { + const editingAllowed = !this.props.external && this.props.isOwner && !this.props.isRepost; + if (editingAllowed) { + this.debounceInstance = Window.debounce(() => this._handleSave(), 3000); + this.calculateSelected(); + } + }; + + componentDidUpdate = (prevProps, prevState) => { + if (!isEqual(prevState.tags, this.state.tags)) { + this.updateSuggestions(); + } + }; + + updateSuggestions = () => { + let newSuggestions = new Set([...this.state.suggestions, ...this.state.tags]); + this.setState({ suggestions: Array.from(newSuggestions) }); + }; + + calculateSelected = () => { + console.log("calculate selected"); + let inPublicSlates = 0; + let selected = {}; + const id = this.props.data.id; + for (let slate of this.props.viewer.slates) { + if (slate.objects.some((obj) => obj.id === id)) { + if (slate.isPublic) { + inPublicSlates += 1; + } + selected[slate.id] = true; + } + } + this.setState({ selected, inPublicSlates, isPublic: this.props.data.isPublic }); + }; + + _handleToggleAccordion = (tab) => { + this.setState({ [tab]: !this.state[tab] }); + }; + + _handleDarkMode = async (e) => { + Events.dispatchCustomEvent({ + name: "set-slate-theme", + detail: { darkmode: e.target.value }, + }); + }; + + _handleChange = (e) => { + if (this.props.external || !this.props.isOwner) return; + this.debounceInstance(); + this.setState( + { + [e.target.name]: e.target.value, + showSavedMessage: false, + }, + () => { + if (e.target.name === "Tags") { + this.updateSuggestions(); + } + } + ); + }; + + _handleCapitalization(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + _handleSave = async () => { + if (this.props.external || !this.props.isOwner) return; + this.props.onUpdateViewer({ tags: this.state.suggestions }); + const response = await Actions.updateFile({ + id: this.props.data.id, + data: { + name: this.state.name, + body: this.state.body, + source: this.state.source, + author: this.state.author, + tags: this.state.tags, + }, + }); + Events.hasError(response); + this.setState({ showSavedMessage: true }); + }; + + _handleSaveCopy = async (data) => { + this.setState({ loading: "savingCopy" }); + console.log(data); + await UserBehaviors.saveCopy({ files: [data] }); + this.setState({ loading: false }); + }; + + _handleUpload = async (e) => { + if (this.props.external || !this.props.isOwner) return; + e.persist(); + this.setState({ isUploading: true }); + let previousCoverId = this.props.data.data.coverImage?.id; + if (!e || !e.target) { + this.setState({ isUploading: false }); + return; + } + let file = await UserBehaviors.uploadImage(e.target.files[0], this.props.resources, true); + if (!file) { + this.setState({ isUploading: false }); + return; + } + + let coverImage = file; + + //TODO(martina): create an endpoint specifically for cover images instead of this, which will delete original cover image etc + + let updateReponse = await Actions.updateFile({ + id: this.props.data.id, + data: { + coverImage, + }, + }); + + if (previousCoverId) { + if (!this.props.viewer.library.some((obj) => obj.id === previousCoverId)) { + await UserBehaviors.deleteFiles(previousCoverId, true); + } + } + + Events.hasError(updateReponse); + this.setState({ isUploading: false }); + }; + + _handleDownload = () => { + if (this.props.data.data.type === "application/unity") { + this.setState({ isDownloading: true }, async () => { + const response = await UserBehaviors.downloadZip(this.props.data); + this.setState({ isDownloading: false }); + Events.hasError(response); + }); + } else { + UserBehaviors.download(this.props.data); + } + }; + + _handleCreateSlate = async () => { + if (this.props.external) return; + this.props.onClose(); + this.props.onAction({ + type: "SIDEBAR", + value: "SIDEBAR_CREATE_SLATE", + data: { files: [this.props.data] }, + }); + }; + + _handleDelete = () => { + if (this.props.external || !this.props.isOwner) return; + const message = + "Are you sure you want to delete this? It will be removed from your slates as well"; + if (!window.confirm(message)) { + return; + } + const id = this.props.data.id; + + let updatedLibrary = this.props.viewer.library.filter((obj) => obj.id !== id); + if (this.props.carouselType === "SLATE") { + const slateId = this.props.current.id; + let slates = this.props.viewer.slates; + for (let slate of slates) { + if (slate.id === slateId) { + slate.objects = slate.objects.filter((obj) => obj.id !== id); + break; + } + } + this.props.onUpdateViewer({ library: updatedLibrary, slates }); + } else { + this.props.onUpdateViewer({ library: updatedLibrary }); + } + + UserBehaviors.deleteFiles(id); + }; + + _handleAdd = async (slate) => { + let inPublicSlates = this.state.inPublicSlates; + if (this.state.selected[slate.id]) { + if (slate.isPublic) { + inPublicSlates -= 1; + } + UserBehaviors.removeFromSlate({ slate, ids: [this.props.data.id] }); + } else { + if (slate.isPublic) { + inPublicSlates += 1; + } + UserBehaviors.addToSlate({ + slate, + files: [this.props.data], + }); + } + this.setState({ + selected: { + ...this.state.selected, + [slate.id]: !this.state.selected[slate.id], + }, + inPublicSlates, + }); + }; + + _handleRemove = async () => { + if (!this.props.carouselType === "SLATE" || this.props.external || !this.props.isOwner) { + return; + } + + const id = this.props.data.id; + const slateId = this.props.current.id; + let slates = this.props.viewer.slates; + for (let slate of slates) { + if (slate.id === slateId) { + slate.objects = slate.objects.filter((obj) => obj.id !== id); + break; + } + } + this.props.onUpdateViewer({ slates }); + + UserBehaviors.removeFromSlate({ slate: this.props.current, ids: [this.props.data.id] }); + }; + + _handleToggleVisibility = async (e) => { + if (this.props.external || !this.props.isOwner) return; + const isVisible = this.state.isPublic || this.state.inPublicSlates > 0; + let selected = cloneDeep(this.state.selected); + if (this.state.inPublicSlates) { + const slateIds = Object.entries(this.state.selected) + .filter((entry) => entry[1]) + .map((entry) => entry[0]); + const publicSlateIds = []; + const publicSlateNames = []; + for (let slate of this.props.viewer.slates) { + if (slate.isPublic && slateIds.includes(slate.id)) { + publicSlateNames.push(slate.data.name); + publicSlateIds.push(slate.id); + selected[slate.id] = false; + } + } + const slateNames = publicSlateNames.join(", "); + const message = `Making this file private will remove it from the following public slates: ${slateNames}. Do you wish to continue?`; + if (!window.confirm(message)) { + return; + } + } + + if (this.props.carouselType === "SLATE" && this.props.current.isPublic) { + const slateId = this.props.current.id; + let slates = this.props.viewer.slates; + for (let slate of slates) { + if (slate.id === slateId) { + slate.objects = slate.objects.filter((obj) => obj.id !== id); + break; + } + } + this.props.onUpdateViewer({ slates }); + } + + let response = await Actions.toggleFilePrivacy(this.props.data); + Events.hasError(response); + if (isVisible) { + this.setState({ inPublicSlates: 0, isPublic: false, selected }); + } else { + this.setState({ isPublic: true }); + } + }; + + render() { + const isVisible = this.state.isPublic || this.state.inPublicSlates > 0 ? true : false; + const file = this.props.data; + const { coverImage, type, size } = file.data; + const editingAllowed = this.props.isOwner && !this.props.isRepost && !this.props.external; + + const isUnityGame = type === "application/unity"; + + const elements = []; + if (editingAllowed && !isUnityGame) { + elements.push( +
+ +