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

Dependencies updated to React 19

Minor bugfixes
This commit is contained in:
Qortal Dev 2024-12-30 09:53:21 -07:00
parent 5fad85baa7
commit f687b3025d
22 changed files with 1859 additions and 4976 deletions

View File

@ -1,15 +1,18 @@
module.exports = { module.exports = {
env: { browser: true, es2020: true }, env: { browser: true, amd: true, node: true, es2020: true },
extends: [ extends: [
'eslint:recommended', "eslint:recommended",
'plugin:@typescript-eslint/recommended', "plugin:@typescript-eslint/recommended",
'plugin:react-hooks/recommended', "plugin:react-hooks/recommended",
], ],
parser: '@typescript-eslint/parser', parser: "@typescript-eslint/parser",
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' }, parserOptions: { ecmaVersion: "latest", sourceType: "module" },
plugins: ['react-refresh'], plugins: ["react-refresh"],
rules: { rules: {
'react-refresh/only-export-components': 'warn', "react-refresh/only-export-components": "warn",
'@typescript-eslint/no-explicit-any': "off", "@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unused-vars": "warn",
"@typescript-eslint/no-unused-expressions": "off",
"@typescript-eslint/ban-ts-comment": "off",
}, },
} };

6554
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -10,43 +10,44 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@emotion/react": "^11.10.6", "@emotion/react": "^11.14.0",
"@emotion/styled": "^11.10.6", "@emotion/styled": "^11.14.0",
"@mui/icons-material": "^5.11.11", "@mui/icons-material": "^6.3.0",
"@mui/lab": "^5.0.0-alpha.163", "@mui/lab": "^6.0.0-beta.21",
"@mui/material": "^5.11.13", "@mui/material": "^6.3.0",
"@preact/signals-react": "^2.2.0", "@preact/signals-react": "^2.3.0",
"@reduxjs/toolkit": "^1.9.3", "@reduxjs/toolkit": "^2.5.0",
"compressorjs": "^1.2.1", "compressorjs": "^1.2.1",
"dompurify": "^3.0.6", "dompurify": "^3.2.3",
"localforage": "^1.10.0", "localforage": "^1.10.0",
"moment": "^2.29.4", "moment": "^2.30.1",
"quill": "^2.0.2",
"quill-image-resize-module-react": "^3.0.0", "quill-image-resize-module-react": "^3.0.0",
"react": "^18.2.0", "react": "^19.0.0",
"react-dom": "^18.2.0", "react-dom": "^19.0.0",
"react-dropzone": "^14.2.3", "react-dropzone": "^14.3.5",
"react-idle-timer": "^5.7.2", "react-idle-timer": "^5.7.2",
"react-intersection-observer": "^9.4.3", "react-intersection-observer": "^9.14.0",
"react-quill": "^2.0.0", "react-quill-new": "^3.3.3",
"react-redux": "^8.0.5", "react-redux": "^9.2.0",
"react-rnd": "^10.4.1", "react-rnd": "^10.4.14",
"react-router-dom": "^6.9.0", "react-router-dom": "^7.1.1",
"react-toastify": "^9.1.2", "react-toastify": "^11.0.2",
"redux-persist": "^6.0.0", "redux-persist": "^6.0.0",
"short-unique-id": "^4.4.4", "short-unique-id": "^5.2.0",
"ts-key-enum": "^2.0.12" "ts-key-enum": "^2.0.13"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.0.28", "@types/react": "^19.0.2",
"@types/react-dom": "^18.0.11", "@types/react-dom": "^19.0.2",
"@typescript-eslint/eslint-plugin": "^5.57.1", "@typescript-eslint/eslint-plugin": "^8.18.2",
"@typescript-eslint/parser": "^5.57.1", "@typescript-eslint/parser": "^8.18.2",
"@vitejs/plugin-react": "^4.2.1", "@vitejs/plugin-react": "^4.3.4",
"eslint": "^8.38.0", "eslint": "^9.17.0",
"eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.3.4", "eslint-plugin-react-refresh": "^0.4.16",
"prettier": "^2.8.6", "prettier": "^3.4.2",
"typescript": "^5.0.2", "typescript": "^5.7.2",
"vite": "^5.0.5" "vite": "^6.0.6"
} }
} }

