3
0
mirror of https://github.com/Qortal/q-share.git synced 2025-01-30 06:42:22 +00:00

Index.ts refactored into Identifiers.ts and Categories.ts for more clarity

Some references to Q-Tube in code replaced with Q-Share

Characters allowed in Publish Titles added to constants/Misc.ts, more characters are allowed than before

User Search Label now says "User's Exact Name" to communicate that users must be precise about what names they search for

Search and Name Search now can perform searches by hitting enter instead of clicking on Search Button
This commit is contained in:
Qortal Dev 2024-01-03 10:01:20 -07:00
parent 9ccd47b4d1
commit 66b9fb8b6b
23 changed files with 232 additions and 246 deletions

View File

@ -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 {useDispatch, useSelector} from "react-redux";
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 {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/MultiplePublish";
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);
@ -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,7 +373,7 @@ 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);
@ -686,10 +671,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 }}

View File

@ -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);

View File

@ -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: {

View File

@ -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'

View File

@ -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";
QSHARE_PLAYLIST_BASE,
QSHARE_FILE_BASE,
} from "../../constants/Identifiers.ts";
import { MultiplePublish } from "../common/MultiplePublish/MultiplePublish";
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);
@ -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,7 +304,7 @@ 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);
@ -599,10 +601,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 }}

View File

@ -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 (
<Box
sx={{
height: height,
}}
/>
<Box
sx={{
height: height,
}}
/>
);
};
@ -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,
},
}));
}));

View File

@ -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;

View File

