diff --git a/src/components/EditVideo/EditVideo.tsx b/src/components/EditFile/EditFile.tsx similarity index 93% rename from src/components/EditVideo/EditVideo.tsx rename to src/components/EditFile/EditFile.tsx index 2742b40..1804f60 100644 --- a/src/components/EditVideo/EditVideo.tsx +++ b/src/components/EditFile/EditFile.tsx @@ -1,17 +1,10 @@ -import React, { useEffect, useState } from "react"; +import React, {useEffect, useState} from "react"; import { - AddCoverImageButton, - AddLogoIcon, - CoverImagePreview, CrowdfundActionButton, CrowdfundActionButtonRow, CustomInputField, - CustomSelect, - LogoPreviewRow, ModalBody, NewCrowdfundTitle, - StyledButton, - TimesIcon, } from "./Upload-styles"; import { Box, @@ -28,27 +21,19 @@ import { import RemoveIcon from "@mui/icons-material/Remove"; import ShortUniqueId from "short-unique-id"; -import { useDispatch, useSelector } from "react-redux"; -import AddBoxIcon from "@mui/icons-material/AddBox"; -import { useDropzone } from "react-dropzone"; - -import { setNotification } from "../../state/features/notificationsSlice"; -import { objectToBase64, uint8ArrayToBase64 } from "../../utils/toBase64"; -import { RootState } from "../../state/store"; -import { - upsertVideosBeginning, - addToHashMap, - upsertVideos, - setEditVideo, - updateVideo, - updateInHashMap, -} from "../../state/features/videoSlice"; -import ImageUploader from "../common/ImageUploader"; -import { QTUBE_VIDEO_BASE, categories, subCategories, subCategories2, - subCategories3, } from "../../constants"; -import { MultiplePublish } from "../common/MultiplePublish/MultiplePublish"; -import { TextEditor } from "../common/TextEditor/TextEditor"; -import { extractTextFromHTML } from "../common/TextEditor/utils"; +import {useDispatch, useSelector} from "react-redux"; +import {useDropzone} from "react-dropzone"; + +import {setNotification} from "../../state/features/notificationsSlice"; +import {objectToBase64} from "../../utils/toBase64"; +import {RootState} from "../../state/store"; +import {setEditVideo, updateInHashMap, updateVideo,} from "../../state/features/videoSlice"; +import {QSHARE_FILE_BASE,} from "../../constants/Identifiers.ts"; +import {MultiplePublish} from "../common/MultiplePublish/MultiplePublishAll"; +import {TextEditor} from "../common/TextEditor/TextEditor"; +import {extractTextFromHTML} from "../common/TextEditor/utils"; +import {categories, subCategories, subCategories2, subCategories3} from "../../constants/Categories.ts"; +import {titleFormatter} from "../../constants/Misc.ts"; const uid = new ShortUniqueId(); const shortuid = new ShortUniqueId({ length: 5 }); @@ -70,7 +55,7 @@ interface VideoFile { identifier?:string; filename?:string } -export const EditVideo = () => { +export const EditFile = () => { const theme = useTheme(); const dispatch = useDispatch(); const username = useSelector((state: RootState) => state.auth?.user?.name); @@ -80,7 +65,7 @@ export const EditVideo = () => { const editVideoProperties = useSelector( (state: RootState) => state.video.editVideoProperties ); - const [publishes, setPublishes] = useState([]); + const [publishes, setPublishes] = useState(null); const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false); const [videoPropertiesToSetToRedux, setVideoPropertiesToSetToRedux] = useState(null); @@ -302,7 +287,7 @@ export const EditVideo = () => { const file = publish.file; const id = uid(); - const identifier = `${QTUBE_VIDEO_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; + const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; @@ -347,7 +332,7 @@ export const EditVideo = () => { description: metadescription, identifier, filename, - tag1: QTUBE_VIDEO_BASE, + tag1: QSHARE_FILE_BASE, }; listOfPublishes.push(requestBodyVideo); fileReferences.push({ @@ -388,12 +373,16 @@ export const EditVideo = () => { title: title.slice(0, 50), description: metadescription, identifier: editVideoProperties.id, - tag1: QTUBE_VIDEO_BASE, + tag1: QSHARE_FILE_BASE, filename: `video_metadata.json`, }; listOfPublishes.push(requestBodyJson); - setPublishes(listOfPublishes); + const multiplePublish = { + action: "PUBLISH_MULTIPLE_QDN_RESOURCES", + resources: [...listOfPublishes], + }; + setPublishes(multiplePublish); setIsOpenMultiplePublish(true); setVideoPropertiesToSetToRedux({ ...editVideoProperties, @@ -686,10 +675,7 @@ export const EditVideo = () => { value={title} onChange={(e) => { const value = e.target.value; - const formattedValue = value.replace( - /[^a-zA-Z0-9\s-_!?]/g, - "" - ); + const formattedValue = value.replace(titleFormatter, ""); setTitle(formattedValue); }} inputProps={{ maxLength: 180 }} @@ -744,6 +730,18 @@ export const EditVideo = () => { {isOpenMultiplePublish && ( { + setIsOpenMultiplePublish(false); + setPublishes(null) + if(messageNotification){ + dispatch( + setNotification({ + msg: messageNotification, + alertType: 'error' + }) + ) + } + }} onSubmit={() => { setIsOpenMultiplePublish(false); const clonedCopy = structuredClone(videoPropertiesToSetToRedux); diff --git a/src/components/EditVideo/Upload-styles.tsx b/src/components/EditFile/Upload-styles.tsx similarity index 100% rename from src/components/EditVideo/Upload-styles.tsx rename to src/components/EditFile/Upload-styles.tsx diff --git a/src/components/EditPlaylist/EditPlaylist.tsx b/src/components/EditPlaylist/EditPlaylist.tsx index 614be9c..10e99a5 100644 --- a/src/components/EditPlaylist/EditPlaylist.tsx +++ b/src/components/EditPlaylist/EditPlaylist.tsx @@ -12,7 +12,7 @@ import { NewCrowdfundTitle, StyledButton, TimesIcon, -} from "./Upload-styles"; +} from "./Upload-styles.tsx"; import { Box, FormControl, @@ -43,11 +43,12 @@ import { setEditPlaylist, } from "../../state/features/videoSlice"; import ImageUploader from "../common/ImageUploader"; -import { QTUBE_PLAYLIST_BASE, QTUBE_VIDEO_BASE, categories, subCategories } from "../../constants"; +import { QSHARE_PLAYLIST_BASE, QSHARE_FILE_BASE } from "../../constants/Identifiers.ts"; import { Playlists } from "../Playlists/Playlists"; import { PlaylistListEdit } from "../PlaylistListEdit/PlaylistListEdit"; import { TextEditor } from "../common/TextEditor/TextEditor"; import { extractTextFromHTML } from "../common/TextEditor/utils"; +import {categories, subCategories} from "../../constants/Categories.ts"; const uid = new ShortUniqueId(); const shortuid = new ShortUniqueId({ length: 5 }); @@ -289,7 +290,7 @@ export const EditPlaylist = () => { let commentsId = editVideoProperties?.id if(isNew){ - commentsId = `${QTUBE_PLAYLIST_BASE}_cm_${id}` + commentsId = `${QSHARE_PLAYLIST_BASE}_cm_${id}` } const stringDescription = extractTextFromHTML(description) @@ -322,7 +323,7 @@ export const EditPlaylist = () => { .trim() .toLowerCase(); if(isNew){ - identifier = `${QTUBE_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; + identifier = `${QSHARE_PLAYLIST_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; } const requestBodyJson: any = { action: "PUBLISH_QDN_RESOURCE", @@ -332,7 +333,7 @@ export const EditPlaylist = () => { title: title.slice(0, 50), description: metadescription, identifier: identifier, - tag1: QTUBE_VIDEO_BASE, + tag1: QSHARE_FILE_BASE, }; await qortalRequest(requestBodyJson); diff --git a/src/components/PlaylistListEdit/PlaylistListEdit.tsx b/src/components/PlaylistListEdit/PlaylistListEdit.tsx index ffae637..51cf79f 100644 --- a/src/components/PlaylistListEdit/PlaylistListEdit.tsx +++ b/src/components/PlaylistListEdit/PlaylistListEdit.tsx @@ -3,13 +3,13 @@ import { CardContentContainerComment } from "../common/Comments/Comments-styles" import { CrowdfundSubTitle, CrowdfundSubTitleRow, -} from "../UploadVideo/Upload-styles"; +} from "../PublishFile/Upload-styles.tsx"; import { Box, Button, Input, Typography, useTheme } from "@mui/material"; import { useNavigate } from "react-router-dom"; import DeleteOutlineIcon from "@mui/icons-material/DeleteOutline"; import { removeVideo } from "../../state/features/videoSlice"; import AddIcon from '@mui/icons-material/Add'; -import { QTUBE_VIDEO_BASE } from "../../constants"; +import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts"; import { useSelector } from "react-redux"; import { RootState } from "../../state/store"; export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => { @@ -21,7 +21,7 @@ export const PlaylistListEdit = ({ playlistData, removeVideo, addVideo }) => { const [filterSearch, setFilterSearch] = useState("") const search = async()=> { - const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QTUBE_VIDEO_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0` + const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&mode=ALL&identifier=${QSHARE_FILE_BASE}&title=${filterSearch}&limit=20&includemetadata=true&reverse=true&name=${username}&exactmatchnames=true&offset=0` const response = await fetch(url, { method: 'GET', headers: { diff --git a/src/components/Playlists/Playlists.tsx b/src/components/Playlists/Playlists.tsx index 2492bb2..3e60c90 100644 --- a/src/components/Playlists/Playlists.tsx +++ b/src/components/Playlists/Playlists.tsx @@ -1,6 +1,6 @@ import React from 'react' import { CardContentContainerComment } from '../common/Comments/Comments-styles' -import { CrowdfundSubTitle, CrowdfundSubTitleRow } from '../UploadVideo/Upload-styles' +import { CrowdfundSubTitle, CrowdfundSubTitleRow } from '../PublishFile/Upload-styles.tsx' import { Box, Typography, useTheme } from '@mui/material' import { useNavigate } from 'react-router-dom' diff --git a/src/components/UploadVideo/UploadVideo.tsx b/src/components/PublishFile/PublishFile.tsx similarity index 94% rename from src/components/UploadVideo/UploadVideo.tsx rename to src/components/PublishFile/PublishFile.tsx index 2e8b7e0..8366c2d 100644 --- a/src/components/UploadVideo/UploadVideo.tsx +++ b/src/components/PublishFile/PublishFile.tsx @@ -44,21 +44,23 @@ import { } from "../../state/features/videoSlice"; import ImageUploader from "../common/ImageUploader"; import { - QTUBE_PLAYLIST_BASE, - QTUBE_VIDEO_BASE, - categories, - subCategories, - subCategories2, - subCategories3, -} from "../../constants"; -import { MultiplePublish } from "../common/MultiplePublish/MultiplePublish"; + QSHARE_PLAYLIST_BASE, + QSHARE_FILE_BASE, + + + + +} from "../../constants/Identifiers.ts"; +import { MultiplePublish } from "../common/MultiplePublish/MultiplePublishAll"; import { CrowdfundSubTitle, CrowdfundSubTitleRow, -} from "../EditPlaylist/Upload-styles"; +} from "../EditPlaylist/Upload-styles.tsx"; import { CardContentContainerComment } from "../common/Comments/Comments-styles"; import { TextEditor } from "../common/TextEditor/TextEditor"; import { extractTextFromHTML } from "../common/TextEditor/utils"; +import {categories, subCategories, subCategories2, subCategories3} from "../../constants/Categories.ts"; +import {titleFormatter} from "../../constants/Misc.ts"; const uid = new ShortUniqueId(); const shortuid = new ShortUniqueId({ length: 5 }); @@ -78,7 +80,7 @@ interface VideoFile { description: string; coverImage?: string; } -export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { +export const PublishFile = ({ editId, editContent }: NewCrowdfundProps) => { const theme = useTheme(); const dispatch = useDispatch(); const [isOpenMultiplePublish, setIsOpenMultiplePublish] = useState(false); @@ -112,7 +114,7 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { useState(null); const [playlistSetting, setPlaylistSetting] = useState(null); - const [publishes, setPublishes] = useState([]); + const [publishes, setPublishes] = useState(null); const { getRootProps, getInputProps } = useDropzone({ maxFiles: 10, maxSize: 419430400, // 400 MB in bytes @@ -214,7 +216,7 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { const file = publish.file; const id = uid(); - const identifier = `${QTUBE_VIDEO_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; + const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; @@ -260,7 +262,7 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { description: metadescription, identifier, filename, - tag1: QTUBE_VIDEO_BASE, + tag1: QSHARE_FILE_BASE, }; listOfPublishes.push(requestBodyVideo); fileReferences.push({ @@ -274,13 +276,13 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { } const idMeta = uid(); - const identifier = `${QTUBE_VIDEO_BASE}${sanitizeTitle.slice(0, 30)}_${idMeta}`; + const identifier = `${QSHARE_FILE_BASE}${sanitizeTitle.slice(0, 30)}_${idMeta}`; const fileObject: any = { title, version: 1, fullDescription, htmlDescription: description, - commentsId: `${QTUBE_VIDEO_BASE}_cm_${idMeta}`, + commentsId: `${QSHARE_FILE_BASE}_cm_${idMeta}`, category, subcategory, subcategory2, @@ -302,12 +304,18 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { title: title.slice(0, 50), description: metadescription, identifier: identifier + "_metadata", - tag1: QTUBE_VIDEO_BASE, + tag1: QSHARE_FILE_BASE, filename: `video_metadata.json`, }; listOfPublishes.push(requestBodyJson); - setPublishes(listOfPublishes); + + const multiplePublish = { + action: "PUBLISH_MULTIPLE_QDN_RESOURCES", + resources: [...listOfPublishes], + }; + setPublishes(multiplePublish); setIsOpenMultiplePublish(true); + } catch (error: any) { let notificationObj: any = null; if (typeof error === "string") { @@ -599,10 +607,7 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { value={title} onChange={(e) => { const value = e.target.value; - const formattedValue = value.replace( - /[^a-zA-Z0-9\s-_!?]/g, - "" - ); + const formattedValue = value.replace(titleFormatter, ""); setTitle(formattedValue); }} inputProps={{ maxLength: 180 }} @@ -659,6 +664,18 @@ export const UploadVideo = ({ editId, editContent }: NewCrowdfundProps) => { {isOpenMultiplePublish && ( { + setIsOpenMultiplePublish(false); + setPublishes(null) + if(messageNotification){ + dispatch( + setNotification({ + msg: messageNotification, + alertType: 'error' + }) + ) + } + }} onSubmit={() => { setIsOpenMultiplePublish(false); setIsOpen(false); diff --git a/src/components/UploadVideo/Upload-styles.tsx b/src/components/PublishFile/Upload-styles.tsx similarity index 95% rename from src/components/UploadVideo/Upload-styles.tsx rename to src/components/PublishFile/Upload-styles.tsx index d6ef999..d31aa96 100644 --- a/src/components/UploadVideo/Upload-styles.tsx +++ b/src/components/PublishFile/Upload-styles.tsx @@ -67,9 +67,9 @@ export const ModalBody = styled(Box)(({ theme }) => ({ overflowY: "auto", maxHeight: "95vh", boxShadow: - theme.palette.mode === "dark" - ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)" - : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px", + theme.palette.mode === "dark" + ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)" + : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px", "&::-webkit-scrollbar-track": { backgroundColor: theme.palette.background.paper, }, @@ -203,11 +203,11 @@ export const CrowdfundDescription = styled(Typography)(({ theme }) => ({ export const Spacer = ({ height }: any) => { return ( - + ); }; @@ -314,14 +314,14 @@ export const AddCrowdFundButton = styled(Button)(({ theme }) => ({ gap: "8px", color: "#ffffff", backgroundColor: - theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86", + theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86", border: "none", borderRadius: "5px", transition: "all 0.3s ease-in-out", "&:hover": { cursor: "pointer", backgroundColor: - theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d", + theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d", }, })); @@ -333,14 +333,14 @@ export const EditCrowdFundButton = styled(Button)(({ theme }) => ({ gap: "8px", color: "#ffffff", backgroundColor: - theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86", + theme.palette.mode === "dark" ? theme.palette.primary.main : "#2a9a86", border: "none", borderRadius: "5px", transition: "all 0.3s ease-in-out", "&:hover": { cursor: "pointer", backgroundColor: - theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d", + theme.palette.mode === "dark" ? theme.palette.primary.dark : "#217e6d", }, })); @@ -584,4 +584,4 @@ export const CustomSelect = styled(Select)(({ theme }) => ({ fontWeight: 400, color: theme.palette.text.primary, }, -})); +})); \ No newline at end of file diff --git a/src/components/common/Comments/CommentEditor.tsx b/src/components/common/Comments/CommentEditor.tsx index c2436d1..1911680 100644 --- a/src/components/common/Comments/CommentEditor.tsx +++ b/src/components/common/Comments/CommentEditor.tsx @@ -11,7 +11,7 @@ import { CommentInputContainer, SubmitCommentButton, } from "./Comments-styles"; -import { COMMENT_BASE } from "../../../constants"; +import { QSHARE_COMMENT_BASE } from "../../../constants/Identifiers.ts"; const uid = new ShortUniqueId(); const notification = localforage.createInstance({ @@ -201,13 +201,13 @@ export const CommentEditor = ({ try { const id = uid(); - let identifier = `${COMMENT_BASE}${postId.slice(-12)}_base_${id}`; + let identifier = `${QSHARE_COMMENT_BASE}${postId.slice(-12)}_base_${id}`; let idForNotification = identifier; if (isReply && commentId) { const removeBaseCommentId = commentId; removeBaseCommentId.replace("_base_", ""); - identifier = `${COMMENT_BASE}${postId.slice( + identifier = `${QSHARE_COMMENT_BASE}${postId.slice( -12 )}_reply_${removeBaseCommentId.slice(-6)}_${id}`; idForNotification = commentId; diff --git a/src/components/common/Comments/CommentSection.tsx b/src/components/common/Comments/CommentSection.tsx index 66dfc14..a6cb325 100644 --- a/src/components/common/Comments/CommentSection.tsx +++ b/src/components/common/Comments/CommentSection.tsx @@ -14,8 +14,8 @@ import { LoadMoreCommentsButtonRow, NoCommentsRow, } from "./Comments-styles"; -import { COMMENT_BASE } from "../../../constants"; -import { CrowdfundSubTitle, CrowdfundSubTitleRow } from "../../UploadVideo/Upload-styles"; +import { QSHARE_COMMENT_BASE } from "../../../constants/Identifiers.ts"; +import { CrowdfundSubTitle, CrowdfundSubTitleRow } from "../../PublishFile/Upload-styles.tsx"; interface CommentSectionProps { postId: string; @@ -105,7 +105,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => { const offset = 0; const removeBaseCommentId = commentId.replace("_base_", ""); - const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${COMMENT_BASE}${postId.slice( + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSHARE_COMMENT_BASE}${postId.slice( -12 )}_reply_${removeBaseCommentId.slice( -6 @@ -150,7 +150,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => { if (isNewMessages && numberOfComments) { offset = numberOfComments; } - const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${COMMENT_BASE}${postId.slice( + const url = `/arbitrary/resources/search?mode=ALL&service=BLOG_COMMENT&query=${QSHARE_COMMENT_BASE}${postId.slice( -12 )}_base_&limit=20&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`; const response = await fetch(url, { diff --git a/src/components/common/MultiplePublish/MultiplePublish.tsx b/src/components/common/MultiplePublish/MultiplePublish.tsx deleted file mode 100644 index 3070a41..0000000 --- a/src/components/common/MultiplePublish/MultiplePublish.tsx +++ /dev/null @@ -1,136 +0,0 @@ -/* eslint-disable @typescript-eslint/no-explicit-any */ -import { - Box, - Button, - CircularProgress, - Modal, - Typography, - useTheme, -} from "@mui/material"; -import React, { useCallback, useEffect, useState, useRef } from "react"; -import { ModalBody } from "../../UploadVideo/Upload-styles"; -import { CircleSVG } from "../../../assets/svgs/CircleSVG"; -import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG"; - -export const MultiplePublish = ({ publishes, isOpen, onSubmit }) => { - const theme = useTheme(); - const listOfSuccessfulPublishesRef = useRef([]) - const [listOfSuccessfulPublishes, setListOfSuccessfulPublishes] = useState< - any[] - >([]); - const [currentlyInPublish, setCurrentlyInPublish] = useState(null); - const hasStarted = useRef(false); - const publish = useCallback(async (pub: any) => { - await qortalRequest(pub); - }, []); - const [isPublishing, setIsPublishing] = useState(true) - - const handlePublish = useCallback( - async (pub: any) => { - try { - setCurrentlyInPublish(pub?.identifier); - - await publish(pub); - - setListOfSuccessfulPublishes((prev: any) => [...prev, pub?.identifier]); - listOfSuccessfulPublishesRef.current = [...listOfSuccessfulPublishesRef.current, pub?.identifier] - } catch (error) { - console.log({ error }); - await new Promise((res) => { - setTimeout(() => { - res(); - }, 5000); - }); - // await handlePublish(pub); - } - }, - [publish] - ); - - const startPublish = useCallback( - async (pubs: any) => { - setIsPublishing(true) - const filterPubs = pubs.filter((pub)=> !listOfSuccessfulPublishesRef.current.includes(pub.identifier)) - for (const pub of filterPubs) { - await handlePublish(pub); - - } - - if(listOfSuccessfulPublishesRef.current.length === pubs.length){ - onSubmit() - } - setIsPublishing(false) - }, - [handlePublish, onSubmit, listOfSuccessfulPublishes, publishes] - ); - - useEffect(() => { - if (publishes && !hasStarted.current) { - hasStarted.current = true; - startPublish(publishes); - } - }, [startPublish, publishes, listOfSuccessfulPublishes]); - - - return ( - - - {publishes.map((publish: any) => { - return ( - - {publish?.title} - {publish?.identifier === currentlyInPublish ? ( - - ) : listOfSuccessfulPublishes.includes(publish.identifier) ? ( - - ) : ( - - )} - - ); - })} - {!isPublishing && listOfSuccessfulPublishes.length !== publishes.length && ( - <> - Some files were not published. Please try again. It's important that all the files get published. Maybe wait a couple minutes if the error keeps occurring - - - )} - - - - ); -}; diff --git a/src/components/common/MultiplePublish/MultiplePublishAll.tsx b/src/components/common/MultiplePublish/MultiplePublishAll.tsx new file mode 100644 index 0000000..36fc0c3 --- /dev/null +++ b/src/components/common/MultiplePublish/MultiplePublishAll.tsx @@ -0,0 +1,211 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { + Box, + Button, + CircularProgress, + Modal, + Typography, + useTheme, +} from "@mui/material"; +import React, { useCallback, useEffect, useState, useRef } from "react"; +import { CircleSVG } from "../../../assets/svgs/CircleSVG"; +import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG"; +import { styled } from "@mui/system"; + +interface Publish { + resources: any[]; + action: string; +} + +interface MultiplePublishProps { + publishes: Publish; + isOpen: boolean; + onSubmit: ()=> void + onError: (message?: string)=> void +} +export const MultiplePublish = ({ publishes, isOpen, onSubmit, onError}: MultiplePublishProps) => { + const theme = useTheme(); + const listOfSuccessfulPublishesRef = useRef([]) + const [listOfSuccessfulPublishes, setListOfSuccessfulPublishes] = useState< + any[] + >([]); + const [listOfUnsuccessfulPublishes, setListOfUnSuccessfulPublishes] = useState< + any[] + >([]); + const [currentlyInPublish, setCurrentlyInPublish] = useState(null); + const hasStarted = useRef(false); + const publish = useCallback(async (pub: any) => { + const lengthOfResources = pub?.resources?.length + const lengthOfTimeout = lengthOfResources * 30000 + return await qortalRequestWithTimeout(pub, lengthOfTimeout); + }, []); + const [isPublishing, setIsPublishing] = useState(true) + + const handlePublish = useCallback( + async (pub: any) => { + try { + setCurrentlyInPublish(pub?.identifier); + setIsPublishing(true) + const res = await publish(pub); + + onSubmit() + setListOfUnSuccessfulPublishes([]) + + } catch (error: any) { + const unsuccessfulPublishes = error?.error?.unsuccessfulPublishes || [] + if(error?.error === 'User declined request'){ + onError() + return + } + + if(error?.error === 'The request timed out'){ + onError("The request timed out") + + return + } + + + if(unsuccessfulPublishes?.length > 0){ + setListOfUnSuccessfulPublishes(unsuccessfulPublishes) + + } + } finally { + + setIsPublishing(false) + } + }, + [publish] + ); + + const retry = ()=> { + let newlistOfMultiplePublishes: any[] = []; + listOfUnsuccessfulPublishes?.forEach((item)=> { + const findPub = publishes?.resources.find((res: any)=> res?.identifier === item.identifier) + if(findPub){ + newlistOfMultiplePublishes.push(findPub) + } + }) + const multiplePublish = { + ...publishes, + resources: newlistOfMultiplePublishes + }; + handlePublish(multiplePublish) + } + + const startPublish = useCallback( + async (pubs: any) => { + await handlePublish(pubs); + }, + [handlePublish, onSubmit, listOfSuccessfulPublishes, publishes] + ); + + useEffect(() => { + if (publishes && !hasStarted.current) { + hasStarted.current = true; + startPublish(publishes); + } + }, [startPublish, publishes, listOfSuccessfulPublishes]); + + + return ( + + + {publishes?.resources?.map((publish: any) => { + const unpublished = listOfUnsuccessfulPublishes.map(item => item?.identifier) + return ( + + {publish?.identifier} + {!isPublishing && hasStarted.current ? ( + <> + {!unpublished.includes(publish.identifier) ? ( + + ) : ( + + )} + + ): } + + + ); + })} + {!isPublishing && listOfUnsuccessfulPublishes.length > 0 && ( + <> + Some files were not published. Please try again. It's important that all the files get published. Maybe wait a couple minutes if the error keeps occurring + + + )} + + + + ); +}; + + +export const ModalBody = styled(Box)(({ theme }) => ({ + position: "absolute", + backgroundColor: theme.palette.background.default, + borderRadius: "4px", + top: "50%", + left: "50%", + transform: "translate(-50%, -50%)", + width: "75%", + maxWidth: "900px", + padding: "15px 35px", + display: "flex", + flexDirection: "column", + gap: "17px", + overflowY: "auto", + maxHeight: "95vh", + boxShadow: + theme.palette.mode === "dark" + ? "0px 4px 5px 0px hsla(0,0%,0%,0.14), 0px 1px 10px 0px hsla(0,0%,0%,0.12), 0px 2px 4px -1px hsla(0,0%,0%,0.2)" + : "rgba(99, 99, 99, 0.2) 0px 2px 8px 0px", + "&::-webkit-scrollbar-track": { + backgroundColor: theme.palette.background.paper, + }, + "&::-webkit-scrollbar-track:hover": { + backgroundColor: theme.palette.background.paper, + }, + "&::-webkit-scrollbar": { + width: "16px", + height: "10px", + backgroundColor: theme.palette.mode === "light" ? "#f6f8fa" : "#292d3e", + }, + "&::-webkit-scrollbar-thumb": { + backgroundColor: theme.palette.mode === "light" ? "#d3d9e1" : "#575757", + borderRadius: "8px", + backgroundClip: "content-box", + border: "4px solid transparent", + }, + "&::-webkit-scrollbar-thumb:hover": { + backgroundColor: theme.palette.mode === "light" ? "#b7bcc4" : "#474646", + }, +})); \ No newline at end of file diff --git a/src/components/layout/Navbar/Navbar.tsx b/src/components/layout/Navbar/Navbar.tsx index d85501c..3e6b40d 100644 --- a/src/components/layout/Navbar/Navbar.tsx +++ b/src/components/layout/Navbar/Navbar.tsx @@ -35,8 +35,8 @@ import { } from "../../../state/features/videoSlice"; import { RootState } from "../../../state/store"; import { useWindowSize } from "../../../hooks/useWindowSize"; -import { UploadVideo } from "../../UploadVideo/UploadVideo"; -import { StyledButton } from "../../UploadVideo/Upload-styles"; +import { PublishFile } from "../../PublishFile/PublishFile.tsx"; +import { StyledButton } from "../../PublishFile/Upload-styles.tsx"; interface Props { isAuthenticated: boolean; userName: string | null; @@ -400,7 +400,7 @@ const NavBar: React.FC = ({ {isAuthenticated && userName && ( <> - + )} diff --git a/src/constants/Categories.ts b/src/constants/Categories.ts new file mode 100644 index 0000000..7a7d2ab --- /dev/null +++ b/src/constants/Categories.ts @@ -0,0 +1,221 @@ +import softwareIcon from "../assets/icons/software.webp"; +import gamingIcon from "../assets/icons/gaming.webp"; +import mediaIcon from "../assets/icons/media.webp"; +import videoIcon from "../assets/icons/video.webp"; +import audioIcon from "../assets/icons/audio.webp"; +import documentIcon from "../assets/icons/document.webp"; + +interface SubCategory { + id: number; + name: string; +} + +interface Categories { + [key: number]: SubCategory[]; +} + +const sortCategory = (a: SubCategory, b: SubCategory) => { + if (a.name === "Other") return 1; + else if (b.name === "Other") return -1; + else return a.name.localeCompare(b.name); +}; + +export const categories = [ + {"id": 1, "name": "Software"}, + {"id": 2, "name": "Gaming"}, + {"id": 3, "name": "Media"}, + {"id": 4, "name": "Other"} +].sort(sortCategory); +export const subCategories: Categories = { + 1: [ + {"id": 101, "name": "OS"}, + {"id": 102, "name": "Application"}, + {"id": 103, "name": "Source Code"}, + {"id": 104, "name": "Other"} + ].sort(sortCategory), + 2: [ + {"id": 201, "name": "NES"}, + {"id": 202, "name": "SNES"}, + {"id": 203, "name": "PC"}, + {"id": 204, "name": "Other"} + ].sort(sortCategory), + 3: [ + {"id": 301, "name": "Audio"}, + {"id": 302, "name": "Video"}, + {"id": 303, "name": "Image"}, + {"id": 304, "name": "Document"}, + {"id": 305, "name": "Other"} + ].sort(sortCategory) +}; + +const gamingSystems = [ + {"id": 20101, "name": "ROM"}, + {"id": 20102, "name": "Romhack"}, + {"id": 20103, "name": "Emulator"}, + {"id": 20104, "name": "Guide"}, + {"id": 20105, "name": "Other"}, + ].sort(sortCategory) +export const subCategories2: Categories = { + 201: gamingSystems, // NES + 202: gamingSystems, // SNES + 301: [ // Audio + {"id": 30101, "name": "Music"}, + {"id": 30102, "name": "Podcasts"}, + {"id": 30103, "name": "Audiobooks"}, + {"id": 30104, "name": "Sound Effects"}, + {"id": 30105, "name": "Lectures & Speeches"}, + {"id": 30106, "name": "Radio Shows"}, + {"id": 30107, "name": "Ambient Sounds"}, + {"id": 30108, "name": "Language Learning Material"}, + {"id": 30109, "name": "Comedy & Satire"}, + {"id": 30110, "name": "Documentaries"}, + {"id": 30111, "name": "Guided Meditations & Yoga"}, + {"id": 30112, "name": "Live Performances"}, + {"id": 30113, "name": "Nature Sounds"}, + {"id": 30114, "name": "Soundtracks"}, + {"id": 30115, "name": "Interviews"} + ].sort(sortCategory), + 302: [ // Under Video + {"id": 30201, "name": "Movies"}, + {"id": 30202, "name": "Series"}, + {"id": 30203, "name": "Music"}, + {"id": 30204, "name": "Education"}, + {"id": 30205, "name": "Lifestyle"}, + {"id": 30206, "name": "Gaming"}, + {"id": 30207, "name": "Technology"}, + {"id": 30208, "name": "Sports"}, + {"id": 30209, "name": "News & Politics"}, + {"id": 30210, "name": "Cooking & Food"}, + {"id": 30211, "name": "Animation"}, + {"id": 30212, "name": "Science"}, + {"id": 30213, "name": "Health & Wellness"}, + {"id": 30214, "name": "DIY & Crafts"}, + {"id": 30215, "name": "Kids & Family"}, + {"id": 30216, "name": "Comedy"}, + {"id": 30217, "name": "Travel & Adventure"}, + {"id": 30218, "name": "Art & Design"}, + {"id": 30219, "name": "Nature & Environment"}, + {"id": 30220, "name": "Business & Finance"}, + {"id": 30221, "name": "Personal Development"}, + {"id": 30222, "name": "Other"}, + {"id": 30223, "name": "History"} + ].sort(sortCategory), + 303: [ // Image + {"id": 30301, "name": "Nature"}, + {"id": 30302, "name": "Urban & Cityscapes"}, + {"id": 30303, "name": "People & Portraits"}, + {"id": 30304, "name": "Art & Abstract"}, + {"id": 30305, "name": "Travel & Adventure"}, + {"id": 30306, "name": "Animals & Wildlife"}, + {"id": 30307, "name": "Sports & Action"}, + {"id": 30308, "name": "Food & Cuisine"}, + {"id": 30309, "name": "Fashion & Beauty"}, + {"id": 30310, "name": "Technology & Science"}, + {"id": 30311, "name": "Historical & Cultural"}, + {"id": 30312, "name": "Aerial & Drone"}, + {"id": 30313, "name": "Black & White"}, + {"id": 30314, "name": "Events & Celebrations"}, + {"id": 30315, "name": "Business & Corporate"}, + {"id": 30316, "name": "Health & Wellness"}, + {"id": 30317, "name": "Transportation & Vehicles"}, + {"id": 30318, "name": "Still Life & Objects"}, + {"id": 30319, "name": "Architecture & Buildings"}, + {"id": 30320, "name": "Landscapes & Seascapes"} + ].sort(sortCategory), + 304: [ // Document + {"id": 30401, "name": "PDF"}, + {"id": 30402, "name": "Word Document"}, + {"id": 30403, "name": "Spreadsheet"}, + {"id": 30404, "name": "Powerpoint"}, + {"id": 30405, "name": "Books"} + ].sort(sortCategory) +}; +export const subCategories3: Categories = { + 30201: [ // Under Movies + {"id": 3020101, "name": "Action & Adventure"}, + {"id": 3020102, "name": "Comedy"}, + {"id": 3020103, "name": "Drama"}, + {"id": 3020104, "name": "Fantasy & Science Fiction"}, + {"id": 3020105, "name": "Horror & Thriller"}, + {"id": 3020106, "name": "Documentaries"}, + {"id": 3020107, "name": "Animated"}, + {"id": 3020108, "name": "Family & Kids"}, + {"id": 3020109, "name": "Romance"}, + {"id": 3020110, "name": "Mystery & Crime"}, + {"id": 3020111, "name": "Historical & War"}, + {"id": 3020112, "name": "Musicals & Music Films"}, + {"id": 3020113, "name": "Indie Films"}, + {"id": 3020114, "name": "International Films"}, + {"id": 3020115, "name": "Biographies & True Stories"}, + {"id": 3020116, "name": "Other"} + ].sort(sortCategory), + 30202: [ // Under Series + {"id": 3020201, "name": "Dramas"}, + {"id": 3020202, "name": "Comedies"}, + {"id": 3020203, "name": "Reality & Competition"}, + {"id": 3020204, "name": "Documentaries & Docuseries"}, + {"id": 3020205, "name": "Sci-Fi & Fantasy"}, + {"id": 3020206, "name": "Crime & Mystery"}, + {"id": 3020207, "name": "Animated Series"}, + {"id": 3020208, "name": "Kids & Family"}, + {"id": 3020209, "name": "Historical & Period Pieces"}, + {"id": 3020210, "name": "Action & Adventure"}, + {"id": 3020211, "name": "Horror & Thriller"}, + {"id": 3020212, "name": "Romance"}, + {"id": 3020213, "name": "Anthologies"}, + {"id": 3020214, "name": "International Series"}, + {"id": 3020215, "name": "Miniseries"}, + {"id": 3020216, "name": "Other"} + ].sort(sortCategory), + 30405: [ // Under Books + {"id": 3040501, "name": "Fiction"}, + {"id": 3040502, "name": "Non-Fiction"}, + {"id": 3040503, "name": "Science Fiction & Fantasy"}, + {"id": 3040504, "name": "Biographies & Memoirs"}, + {"id": 3040505, "name": "Children's Books"}, + {"id": 3040506, "name": "Educational"}, + {"id": 3040507, "name": "Self-Help"}, + {"id": 3040508, "name": "Cookbooks, Food & Wine"}, + {"id": 3040509, "name": "Mystery & Thriller"}, + {"id": 3040510, "name": "History"}, + {"id": 3040511, "name": "Poetry"}, + {"id": 3040512, "name": "Art & Photography"}, + {"id": 3040513, "name": "Religion & Spirituality"}, + {"id": 3040514, "name": "Travel"}, + {"id": 3040515, "name": "Comics & Graphic Novels"}, + + ].sort(sortCategory), + 30101: [ // Under Music + {"id": 3010101, "name": "Rock"}, + {"id": 3010102, "name": "Pop"}, + {"id": 3010103, "name": "Classical"}, + {"id": 3010104, "name": "Jazz"}, + {"id": 3010105, "name": "Electronic"}, + {"id": 3010106, "name": "Country"}, + {"id": 3010107, "name": "Hip Hop/Rap"}, + {"id": 3010108, "name": "Blues"}, + {"id": 3010109, "name": "R&B/Soul"}, + {"id": 3010110, "name": "Reggae"}, + {"id": 3010111, "name": "Folk"}, + {"id": 3010112, "name": "Metal"}, + {"id": 3010113, "name": "World Music"}, + {"id": 3010114, "name": "Latin"}, + {"id": 3010115, "name": "Indie"}, + {"id": 3010116, "name": "Punk"}, + {"id": 3010117, "name": "Soundtracks"}, + {"id": 3010118, "name": "Children's Music"}, + {"id": 3010119, "name": "New Age"}, + {"id": 3010120, "name": "Classical Crossover"} + ].sort(sortCategory) + + +}; +export const icons = { + 1: softwareIcon, + 2: gamingIcon, + 3: mediaIcon, + 4: softwareIcon, + 302: videoIcon, + 301: audioIcon, + 304: documentIcon +} \ No newline at end of file diff --git a/src/constants/Identifiers.ts b/src/constants/Identifiers.ts new file mode 100644 index 0000000..66b2c8b --- /dev/null +++ b/src/constants/Identifiers.ts @@ -0,0 +1,17 @@ +const useTestIdentifiers = false; + +export const QSHARE_FILE_BASE = useTestIdentifiers + ? "MYTEST_share_vid_" + : "qshare_file_"; + + export const QSHARE_PLAYLIST_BASE = useTestIdentifiers + ? "MYTEST_share_playlist_" + : "qshare_playlist_"; + + export const QSHARE_COMMENT_BASE = useTestIdentifiers + ? "qcomment_v1_MYTEST_" + : "qcomment_v1_qshare_"; + + + + diff --git a/src/constants/Misc.ts b/src/constants/Misc.ts new file mode 100644 index 0000000..8aaa2a0 --- /dev/null +++ b/src/constants/Misc.ts @@ -0,0 +1 @@ +export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.~;:|]/g; \ No newline at end of file diff --git a/src/constants/index.ts b/src/constants/index.ts deleted file mode 100644 index 128ea8e..0000000 --- a/src/constants/index.ts +++ /dev/null @@ -1,237 +0,0 @@ -import softwareIcon from '../assets/icons/software.webp' -import gamingIcon from '../assets/icons/gaming.webp' -import mediaIcon from '../assets/icons/media.webp' -import audioIcon from '../assets/icons/audio.webp' -import videoIcon from '../assets/icons/video.webp' -import documentIcon from '../assets/icons/document.webp' - - -const useTestIdentifiers = false; - -export const QTUBE_VIDEO_BASE = useTestIdentifiers - ? "MYTEST_share_vid_" - : "qshare_file_"; - - export const QTUBE_PLAYLIST_BASE = useTestIdentifiers - ? "MYTEST_share_playlist_" - : "qshare_playlist_"; - - export const COMMENT_BASE = useTestIdentifiers - ? "qcomment_v1_MYTEST_" - : "qcomment_v1_qshare_"; - - interface SubCategory { - id: number; - name: string; -} - -interface CategoryMap { - [key: number]: SubCategory[]; -} - - -export const categories = [ - {"id": 1, "name": "Software"}, - {"id": 2, "name": "Gaming"}, - {"id": 3, "name": "Media"} -]; - -export const subCategories: CategoryMap = { - 1: [ - {"id": 101, "name": "OS"}, - {"id": 102, "name": "Application"}, - {"id": 103, "name": "Source Code"}, - {"id": 104, "name": "Other"} - ], - 2: [ - {"id": 201, "name": "NES"}, - {"id": 202, "name": "SNES"}, - {"id": 203, "name": "PC"}, - {"id": 204, "name": "Other Gaming Systems"} - ], - 3: [ - {"id": 301, "name": "Audio"}, - {"id": 302, "name": "Video"}, - {"id": 303, "name": "Image"}, - {"id": 304, "name": "Document"}, - {"id": 305, "name": "Other Media Formats"} - ] -}; - - - - -export const subCategories2: CategoryMap = { - 201: [ // NES - {"id": 20101, "name": "ROM"}, - {"id": 20102, "name": "Romhack"}, - {"id": 20103, "name": "Emulator"}, - ], - 202: [ // SNES - {"id": 20201, "name": "ROM"}, - {"id": 20202, "name": "Romhack"}, - {"id": 20203, "name": "Emulator"}, - ], - 301: [ // Audio - {"id": 30101, "name": "Music"}, - {"id": 30102, "name": "Podcasts"}, - {"id": 30103, "name": "Audiobooks"}, - {"id": 30104, "name": "Sound Effects"}, - {"id": 30105, "name": "Lectures & Speeches"}, - {"id": 30106, "name": "Radio Shows"}, - {"id": 30107, "name": "Ambient Sounds"}, - {"id": 30108, "name": "Language Learning Material"}, - {"id": 30109, "name": "Comedy & Satire"}, - {"id": 30110, "name": "Documentaries"}, - {"id": 30111, "name": "Guided Meditations & Yoga"}, - {"id": 30112, "name": "Live Performances"}, - {"id": 30113, "name": "Nature Sounds"}, - {"id": 30114, "name": "Soundtracks"}, - {"id": 30115, "name": "Interviews"} - ], - 302: [ // Under Video - {"id": 30201, "name": "Movies"}, - {"id": 30202, "name": "Series"}, - {"id": 30203, "name": "Music"}, - {"id": 30204, "name": "Education"}, - {"id": 30205, "name": "Lifestyle"}, - {"id": 30206, "name": "Gaming"}, - {"id": 30207, "name": "Technology"}, - {"id": 30208, "name": "Sports"}, - {"id": 30209, "name": "News & Politics"}, - {"id": 30210, "name": "Cooking & Food"}, - {"id": 30211, "name": "Animation"}, - {"id": 30212, "name": "Science"}, - {"id": 30213, "name": "Health & Wellness"}, - {"id": 30214, "name": "DIY & Crafts"}, - {"id": 30215, "name": "Kids & Family"}, - {"id": 30216, "name": "Comedy"}, - {"id": 30217, "name": "Travel & Adventure"}, - {"id": 30218, "name": "Art & Design"}, - {"id": 30219, "name": "Nature & Environment"}, - {"id": 30220, "name": "Business & Finance"}, - {"id": 30221, "name": "Personal Development"}, - {"id": 30222, "name": "Other"}, - {"id": 30223, "name": "History"} - ], - 303: [ // Image - {"id": 30301, "name": "Nature"}, - {"id": 30302, "name": "Urban & Cityscapes"}, - {"id": 30303, "name": "People & Portraits"}, - {"id": 30304, "name": "Art & Abstract"}, - {"id": 30305, "name": "Travel & Adventure"}, - {"id": 30306, "name": "Animals & Wildlife"}, - {"id": 30307, "name": "Sports & Action"}, - {"id": 30308, "name": "Food & Cuisine"}, - {"id": 30309, "name": "Fashion & Beauty"}, - {"id": 30310, "name": "Technology & Science"}, - {"id": 30311, "name": "Historical & Cultural"}, - {"id": 30312, "name": "Aerial & Drone"}, - {"id": 30313, "name": "Black & White"}, - {"id": 30314, "name": "Events & Celebrations"}, - {"id": 30315, "name": "Business & Corporate"}, - {"id": 30316, "name": "Health & Wellness"}, - {"id": 30317, "name": "Transportation & Vehicles"}, - {"id": 30318, "name": "Still Life & Objects"}, - {"id": 30319, "name": "Architecture & Buildings"}, - {"id": 30320, "name": "Landscapes & Seascapes"} - ], - 304: [ // Document - {"id": 30401, "name": "PDF"}, - {"id": 30402, "name": "Word Document"}, - {"id": 30403, "name": "Spreadsheet"}, - {"id": 30404, "name": "Powerpoint"}, - {"id": 30405, "name": "Books"} - ] -}; - - -export const subCategories3: CategoryMap = { - 30201: [ // Under Movies - {"id": 3020101, "name": "Action & Adventure"}, - {"id": 3020102, "name": "Comedy"}, - {"id": 3020103, "name": "Drama"}, - {"id": 3020104, "name": "Fantasy & Science Fiction"}, - {"id": 3020105, "name": "Horror & Thriller"}, - {"id": 3020106, "name": "Documentaries"}, - {"id": 3020107, "name": "Animated"}, - {"id": 3020108, "name": "Family & Kids"}, - {"id": 3020109, "name": "Romance"}, - {"id": 3020110, "name": "Mystery & Crime"}, - {"id": 3020111, "name": "Historical & War"}, - {"id": 3020112, "name": "Musicals & Music Films"}, - {"id": 3020113, "name": "Indie Films"}, - {"id": 3020114, "name": "International Films"}, - {"id": 3020115, "name": "Biographies & True Stories"}, - {"id": 3020116, "name": "Other"} - ], - 30202: [ // Under Series - {"id": 3020201, "name": "Dramas"}, - {"id": 3020202, "name": "Comedies"}, - {"id": 3020203, "name": "Reality & Competition"}, - {"id": 3020204, "name": "Documentaries & Docuseries"}, - {"id": 3020205, "name": "Sci-Fi & Fantasy"}, - {"id": 3020206, "name": "Crime & Mystery"}, - {"id": 3020207, "name": "Animated Series"}, - {"id": 3020208, "name": "Kids & Family"}, - {"id": 3020209, "name": "Historical & Period Pieces"}, - {"id": 3020210, "name": "Action & Adventure"}, - {"id": 3020211, "name": "Horror & Thriller"}, - {"id": 3020212, "name": "Romance"}, - {"id": 3020213, "name": "Anthologies"}, - {"id": 3020214, "name": "International Series"}, - {"id": 3020215, "name": "Miniseries"}, - {"id": 3020216, "name": "Other"} - ], - 30405: [ // Under Books - {"id": 3040501, "name": "Fiction"}, - {"id": 3040502, "name": "Non-Fiction"}, - {"id": 3040503, "name": "Science Fiction & Fantasy"}, - {"id": 3040504, "name": "Biographies & Memoirs"}, - {"id": 3040505, "name": "Children's Books"}, - {"id": 3040506, "name": "Educational"}, - {"id": 3040507, "name": "Self-Help"}, - {"id": 3040508, "name": "Cookbooks, Food & Wine"}, - {"id": 3040509, "name": "Mystery & Thriller"}, - {"id": 3040510, "name": "History"}, - {"id": 3040511, "name": "Poetry"}, - {"id": 3040512, "name": "Art & Photography"}, - {"id": 3040513, "name": "Religion & Spirituality"}, - {"id": 3040514, "name": "Travel"}, - {"id": 3040515, "name": "Comics & Graphic Novels"}, - -], -30101: [ // Under Music - {"id": 3010101, "name": "Rock"}, - {"id": 3010102, "name": "Pop"}, - {"id": 3010103, "name": "Classical"}, - {"id": 3010104, "name": "Jazz"}, - {"id": 3010105, "name": "Electronic"}, - {"id": 3010106, "name": "Country"}, - {"id": 3010107, "name": "Hip Hop/Rap"}, - {"id": 3010108, "name": "Blues"}, - {"id": 3010109, "name": "R&B/Soul"}, - {"id": 3010110, "name": "Reggae"}, - {"id": 3010111, "name": "Folk"}, - {"id": 3010112, "name": "Metal"}, - {"id": 3010113, "name": "World Music"}, - {"id": 3010114, "name": "Latin"}, - {"id": 3010115, "name": "Indie"}, - {"id": 3010116, "name": "Punk"}, - {"id": 3010117, "name": "Soundtracks"}, - {"id": 3010118, "name": "Children's Music"}, - {"id": 3010119, "name": "New Age"}, - {"id": 3010120, "name": "Classical Crossover"} -] - - -}; - -export const icons = { - 1: softwareIcon, - 2: gamingIcon, - 3: mediaIcon, - 302: videoIcon, - 301: audioIcon, - 304: documentIcon -} \ No newline at end of file diff --git a/src/hooks/useFetchVideos.tsx b/src/hooks/useFetchFiles.tsx similarity index 94% rename from src/hooks/useFetchVideos.tsx rename to src/hooks/useFetchFiles.tsx index 369fb57..55d5446 100644 --- a/src/hooks/useFetchVideos.tsx +++ b/src/hooks/useFetchFiles.tsx @@ -14,13 +14,13 @@ import { } from '../state/features/globalSlice' import { RootState } from '../state/store' import { fetchAndEvaluateVideos } from '../utils/fetchVideos' -import { QTUBE_PLAYLIST_BASE, QTUBE_VIDEO_BASE } from '../constants' +import { QSHARE_PLAYLIST_BASE, QSHARE_FILE_BASE } from '../constants/Identifiers.ts' import { RequestQueue } from '../utils/queue' import { queue } from '../wrappers/GlobalWrapper' -export const useFetchVideos = () => { +export const useFetchFiles = () => { const dispatch = useDispatch() const hashMapVideos = useSelector( (state: RootState) => state.video.hashMapVideos @@ -95,7 +95,7 @@ export const useFetchVideos = () => { dispatch(setIsLoadingGlobal(true)) - const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true` + const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true` const response = await fetch(url, { method: 'GET', headers: { @@ -213,11 +213,11 @@ export const useFetchVideos = () => { } if(type === 'playlists'){ defaultUrl = defaultUrl + `&service=PLAYLIST` - defaultUrl = defaultUrl + `&identifier=${QTUBE_PLAYLIST_BASE}` + defaultUrl = defaultUrl + `&identifier=${QSHARE_PLAYLIST_BASE}` } else { defaultUrl = defaultUrl + `&service=DOCUMENT` - defaultUrl = defaultUrl + `&identifier=${QTUBE_VIDEO_BASE}` + defaultUrl = defaultUrl + `&identifier=${QSHARE_FILE_BASE}` } // const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=${videoLimit}&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}` @@ -288,7 +288,7 @@ export const useFetchVideos = () => { const offset = filteredVideos.length const replaceSpacesWithUnderscore = filterValue.replace(/ /g, '_'); - const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${replaceSpacesWithUnderscore}&identifier=${QTUBE_VIDEO_BASE}&limit=10&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}` + const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${replaceSpacesWithUnderscore}&identifier=${QSHARE_FILE_BASE}&limit=10&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true&offset=${offset}` const response = await fetch(url, { method: 'GET', headers: { @@ -345,7 +345,7 @@ export const useFetchVideos = () => { try { - const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true` + const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=20&includemetadata=false&reverse=true&excludeblocked=true&exactmatchnames=true` const response = await fetch(url, { method: 'GET', headers: { @@ -382,12 +382,12 @@ export const useFetchVideos = () => { return { - getVideos, + getFiles: getVideos, checkAndUpdateVideo, getVideo, hashMapVideos, - getNewVideos, - checkNewVideos, - getVideosFiltered + getNewFiles: getNewVideos, + checkNewFiles: checkNewVideos, + getFilesFiltered: getVideosFiltered } } diff --git a/src/pages/Home/Channels.tsx b/src/pages/Home/Channels.tsx index d4c62d8..d8c80a3 100644 --- a/src/pages/Home/Channels.tsx +++ b/src/pages/Home/Channels.tsx @@ -9,9 +9,9 @@ import { Typography, useTheme } from '@mui/material' -import { useFetchVideos } from '../../hooks/useFetchVideos' +import { useFetchFiles } from '../../hooks/useFetchFiles.tsx' import LazyLoad from '../../components/common/LazyLoad' -import { BottomParent, NameContainer, VideoCard, VideoCardName, VideoCardTitle, VideoContainer, VideoUploadDate } from './VideoList-styles' +import { BottomParent, NameContainer, VideoCard, VideoCardName, VideoCardTitle, VideoContainer, VideoUploadDate } from './FileList-styles.tsx' import ResponsiveImage from '../../components/ResponsiveImage' import { formatDate, formatTimestampSeconds } from '../../utils/time' import { ChannelCard, ChannelTitle } from './Home-styles' diff --git a/src/pages/Home/VideoList-styles.tsx b/src/pages/Home/FileList-styles.tsx similarity index 100% rename from src/pages/Home/VideoList-styles.tsx rename to src/pages/Home/FileList-styles.tsx diff --git a/src/pages/Home/VideoList.tsx b/src/pages/Home/FileList.tsx similarity index 96% rename from src/pages/Home/VideoList.tsx rename to src/pages/Home/FileList.tsx index 0cff5cd..1badb83 100644 --- a/src/pages/Home/VideoList.tsx +++ b/src/pages/Home/FileList.tsx @@ -21,7 +21,7 @@ import { Typography, useTheme, } from "@mui/material"; -import { useFetchVideos } from "../../hooks/useFetchVideos"; +import { useFetchFiles } from "../../hooks/useFetchFiles.tsx"; import LazyLoad from "../../components/common/LazyLoad"; import { BlockIconContainer, @@ -40,7 +40,7 @@ import { VideoCardTitle, VideoContainer, VideoUploadDate, -} from "./VideoList-styles"; +} from "./FileList-styles.tsx"; import ResponsiveImage from "../../components/ResponsiveImage"; import { formatDate, formatTimestampSeconds } from "../../utils/time"; import { Subtitle, SubtitleContainer } from "./Home-styles"; @@ -59,17 +59,17 @@ import { setEditPlaylist, setEditVideo, } from "../../state/features/videoSlice"; -import { categories, icons, subCategories, subCategories2, subCategories3 } from "../../constants"; import { Playlists } from "../../components/Playlists/Playlists"; import { PlaylistSVG } from "../../assets/svgs/PlaylistSVG"; import BlockIcon from "@mui/icons-material/Block"; import EditIcon from '@mui/icons-material/Edit'; import { formatBytes } from "../VideoContent/VideoContent"; +import {categories, icons, subCategories, subCategories2, subCategories3} from "../../constants/Categories.ts"; interface VideoListProps { mode?: string; } -export const VideoList = ({ mode }: VideoListProps) => { +export const FileList = ({ mode }: VideoListProps) => { const theme = useTheme(); const prevVal = useRef(""); const isFiltering = useSelector( @@ -152,10 +152,10 @@ export const VideoList = ({ mode }: VideoListProps) => { (state: RootState) => state.video ); const navigate = useNavigate(); - const { getVideos, getNewVideos, checkNewVideos, getVideosFiltered } = - useFetchVideos(); + const { getFiles, getNewFiles, checkNewFiles, getFilesFiltered } = + useFetchFiles(); - const getVideosHandler = React.useCallback( + const getFilesHandler = React.useCallback( async (reset?: boolean, resetFilers?: boolean) => { @@ -168,7 +168,7 @@ export const VideoList = ({ mode }: VideoListProps) => { subcategory2: selectedSubCategoryVideos2?.id, subcategory3: selectedSubCategoryVideos3?.id, }) - await getVideos( + await getFiles( { name: filterName, category: selectedCategoryVideos?.id, @@ -184,9 +184,9 @@ export const VideoList = ({ mode }: VideoListProps) => { isFetching.current = false; }, [ - getVideos, + getFiles, filterValue, - getVideosFiltered, + getFilesFiltered, isFiltering, filterName, selectedCategoryVideos, @@ -198,24 +198,30 @@ export const VideoList = ({ mode }: VideoListProps) => { ] ); + const searchOnEnter = e => { + if (e.keyCode == 13) { + getFilesHandler(true); + } + }; + useEffect(() => { if (isFiltering && filterValue !== prevVal?.current) { prevVal.current = filterValue; - getVideosHandler(); + getFilesHandler(); } }, [filterValue, isFiltering, filteredVideos]); - const getVideosHandlerMount = React.useCallback(async () => { + const getFilesHandlerMount = React.useCallback(async () => { if (firstFetch.current) return; firstFetch.current = true; setIsLoading(true); - await getVideos(); + await getFiles(); afterFetch.current = true; isFetching.current = false; setIsLoading(false); - }, [getVideos]); + }, [getFiles]); let videos = globalVideos; @@ -259,12 +265,12 @@ export const VideoList = ({ mode }: VideoListProps) => { globalVideos.length === 0 ) { isFetching.current = true; - getVideosHandlerMount(); + getFilesHandlerMount(); } else { firstFetch.current = true; afterFetch.current = true; } - }, [getVideosHandlerMount, globalVideos]); + }, [getFilesHandlerMount, globalVideos]); const filtersToDefault = async () => { setFilterType("videos"); @@ -274,7 +280,7 @@ export const VideoList = ({ mode }: VideoListProps) => { setSelectedSubCategoryVideos(null); ReactDOM.flushSync(() => { - getVideosHandler(true, true); + getFilesHandler(true, true); }); }; @@ -340,6 +346,7 @@ export const VideoList = ({ mode }: VideoListProps) => { onChange={(e) => { setFilterSearch(e.target.value); }} + onKeyDown={searchOnEnter} value={filterSearch} placeholder="Search" sx={{ @@ -367,8 +374,9 @@ export const VideoList = ({ mode }: VideoListProps) => { onChange={(e) => { setFilterName(e.target.value); }} + onKeyDown={searchOnEnter} value={filterName} - placeholder="User's name" + placeholder="User's Name (Exact)" sx={{ marginTop: "20px", borderBottom: "1px solid white", @@ -640,7 +648,7 @@ export const VideoList = ({ mode }: VideoListProps) => {