Browse Source

Fixed video skeleton not loading bug.

Deleted videos are not filtered out. They are now visible and show an image on the Home, Channel, and VideoContent pages that says "This video has been removed by the user".

Fixed minification bug caused by store.ts

titleFormatter and titleFormatterOnSave redone, only characters not allowed by Operating Systems are filtered out when saving as file.
pull/30/head
Qortal Dev 2 months ago
parent
commit
6412417891
  1. BIN
      src/assets/img/DeletedVideo.jpg
  2. 68
      src/components/ResponsiveImage.tsx
  3. 5
      src/components/common/SuperLikesList/CommentEditor.tsx
  4. 7
      src/constants/Misc.ts
  5. 7
      src/pages/ContentPages/VideoContent/VideoContent.tsx
  6. 22
      src/pages/Home/VideoList.tsx
  7. 1
      src/state/store.ts
  8. 35
      src/utils/fetchVideos.ts

BIN
src/assets/img/DeletedVideo.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

68
src/components/ResponsiveImage.tsx

@ -1,14 +1,14 @@
import React, { useState, useEffect, CSSProperties } from 'react'
import Skeleton from '@mui/material/Skeleton'
import { Box } from '@mui/material'
import React, { useState, useEffect, CSSProperties } from "react";
import Skeleton from "@mui/material/Skeleton";
import { Box } from "@mui/material";
import DeletedVideo from "../assets/img/DeletedVideo.jpg";
interface ResponsiveImageProps {
src: string
width: number
height: number
alt?: string
className?: string
style?: CSSProperties
src: string;
width: number;
height: number;
alt?: string;
className?: string;
style?: CSSProperties;
}
const ResponsiveImage: React.FC<ResponsiveImageProps> = ({
@ -17,49 +17,55 @@ const ResponsiveImage: React.FC<ResponsiveImageProps> = ({
height,
alt,
className,
style
style,
}) => {
const [loading, setLoading] = useState(true)
const [loading, setLoading] = useState(true);
const endLoading = (endTimeSeconds: number) => {
const endTimeMilliSeconds = endTimeSeconds * 1000;
setTimeout(() => {
if (loading) setLoading(false);
}, endTimeMilliSeconds);
};
useEffect(() => endLoading(5), []);
return (
<Box
sx={{
padding: '2px',
height: '100%',
...style
padding: "2px",
height: "100%",
...style,
}}
>
{loading && (
<Skeleton
variant="rectangular"
style={{
width: '100%',
width: "100%",
height: 0,
paddingBottom: `${(height / width) * 100}%`,
objectFit: 'contain',
visibility: loading ? 'visible' : 'hidden',
borderRadius: '8px'
objectFit: "contain",
visibility: loading ? "visible" : "hidden",
borderRadius: "8px",
}}
/>
)}
<img
onLoad={() => setLoading(false)}
src={src}
src={!src && !loading ? DeletedVideo : src}
style={{
width: '100%',
height: '100%',
borderRadius: '8px',
visibility: loading ? 'hidden' : 'visible',
position: loading ? 'absolute' : 'unset',
objectFit: 'contain'
width: "100%",
height: "100%",
borderRadius: "8px",
visibility: loading ? "hidden" : "visible",
position: loading ? "absolute" : "unset",
objectFit: "contain",
}}
/>
</Box>
)
}
);
};
export default ResponsiveImage
export default ResponsiveImage;

5
src/components/common/SuperLikesList/CommentEditor.tsx