View File

@ -13,7 +13,7 @@ import { PlaylistContent } from "./pages/ContentPages/PlaylistContent/PlaylistCo
import { VideoContent } from "./pages/ContentPages/VideoContent/VideoContent"; import { VideoContent } from "./pages/ContentPages/VideoContent/VideoContent";
import { Home } from "./pages/Home/Home"; import { Home } from "./pages/Home/Home";
import { setFilteredSubscriptions } from "./state/features/videoSlice.ts"; import { setFilteredSubscriptions } from "./state/features/videoSlice.ts";
import { store } from "./state/store"; import { store, persistor } from "./state/store";
import { darkTheme, lightTheme } from "./styles/theme"; import { darkTheme, lightTheme } from "./styles/theme";
import DownloadWrapper from "./wrappers/DownloadWrapper"; import DownloadWrapper from "./wrappers/DownloadWrapper";
import GlobalWrapper from "./wrappers/GlobalWrapper"; import GlobalWrapper from "./wrappers/GlobalWrapper";
@ -21,7 +21,7 @@ import { ScrollWrapper } from "./wrappers/ScrollWrapper.tsx";
function App() { function App() {
// const themeColor = window._qdnTheme // const themeColor = window._qdnTheme
const persistor = persistStore(store);
const [theme, setTheme] = useState("dark"); const [theme, setTheme] = useState("dark");
useIframe(); useIframe();

View File

@ -290,7 +290,7 @@ export const EditPlaylist = () => {
code: codeValue, code: codeValue,
}; };
}); });
const id = uid(); const id = uid.rnd();
let commentsId = editVideoProperties?.id; let commentsId = editVideoProperties?.id;

View File

