3
0
mirror of https://github.com/Qortal/q-tube.git synced 2025-02-11 17:55:51 +00:00

Metadata for publishes is now a file instead of Base64.

.eslintrc renamed to cjs to fix error when using ESLint

Max file size is now global variable that coverts file size to binary byte format automatically.

Many small EsLint fixes.

Fixed no key warning in MultiplePublishAll.tsx
This commit is contained in:
Qortal Dev 2024-06-18 15:41:50 -06:00
parent e4e45f8ad0
commit 0001ea250a
9 changed files with 68 additions and 57 deletions

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "qtube",
"version": "0.0.0",
"version": "2.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "qtube",
"version": "0.0.0",
"version": "2.0.0",
"dependencies": {
"@emotion/react": "^11.10.6",
"@emotion/styled": "^11.10.6",

View File

@ -35,7 +35,7 @@ import AddBoxIcon from "@mui/icons-material/AddBox";
import { useDropzone } from "react-dropzone";
import { setNotification } from "../../../state/features/notificationsSlice.ts";
import { objectToBase64, uint8ArrayToBase64 } from "../../../utils/toBase64.ts";
import { objectToBase64, objectToFile, uint8ArrayToBase64 } from "../../../utils/toBase64.ts";
import { RootState } from "../../../state/store.ts";
import {
upsertVideosBeginning,
@ -53,7 +53,7 @@ import { extractTextFromHTML } from "../../common/TextEditor/utils.ts";
import { toBase64 } from "../PublishVideo/PublishVideo.tsx";
import { FrameExtractor } from "../../common/FrameExtractor/FrameExtractor.tsx";
import { QTUBE_VIDEO_BASE } from "../../../constants/Identifiers.ts";
import { titleFormatter } from "../../../constants/Misc.ts";
import { maxSize, titleFormatter, videoMaxSize } from "../../../constants/Misc.ts";
const uid = new ShortUniqueId();
const shortuid = new ShortUniqueId({ length: 5 });
@ -103,7 +103,7 @@ export const EditVideo = () => {
"video/*": [],
},
maxFiles: 1,
maxSize: 419430400, // 400 MB in bytes
maxSize,
onDrop: (acceptedFiles, rejectedFiles) => {
const firstFile = acceptedFiles[0];
@ -114,7 +114,7 @@ export const EditVideo = () => {
rejectedFiles.forEach(({ file, errors }) => {
errors.forEach(error => {
if (error.code === "file-too-large") {
errorString = "File must be under 400mb";
errorString = `File must be under ${videoMaxSize}MB`;
}
console.log(`Error with file ${file.name}: ${error.message}`);
});
@ -248,7 +248,7 @@ export const EditVideo = () => {
);
return;
}
let listOfPublishes = [];
const listOfPublishes = [];
const category = selectedCategoryVideos.id;
const subcategory = selectedSubCategoryVideos?.id || "";
@ -259,14 +259,14 @@ export const EditVideo = () => {
fileExtension = fileExtensionSplit?.pop() || "mp4";
}
let filename = title.slice(0, 15);
const filename = title.slice(0, 15);
// Step 1: Replace all white spaces with underscores
// Replace all forms of whitespace (including non-standard ones) with underscores
let stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
const stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
// Remove all non-alphanumeric characters (except underscores)
let alphanumericString = stringWithUnderscores.replace(
const alphanumericString = stringWithUnderscores.replace(
/[^a-zA-Z0-9_]/g,
""
);
@ -287,17 +287,17 @@ export const EditVideo = () => {
filename: `${alphanumericString.trim()}.${fileExtension}`,
};
let metadescription =
const metadescription =
`**category:${category};subcategory:${subcategory};code:${editVideoProperties.code}**` +
description.slice(0, 150);
const crowdfundObjectToBase64 = await objectToBase64(videoObject);
const videoObjectToFile = objectToFile(videoObject);
// Description is obtained from raw data
const requestBodyJson: any = {
action: "PUBLISH_QDN_RESOURCE",
name: username,
service: "DOCUMENT",
data64: crowdfundObjectToBase64,
file: videoObjectToFile,
title: title.slice(0, 50),
description: metadescription,
identifier: editVideoProperties.id,
@ -318,7 +318,7 @@ export const EditVideo = () => {
tag1: QTUBE_VIDEO_BASE,
filename: `${alphanumericString.trim()}.${fileExtension}`,
};
console.log('edit file is: ', file)
listOfPublishes.push(requestBodyVideo);
}
@ -377,7 +377,7 @@ export const EditVideo = () => {
const onFramesExtracted = async imgs => {
try {
let imagesExtracts = [];
const imagesExtracts = [];
for (const img of imgs) {
try {
@ -395,7 +395,7 @@ export const EditVideo = () => {
compressedFile = file;
resolve();
},
error(err) {},
error(error) {console.log(error)},
});
});
if (!compressedFile) continue;
@ -407,7 +407,7 @@ export const EditVideo = () => {
}
setImageExtracts(imagesExtracts);
} catch (error) {}
} catch (error) {console.log(error)}
};
return (

View File

@ -125,6 +125,7 @@ export const MultiplePublish = ({
);
return (
<Box
key={publish?.identifier}
sx={{
display: "flex",
gap: "20px",

View File

@ -38,7 +38,7 @@ import { useDropzone } from "react-dropzone";
import AddIcon from "@mui/icons-material/Add";
import { setNotification } from "../../../state/features/notificationsSlice.ts";
import { objectToBase64, uint8ArrayToBase64 } from "../../../utils/toBase64.ts";
import { objectToBase64, objectToFile, uint8ArrayToBase64 } from "../../../utils/toBase64.ts";
import { RootState } from "../../../state/store.ts";
import {
upsertVideosBeginning,
@ -65,7 +65,7 @@ import {
QTUBE_PLAYLIST_BASE,
QTUBE_VIDEO_BASE,
} from "../../../constants/Identifiers.ts";
import { titleFormatter } from "../../../constants/Misc.ts";
import { maxSize, titleFormatter, videoMaxSize } from "../../../constants/Misc.ts";
import { getFileName } from "../../../utils/stringFunctions.ts";
export const toBase64 = (file: File): Promise<string | ArrayBuffer | null> =>
@ -137,13 +137,16 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
const [isCheckDescriptionIsTitle, setIsCheckDescriptionIsTitle] =
useState(false);
const [imageExtracts, setImageExtracts] = useState<any>({});
const { getRootProps, getInputProps } = useDropzone({
accept: {
"video/*": [],
},
maxSize: 419430400, // 400 MB in bytes
maxSize,
onDrop: (acceptedFiles, rejectedFiles) => {
const formatArray = acceptedFiles.map(item => {
console.log('file: ', item)
let filteredTitle = "";
if (isCheckTitleByFile) {
@ -164,7 +167,7 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
rejectedFiles.forEach(({ file, errors }) => {
errors.forEach(error => {
if (error.code === "file-too-large") {
errorString = "File must be under 400mb";
errorString = `File must be under ${videoMaxSize}MB`;
}
console.log(`Error with file ${file.name}: ${error.message}`);
});
@ -180,10 +183,10 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
},
});
useEffect(() => {
if (editContent) {
}
}, [editContent]);
// useEffect(() => {
// if (editContent) {
// }
// }, [editContent]);
const onClose = () => {
setIsOpen(false);
@ -238,7 +241,7 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
return;
}
let listOfPublishes = [];
const listOfPublishes = [];
for (let i = 0; i < files.length; i++) {
const publish = files[i];
@ -274,18 +277,18 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
fileExtension = fileExtensionSplit?.pop() || "mp4";
}
let filename = title.slice(0, 15);
const filename = title.slice(0, 15);
// Step 1: Replace all white spaces with underscores
// Replace all forms of whitespace (including non-standard ones) with underscores
let stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
const stringWithUnderscores = filename.replace(/[\s\uFEFF\xA0]+/g, "_");
// Remove all non-alphanumeric characters (except underscores)
let alphanumericString = stringWithUnderscores.replace(
const alphanumericString = stringWithUnderscores.replace(
/[^a-zA-Z0-9_]/g,
""
);
console.log('file size: ', file.size)
const videoObject: any = {
title,
version: 1,
@ -306,17 +309,16 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
filename: `${alphanumericString.trim()}.${fileExtension}`,
};
let metadescription =
const metadescription =
`**category:${category};subcategory:${subcategory};code:${code}**` +
fullDescription.slice(0, 150);
const crowdfundObjectToBase64 = await objectToBase64(videoObject);
// Description is obtained from raw data
const requestBodyJson: any = {
action: "PUBLISH_QDN_RESOURCE",
name: name,
service: "DOCUMENT",
data64: crowdfundObjectToBase64,
file: objectToFile(videoObject),
title: title.slice(0, 50),
description: metadescription,
identifier: identifier + "_metadata",
@ -392,17 +394,17 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
.slice(0, 10)
.join("");
let metadescription =
const metadescription =
`**category:${category};subcategory:${subcategory};${codes}**` +
stringDescription.slice(0, 120);
const crowdfundObjectToBase64 = await objectToBase64(playlistObject);
// Description is obtained from raw data
const requestBodyJson: any = {
action: "PUBLISH_QDN_RESOURCE",
name: name,
service: "PLAYLIST",
data64: crowdfundObjectToBase64,
file: objectToFile(playlistObject),
title: title.slice(0, 50),
description: metadescription,
identifier: identifier + "_metadata",
@ -447,17 +449,17 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
.slice(0, 10)
.join("");
let metadescription =
const metadescription =
`**category:${playlistObject.category};subcategory:${playlistObject.subcategory};${codes}**` +
playlistObject.description.slice(0, 120);
const crowdfundObjectToBase64 = await objectToBase64(playlistObject);
// Description is obtained from raw data
const requestBodyJson: any = {
action: "PUBLISH_QDN_RESOURCE",
name: name,
service: "PLAYLIST",
data64: crowdfundObjectToBase64,
file: objectToFile( playlistObject),
title: playlistObject.title.slice(0, 50),
description: metadescription,
identifier: selectExistingPlaylist.identifier,
@ -480,24 +482,24 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
let notificationObj: any = null;
if (typeof error === "string") {
notificationObj = {
msg: error || "Failed to publish crowdfund",
msg: error || "Failed to publish video",
alertType: "error",
};
} else if (typeof error?.error === "string") {
notificationObj = {
msg: error?.error || "Failed to publish crowdfund",
msg: error?.error || "Failed to publish video",
alertType: "error",
};
} else {
notificationObj = {
msg: error?.message || "Failed to publish crowdfund",
msg: error?.message || "Failed to publish video",
alertType: "error",
};
}
if (!notificationObj) return;
dispatch(setNotification(notificationObj));
throw new Error("Failed to publish crowdfund");
throw new Error("Failed to publish video");
}
}
@ -578,7 +580,7 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
const onFramesExtracted = async (imgs, index) => {
try {
let imagesExtracts = [];
const imagesExtracts = [];
for (const img of imgs) {
try {
@ -596,7 +598,7 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
compressedFile = file;
resolve();
},
error(err) {},
error(error) {console.log(error)},
});
});
if (!compressedFile) continue;
@ -613,7 +615,7 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
[index]: imagesExtracts,
};
});
} catch (error) {}
} catch (error) {console.log(error)}
};
return (

View File

@ -14,7 +14,7 @@ export const getCurrentLikeType = async (
});
return response?.likeType;
} catch (e) {
console.log("liketype error: ", e);
// console.log("liketype error: ", e);
return NEUTRAL;
}
};

View File

@ -1,3 +1,6 @@
export const minPriceSuperlike = 1;
export const titleFormatter = /[^a-zA-Z0-9\s-_!?()&'",.;:|—~@#$%^*+=<>]/g;
export const titleFormatterOnSave = /[^a-zA-Z0-9\s-_!()&',.;—~@#$%^+=]/g;
export const videoMaxSize = 400; // Size in Megabytes (decimal)
export const maxSize = videoMaxSize *1024*1024

View File

@ -72,7 +72,7 @@ export const useFetchVideos = () => {
const getAvatar = React.useCallback(async (author: string) => {
try {
let url = await qortalRequest({
const url = await qortalRequest({
action: "GET_QDN_RESOURCE_URL",
name: author,
service: "THUMBNAIL",
@ -85,14 +85,14 @@ export const useFetchVideos = () => {
url,
})
);
} catch (error) {}
} catch (error) {console.log(error)}
}, []);
const getVideo = async (
user: string,
videoId: string,
content: any,
retries: number = 0
retries = 0
) => {
try {
const res = await fetchAndEvaluateVideos({
@ -183,7 +183,7 @@ export const useFetchVideos = () => {
}
}
}
} catch (error) {
} catch (error) {console.log(error)
} finally {
dispatch(setIsLoadingGlobal(false));
}
@ -311,7 +311,6 @@ export const useFetchVideos = () => {
}
} catch (error) {
console.log({ error });
} finally {
}
},
[videos, hashMapVideos]
@ -370,8 +369,7 @@ export const useFetchVideos = () => {
}
}
}
} catch (error) {
} finally {
} catch (error) {console.log(error)
}
},
[filteredVideos, hashMapVideos]
@ -411,12 +409,12 @@ export const useFetchVideos = () => {
const newArray = responseData.slice(0, findVideo);
dispatch(setCountNewVideos(newArray.length));
return;
} catch (error) {}
} catch (error) {console.log(error)}
}, [videos]);
const getVideosCount = React.useCallback(async () => {
try {
let url = `/arbitrary/resources/search?mode=ALL&includemetadata=false&limit=0&service=DOCUMENT&identifier=${QTUBE_VIDEO_BASE}`;
const url = `/arbitrary/resources/search?mode=ALL&includemetadata=false&limit=0&service=DOCUMENT&identifier=${QTUBE_VIDEO_BASE}`;
const response = await fetch(url, {
method: "GET",
@ -436,7 +434,6 @@ export const useFetchVideos = () => {
dispatch(setVideosPerNamePublished(videosPerNamePublished));
} catch (error) {
console.log({ error });
} finally {
}
}, []);

View File

@ -46,6 +46,14 @@ export function objectToBase64(obj: any) {
})
}
export function objectToFile(obj: any) {
// Step 1: Convert the object to a JSON string
const jsonString = JSON.stringify(obj)
// Step 2: Create a Blob from the JSON string
const blob = new Blob([jsonString], { type: 'application/json' })
return blob
}
export function objectToUint8Array(obj: any) {
// Convert the object to a JSON string
const jsonString = JSON.stringify(obj)