@ -181,18 +181,17 @@ export const CommentEditor = ({
notificationInformation: comment.notificationInformation,
about: comment.about,
};
const superLikeToFile = await objectToFile(superObj);
const superLikeToFile = objectToFile(superObj);
dataFile = superLikeToFile;
}
if (isSuperLike && !dataFile)
throw new Error("unable to edit Super like");
const stringFile = stringToFile(value);
const resourceResponse = await qortalRequest({
action: "PUBLISH_QDN_RESOURCE",
name: name,
service: "BLOG_COMMENT",
file: isSuperLike ? dataFile : stringFile,
file: isSuperLike ? dataFile : stringToFile(value),
identifier: identifier,
description,
tag1,

7
src/constants/Misc.ts

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

7
src/pages/ContentPages/VideoContent/VideoContent.tsx

@ -7,6 +7,7 @@ import React, {
} from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom";
import ResponsiveImage from "../../../components/ResponsiveImage.tsx";
import { setIsLoadingGlobal } from "../../../state/features/globalSlice.ts";
import { Avatar, Box, Typography, useTheme } from "@mui/material";
import {
@ -17,6 +18,7 @@ import { RootState } from "../../../state/store.ts";
import { addToHashMap } from "../../../state/features/videoSlice.ts";
import AttachFileIcon from "@mui/icons-material/AttachFile";
import DownloadIcon from "@mui/icons-material/Download";
import DeletedVideo from "../../../assets/img/DeletedVideo.jpg";
import mockImg from "../../../test/mockimg.jpg";
import {
@ -403,7 +405,7 @@ export const VideoContent = () => {
width: "70vw",
}}
>
{videoReference && (
{videoReference ? (
<VideoPlayer
name={videoReference?.name}
service={videoReference?.service}
@ -414,6 +416,8 @@ export const VideoContent = () => {
customStyle={{ aspectRatio: "16/9" }}
ref={containerRef}
/>
) : (
<img src={DeletedVideo} width={"100%"} height={"100%"} />
)}
<Box
sx={{
@ -630,6 +634,7 @@ export const VideoContent = () => {
</Box>
</VideoPlayerContainer>
<SuperLikesSection
/* eslint-disable-next-line @typescript-eslint/no-empty-function */
getMore={() => {}}
loadingSuperLikes={loadingSuperLikes}
superlikes={superlikeList}

22
src/pages/Home/VideoList.tsx

@ -6,7 +6,12 @@ import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { PlaylistSVG } from "../../assets/svgs/PlaylistSVG.tsx";
import ResponsiveImage from "../../components/ResponsiveImage.tsx";
import { blockUser, setEditPlaylist, setEditVideo, Video } from "../../state/features/videoSlice.ts";
import {
blockUser,
setEditPlaylist,
setEditVideo,
Video,
} from "../../state/features/videoSlice.ts";
import { RootState } from "../../state/store.ts";
import { formatDate } from "../../utils/time.ts";
import { VideoCardImageContainer } from "./VideoCardImageContainer.tsx";
@ -55,16 +60,14 @@ export const VideoList = ({ videos }: VideoListProps) => {
if (response === true) {
dispatch(blockUser(user));
}
} catch (error) {console.log(error)}
} catch (error) {
console.log(error);
}
};
const filteredVideos = useMemo(() => {
return videos.filter((video: Video) => hashMapVideos[`${video.id}-${video.user}`]?.isValid);
}, [videos, hashMapVideos]);
return (
<VideoCardContainer>
{filteredVideos.map((video: any) => {
{videos.map((video: any) => {
const fullId = video ? `${video.id}-${video.user}` : undefined;
const existingVideo = hashMapVideos[fullId];
let hasHash = false;
@ -244,11 +247,6 @@ export const VideoList = ({ videos }: VideoListProps) => {
videoImage={videoObj.videoImage}
frameImages={videoObj?.extracts || []}
/>
{/* <ResponsiveImage
src={videoObj.videoImage}
width={266}
height={150}
/> */}
<VideoCardTitle>{videoObj.title}</VideoCardTitle>
<BottomParent>
<NameContainer

1
src/state/store.ts

@ -1,3 +1,4 @@
/* eslint-disable */
import { combineReducers, configureStore } from "@reduxjs/toolkit";
import notificationsReducer from "./features/notificationsSlice";
import authReducer from "./features/authSlice";

35
src/utils/fetchVideos.ts

@ -1,36 +1,35 @@
import { checkStructure } from './checkStructure'
import { checkStructure } from "./checkStructure";
export const fetchAndEvaluateVideos = async (data: any) => {
const getVideo = async () => {
const { user, videoId, content } = data
const { user, videoId, content } = data;
let obj: any = {
...content,
isValid: false
}
};
if (!user || !videoId) return obj
if (!user || !videoId) return obj;
try {
const responseData = await qortalRequest({
action: 'FETCH_QDN_RESOURCE',
action: "FETCH_QDN_RESOURCE",
name: user,
service: content?.service || 'DOCUMENT',
identifier: videoId
})
service: content?.service || "DOCUMENT",
identifier: videoId,
});
if (responseData) {
obj = {
...content,
...responseData,
isValid: true
}
isValid: true,
isDeleted: false,
};
}
return obj
return obj;
} catch (error: any) {
throw new Error(error?.message || 'error')
throw new Error(error?.message || "error");
}
}
};
const res = await getVideo()
return res
}
const res = await getVideo();
return res;
};

Loading…
Cancel
Save