@ -1,25 +1,6 @@
import React, { useEffect, useState } from "react";
import Compressor from "compressorjs";
import { formatBytes } from "../../../utils/numberFunctions.ts";
import {
AddCoverImageButton,
AddLogoIcon,
CoverImagePreview,
CrowdfundActionButton,
CrowdfundActionButtonRow,
CustomInputField,
CustomSelect,
LogoPreviewRow,
ModalBody,
NewCrowdfundTitle,
StyledButton,
TimesIcon,
} from "./EditVideo-styles.tsx";
import { CircularProgress } from "@mui/material";
import { import {
Box, Box,
CircularProgress,
FormControl, FormControl,
InputLabel, InputLabel,
MenuItem, MenuItem,
@ -30,40 +11,47 @@ import {
Typography, Typography,
useTheme, useTheme,
} from "@mui/material"; } from "@mui/material";
import ShortUniqueId from "short-unique-id"; import { Signal, useSignal } from "@preact/signals-react";
import { useDispatch, useSelector } from "react-redux"; import Compressor from "compressorjs";
import AddBoxIcon from "@mui/icons-material/AddBox"; import React, { useEffect, useState } from "react";
import { useDropzone } from "react-dropzone"; import { useDropzone } from "react-dropzone";
import { useDispatch, useSelector } from "react-redux";
import { setNotification } from "../../../state/features/notificationsSlice.ts"; import ShortUniqueId from "short-unique-id";
import {
objectToBase64,
objectToFile,
uint8ArrayToBase64,
} from "../../../utils/PublishFormatter.ts";
import { RootState } from "../../../state/store.ts";
import {
upsertVideosBeginning,
addToHashMap,
upsertVideos,
setEditVideo,
updateVideo,
updateInHashMap,
} from "../../../state/features/videoSlice.ts";
import ImageUploader from "../../common/ImageUploader.tsx";
import { categories, subCategories } from "../../../constants/Categories.ts"; import { categories, subCategories } from "../../../constants/Categories.ts";
import { MultiplePublish } from "../MultiplePublish/MultiplePublishAll.tsx";
import { TextEditor } from "../../common/TextEditor/TextEditor.tsx";
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 { QTUBE_VIDEO_BASE } from "../../../constants/Identifiers.ts";
import { import {
maxSize, maxSize,
titleFormatter, titleFormatter,
videoMaxSize, videoMaxSize,
} from "../../../constants/Misc.ts"; } from "../../../constants/Misc.ts";
import { Signal, useSignal } from "@preact/signals-react";
import { setNotification } from "../../../state/features/notificationsSlice.ts";
import {
setEditVideo,
updateInHashMap,
updateVideo,
} from "../../../state/features/videoSlice.ts";
import { RootState } from "../../../state/store.ts";
import { objectToBase64 } from "../../../utils/PublishFormatter.ts";
import { FrameExtractor } from "../../common/FrameExtractor/FrameExtractor.tsx";
import ImageUploader from "../../common/ImageUploader.tsx";
import { TextEditor } from "../../common/TextEditor/TextEditor.tsx";
import { extractTextFromHTML } from "../../common/TextEditor/utils.ts";
import { MultiplePublish } from "../MultiplePublish/MultiplePublishAll.tsx";
import { toBase64 } from "../PublishVideo/PublishVideo.tsx";
import {
AddCoverImageButton,
AddLogoIcon,
CoverImagePreview,
CrowdfundActionButton,
CrowdfundActionButtonRow,
CustomInputField,
LogoPreviewRow,
ModalBody,
NewCrowdfundTitle,
TimesIcon,
} from "./EditVideo-styles.tsx";
const uid = new ShortUniqueId(); const uid = new ShortUniqueId();
const shortuid = new ShortUniqueId({ length: 5 }); const shortuid = new ShortUniqueId({ length: 5 });

View File

@ -269,13 +269,13 @@ export const PublishVideo = ({
.trim() .trim()
.toLowerCase(); .toLowerCase();
const id = uid(); const id = uid.rnd();
const identifier = editId const identifier = editId
? editId ? editId
: `${QTUBE_VIDEO_BASE}${sanitizeTitle.slice(0, 30)}_${id}`; : `${QTUBE_VIDEO_BASE}${sanitizeTitle.slice(0, 30)}_${id}`;
const code = shortuid(); const code = shortuid.rnd();
const fullDescription = extractTextFromHTML(description); const fullDescription = extractTextFromHTML(description);
let fileExtension = "mp4"; let fileExtension = "mp4";
@ -365,7 +365,7 @@ export const PublishVideo = ({
.trim() .trim()
.toLowerCase(); .toLowerCase();
const id = uid(); const id = uid.rnd();
const identifier = editId const identifier = editId
? editId ? editId

View File

@ -54,7 +54,7 @@ const ResponsiveImage: React.FC<ResponsiveImageProps> = ({
<img <img
onLoad={() => setLoading(false)} onLoad={() => setLoading(false)}
src={!src && !loading ? DeletedVideo : src} src={!src && !loading ? DeletedVideo : src || null}
style={{ style={{
width: "100%", width: "100%",
height: "100%", height: "100%",

View File

@ -201,7 +201,7 @@ export const CommentEditor = ({
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
const id = uid(); const id = uid.rnd();
let identifier = `${COMMENT_BASE}${postId.slice(-12)}_base_${id}`; let identifier = `${COMMENT_BASE}${postId.slice(-12)}_base_${id}`;
let idForNotification = identifier; let idForNotification = identifier;

View File

@ -111,7 +111,7 @@ export const SuperLike = ({
20 20
)};id:${identifier.slice(-30)}**`; )};id:${identifier.slice(-30)}**`;
const id = uid(); const id = uid.rnd();
const identifierSuperLike = `${SUPER_LIKE_BASE}${identifier.slice( const identifierSuperLike = `${SUPER_LIKE_BASE}${identifier.slice(
0, 0,
39 39

View File

@ -15,7 +15,6 @@ export const FrameExtractor = ({
videoDurations, videoDurations,
index, index,
}: FrameExtractorProps) => { }: FrameExtractorProps) => {
useSignals();
const videoRef = useRef(null); const videoRef = useRef(null);
const [durations, setDurations] = useState([]); const [durations, setDurations] = useState([]);
const canvasRef = useRef(null); const canvasRef = useRef(null);
@ -29,8 +28,9 @@ export const FrameExtractor = ({
const newVideoDurations = [...videoDurations.value]; const newVideoDurations = [...videoDurations.value];
newVideoDurations[index] = duration; newVideoDurations[index] = duration;
console.log("durations before update: ", videoDurations.value);
videoDurations.value = [...newVideoDurations]; videoDurations.value = [...newVideoDurations];
console.log("durations after update: ", videoDurations.value);
const section = duration / 4; const section = duration / 4;
const timestamps = []; const timestamps = [];

View File

@ -33,7 +33,7 @@ export const ListSuperLikeContainer = () => {
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "center",
alignItems: "center", alignItems: "center",
marginTop: "60px", marginTop: "40px",
}, },
anchorReference: "none", anchorReference: "none",
}} }}

View File

@ -246,7 +246,7 @@ export const CommentEditor = ({
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
try { try {
const id = uid(); const id = uid.rnd();
let identifier = `${COMMENT_BASE}${postId.slice(-12)}_base_${id}`; let identifier = `${COMMENT_BASE}${postId.slice(-12)}_base_${id}`;
let idForNotification = identifier; let idForNotification = identifier;

View File

@ -1,11 +1,7 @@
import { useMemo } from "react";
import DOMPurify from "dompurify";
import "react-quill/dist/quill.snow.css";
import "react-quill/dist/quill.core.css";
import "react-quill/dist/quill.bubble.css";
import { convertQortalLinks } from "./utils";
import { Box, styled } from "@mui/material"; import { Box, styled } from "@mui/material";
import DOMPurify from "dompurify";
import { useMemo } from "react";
import { convertQortalLinks } from "./utils";
const CrowdfundInlineContent = styled(Box)(({ theme }) => ({ const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
display: "flex", display: "flex",
@ -14,7 +10,7 @@ const CrowdfundInlineContent = styled(Box)(({ theme }) => ({
fontWeight: 400, fontWeight: 400,
letterSpacing: 0, letterSpacing: 0,
color: theme.palette.text.primary, color: theme.palette.text.primary,
width: '100%' width: "100%",
})); }));
export const DisplayHtml = ({ html }) => { export const DisplayHtml = ({ html }) => {
@ -24,8 +20,7 @@ export const DisplayHtml = ({ html }) => {
const sanitize: string = DOMPurify.sanitize(html, { const sanitize: string = DOMPurify.sanitize(html, {
USE_PROFILES: { html: true }, USE_PROFILES: { html: true },
}); });
const anchorQortal = convertQortalLinks(sanitize); return convertQortalLinks(sanitize);
return anchorQortal;
}, [html]); }, [html]);
if (!cleanContent) return null; if (!cleanContent) return null;

View File

@ -0,0 +1 @@
@import "react-quill-new/dist/quill.snow.css";

View File

@ -1,6 +1,11 @@
import React from "react"; import React from "react";
import ReactQuill, { Quill } from "react-quill";
import "react-quill/dist/quill.snow.css"; import ReactQuill, { Quill } from "react-quill-new";
import "./TextEditor.css";
// The quill-image-resize-module-react package does not have ts types defined,
// so the ts error must be ignored
// @ts-ignore
import ImageResize from "quill-image-resize-module-react"; import ImageResize from "quill-image-resize-module-react";
Quill.register("modules/imageResize", ImageResize); Quill.register("modules/imageResize", ImageResize);

View File

@ -14,7 +14,6 @@ export const useVideoControlsState = (
props: VideoPlayerProps, props: VideoPlayerProps,
videoPlayerState: ReturnType<typeof useVideoPlayerState> videoPlayerState: ReturnType<typeof useVideoPlayerState>
) => { ) => {
useSignals();
const { const {
src, src,
getSrc, getSrc,

View File

@ -94,7 +94,7 @@ export const useVideoPlayerState = (props: VideoPlayerProps, ref: any) => {
}, [downloads, identifier]); }, [downloads, identifier]);
const src = useMemo(() => { const src = useMemo(() => {
return download?.url || ""; return download?.url || null;
}, [download?.url]); }, [download?.url]);
const resourceStatus = useMemo(() => { const resourceStatus = useMemo(() => {

View File

@ -91,7 +91,7 @@ export const VideoPlayer = forwardRef<videoRefType, VideoPlayerProps>(
id={identifier} id={identifier}
ref={videoRef} ref={videoRef}
src={ src={
resourceStatus?.status === "READY" && startPlay.value ? src : "" resourceStatus?.status === "READY" && startPlay.value ? src : null
} }
poster={startPlay.value ? "" : poster} poster={startPlay.value ? "" : poster}
onTimeUpdate={updateProgress} onTimeUpdate={updateProgress}

View File

@ -1,27 +1,32 @@
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
import ReactDOM from "react-dom";
import { Box, IconButton, Slider, useTheme } from "@mui/material";
import { CircularProgress, Typography } from "@mui/material";
import { Key } from "ts-key-enum";
import { import {
PlayArrow,
Pause,
VolumeUp,
Fullscreen, Fullscreen,
MoreVert as MoreIcon,
Pause,
PictureInPicture, PictureInPicture,
PlayArrow,
Refresh,
VolumeOff, VolumeOff,
VolumeUp,
} from "@mui/icons-material"; } from "@mui/icons-material";
import CloseIcon from "@mui/icons-material/Close";
import {
Box,
IconButton,
Menu,
MenuItem,
Slider,
Typography,
useTheme,
} from "@mui/material";
import { styled } from "@mui/system"; import { styled } from "@mui/system";
import React, { useContext, useEffect, useMemo, useRef, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Key } from "ts-key-enum";
import { setVideoPlaying } from "../../../state/features/globalSlice.ts";
import { RootState } from "../../../state/store.ts";
import { formatTime } from "../../../utils/numberFunctions.ts"; import { formatTime } from "../../../utils/numberFunctions.ts";
import { MyContext } from "../../../wrappers/DownloadWrapper.tsx"; import { MyContext } from "../../../wrappers/DownloadWrapper.tsx";
import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../../../state/store.ts";
import { Refresh } from "@mui/icons-material";
import CloseIcon from "@mui/icons-material/Close";
import { Menu, MenuItem } from "@mui/material";
import { MoreVert as MoreIcon } from "@mui/icons-material";
import { setVideoPlaying } from "../../../state/features/globalSlice.ts";
const VideoContainer = styled(Box)` const VideoContainer = styled(Box)`
position: relative; position: relative;
display: flex; display: flex;

View File

@ -13,6 +13,7 @@ import {
PERSIST, PERSIST,
PURGE, PURGE,
REGISTER, REGISTER,
persistStore,
} from "redux-persist"; } from "redux-persist";
import storage from "redux-persist/lib/storage"; import storage from "redux-persist/lib/storage";
@ -46,3 +47,5 @@ export type RootState = ReturnType<typeof store.getState>;
// Define the AppDispatch type, which is the type of the Redux store's dispatch function. // Define the AppDispatch type, which is the type of the Redux store's dispatch function.
// This is useful when you need to dispatch an action in a component or elsewhere. // This is useful when you need to dispatch an action in a component or elsewhere.
export type AppDispatch = typeof store.dispatch; export type AppDispatch = typeof store.dispatch;
export const persistor = persistStore(store);

View File

@ -10,7 +10,6 @@
"moduleResolution": "bundler", "moduleResolution": "bundler",
"allowImportingTsExtensions": true, "allowImportingTsExtensions": true,
"resolveJsonModule": true, "resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true, "noEmit": true,
"jsx": "react-jsx", "jsx": "react-jsx",