@ -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, {

View File

@ -8,7 +8,7 @@ import {
useTheme,
} from "@mui/material";
import React, { useCallback, useEffect, useState, useRef } from "react";
import { ModalBody } from "../../UploadVideo/Upload-styles";
import { ModalBody } from "../../PublishFile/Upload-styles.tsx";
import { CircleSVG } from "../../../assets/svgs/CircleSVG";
import { EmptyCircleSVG } from "../../../assets/svgs/EmptyCircleSVG";

View File

@ -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<Props> = ({
<AvatarContainer>
{isAuthenticated && userName && (
<>
<UploadVideo />
<PublishFile />
</>
)}

View File

@ -1,42 +1,25 @@
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'
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";
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 {
interface SubCategory {
id: number;
name: string;
}
interface CategoryMap {
interface Categories {
[key: number]: SubCategory[];
}
export const categories = [
{"id": 1, "name": "Software"},
{"id": 2, "name": "Gaming"},
{"id": 3, "name": "Media"}
];
export const subCategories: CategoryMap = {
export const subCategories: Categories = {
1: [
{"id": 101, "name": "OS"},
{"id": 102, "name": "Application"},
@ -57,11 +40,7 @@ export const subCategories: CategoryMap = {
{"id": 305, "name": "Other Media Formats"}
]
};
export const subCategories2: CategoryMap = {
export const subCategories2: Categories = {
201: [ // NES
{"id": 20101, "name": "ROM"},
{"id": 20102, "name": "Romhack"},
@ -73,21 +52,21 @@ export const subCategories2: CategoryMap = {
{"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"}
{"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"},
@ -115,26 +94,26 @@ export const subCategories2: CategoryMap = {
{"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"}
{"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"},
@ -144,9 +123,7 @@ export const subCategories2: CategoryMap = {
{"id": 30405, "name": "Books"}
]
};
export const subCategories3: CategoryMap = {
export const subCategories3: Categories = {
30201: [ // Under Movies
{"id": 3020101, "name": "Action & Adventure"},
{"id": 3020102, "name": "Comedy"},
@ -184,49 +161,48 @@ export const subCategories3: CategoryMap = {
{"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"}
]
{"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,

View File

@ -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_";

1
src/constants/Misc.ts Normal file
View File

@ -0,0 +1 @@
export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.~;:|]/g;

View File

@ -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
}
}

View File

@ -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'

View File

@ -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 Exact Name"
sx={{
marginTop: "20px",
borderBottom: "1px solid white",
@ -640,7 +648,7 @@ export const VideoList = ({ mode }: VideoListProps) => {
</Button>
<Button
onClick={() => {
getVideosHandler(true);
getFilesHandler(true);
}}
sx={{
marginTop: "20px",
@ -833,7 +841,7 @@ export const VideoList = ({ mode }: VideoListProps) => {
</VideoContainer>
<LazyLoad
onLoadMore={getVideosHandler}
onLoadMore={getFilesHandler}
isLoading={isLoading}
></LazyLoad>
</Box>

View File

@ -12,20 +12,21 @@ 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 { Video } from '../../state/features/videoSlice'
import { queue } from '../../wrappers/GlobalWrapper'
import { QTUBE_VIDEO_BASE, categories, icons, subCategories, subCategories2, subCategories3 } from '../../constants'
import { QSHARE_FILE_BASE } from '../../constants/Identifiers.ts'
import { formatBytes } from '../VideoContent/VideoContent'
import {categories, icons, subCategories, subCategories2, subCategories3} from "../../constants/Categories.ts";
interface VideoListProps {
mode?: string
}
export const VideoListComponentLevel = ({ mode }: VideoListProps) => {
export const FileListComponentLevel = ({ mode }: VideoListProps) => {
const { name: paramName } = useParams()
const theme = useTheme()
const [isLoading, setIsLoading] = useState<boolean>(true)
@ -48,15 +49,15 @@ export const VideoListComponentLevel = ({ mode }: VideoListProps) => {
const navigate = useNavigate()
const {
getVideo,
getNewVideos,
checkNewVideos,
getNewFiles,
checkNewFiles,
checkAndUpdateVideo
} = useFetchVideos()
} = useFetchFiles()
const getVideos = React.useCallback(async () => {
try {
const offset = videos.length
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}_&limit=50&includemetadata=false&reverse=true&excludeblocked=true&name=${paramName}&exactmatchnames=true&offset=${offset}`
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}_&limit=50&includemetadata=false&reverse=true&excludeblocked=true&name=${paramName}&exactmatchnames=true&offset=${offset}`
const response = await fetch(url, {
method: 'GET',
headers: {

View File

@ -1,5 +1,5 @@
import React from 'react'
import { VideoList } from './VideoList'
import { FileList } from './FileList.tsx'
import { useSelector } from 'react-redux'
import { RootState } from '../../state/store'
@ -8,7 +8,7 @@ export const Home = () => {
return (
<>
<VideoList />
<FileList />
</>
)

View File

@ -1,5 +1,5 @@
import React, { useMemo } from 'react'
import { VideoListComponentLevel } from '../Home/VideoListComponentLevel'
import { FileListComponentLevel } from '../Home/FileListComponentLevel.tsx'
import { HeaderContainer, ProfileContainer } from './Profile-styles'
import { AuthorTextComment, StyledCardColComment, StyledCardHeaderComment } from '../VideoContent/VideoContent-styles'
import { Avatar, Box, useTheme } from '@mui/material'
@ -57,7 +57,7 @@ export const IndividualProfile = () => {
</StyledCardHeaderComment>
</Box>
</HeaderContainer>
<VideoListComponentLevel />
<FileListComponentLevel />
</ProfileContainer>
)

View File

@ -32,11 +32,12 @@ import { CommentSection } from "../../components/common/Comments/CommentSection"
import {
CrowdfundSubTitle,
CrowdfundSubTitleRow,
} from "../../components/UploadVideo/Upload-styles";
import { QTUBE_VIDEO_BASE, categories, subCategories, subCategories2, subCategories3 } from "../../constants";
} from "../../components/PublishFile/Upload-styles.tsx";
import { QSHARE_FILE_BASE } from "../../constants/Identifiers.ts";
import { Playlists } from "../../components/Playlists/Playlists";
import { DisplayHtml } from "../../components/common/TextEditor/DisplayHtml";
import FileElement from "../../components/common/FileElement";
import {categories, subCategories, subCategories2, subCategories3} from "../../constants/Categories.ts";
export function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
@ -110,7 +111,7 @@ export const VideoContent = () => {
if (!name || !id) return;
dispatch(setIsLoadingGlobal(true));
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QTUBE_VIDEO_BASE}&limit=1&includemetadata=true&reverse=true&excludeblocked=true&name=${name}&exactmatchnames=true&offset=0&identifier=${id}`;
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&query=${QSHARE_FILE_BASE}&limit=1&includemetadata=true&reverse=true&excludeblocked=true&name=${name}&exactmatchnames=true&offset=0&identifier=${id}`;
const response = await fetch(url, {
method: "GET",
headers: {

View File

@ -15,7 +15,7 @@ import { setUserAvatarHash } from "../state/features/globalSlice";
import { VideoPlayerGlobal } from "../components/common/VideoPlayerGlobal";
import { Rnd } from "react-rnd";
import { RequestQueue } from "../utils/queue";
import { EditVideo } from "../components/EditVideo/EditVideo";
import { EditFile } from "../components/EditFile/EditFile.tsx";
import { EditPlaylist } from "../components/EditPlaylist/EditPlaylist";
import ConsentModal from "../components/common/ConsentModal";
@ -138,7 +138,7 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
userAvatar={userAvatar}
authenticate={askForAccountInformation}
/>
<EditVideo />
<EditFile />
<EditPlaylist />
<Rnd
onDragStart={onDragStart}