Browse Source

Updates to User Interface

Layout of VideoContent.tsx and PlaylistContent.tsx updated, so it will feel more familiar to users.

Video Description boxes will not show the expand/contract button if the contracted description shows all text. The height of the contracted description is doubled.

Deleted Video Image no longer appears in VideoContent.tsx until after the video is loaded.

A new hotkey 'o' on the Video Player lets users switch between maintaining aspect ratio or filling all available space

Description and file downloader don't appear if video is deleted

In PlaylistContent.tsx and VideoContent.tsx, clicking anywhere other than the description or commentEditors will focus the video so that hotkeys will work on it
pull/35/head
Qortal Dev 1 month ago
parent
commit
a16639be84
  1. 3
      src/components/Publish/PublishVideo/PublishVideo-styles.tsx
  2. 18
      src/components/common/Comments/CommentSection.tsx
  3. 8
      src/components/common/Comments/Comments-styles.tsx
  4. 20
      src/components/common/Notifications/Notifications.tsx
  5. 6
      src/components/common/SuperLikesList/Comments-styles.tsx
  6. 24
      src/components/common/SuperLikesList/SuperLikesSection.tsx
  7. 23
      src/components/common/VideoPlayer/VideoPlayer.tsx
  8. 1
      src/pages/ContentPages/PlaylistContent/PlaylistContent-styles.tsx
  9. 221
      src/pages/ContentPages/PlaylistContent/PlaylistContent.tsx
  10. 56
      src/pages/ContentPages/VideoContent/VideoContent-functions.ts
  11. 11
      src/pages/ContentPages/VideoContent/VideoContent-styles.tsx
  12. 627
      src/pages/ContentPages/VideoContent/VideoContent.tsx
  13. 1
      src/state/features/persistSlice.ts
  14. 15
      src/wrappers/GlobalWrapper.tsx

3
src/components/Publish/PublishVideo/PublishVideo-styles.tsx

@ -175,8 +175,7 @@ export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
export const CrowdfundSubTitleRow = styled(Box)({ export const CrowdfundSubTitleRow = styled(Box)({
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "start",
width: "100%",
flexDirection: "row", flexDirection: "row",
}); });

18
src/components/common/Comments/CommentSection.tsx

@ -28,8 +28,8 @@ interface CommentSectionProps {
const Panel = styled("div")` const Panel = styled("div")`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: start;
align-items: center; align-items: start;
width: 100%; width: 100%;
padding-bottom: 10px; padding-bottom: 10px;
height: 100%; height: 100%;
@ -57,7 +57,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
const { user } = useSelector((state: RootState) => state.auth); const { user } = useSelector((state: RootState) => state.auth);
const [newMessages, setNewMessages] = useState(0); const [newMessages, setNewMessages] = useState(0);
const [loadingComments, setLoadingComments] = useState<boolean>(false); const [loadingComments, setLoadingComments] = useState<boolean>(false);
// console.log("postId is: ", postId, " postName is: ", postName);
const onSubmit = (obj?: any, isEdit?: boolean) => { const onSubmit = (obj?: any, isEdit?: boolean) => {
if (isEdit) { if (isEdit) {
setListComments((prev: any[]) => { setListComments((prev: any[]) => {
@ -113,6 +113,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
)}_reply_${removeBaseCommentId.slice( )}_reply_${removeBaseCommentId.slice(
-6 -6
)}&limit=0&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`; )}&limit=0&includemetadata=false&offset=${offset}&reverse=false&excludeblocked=true`;
const response = await fetch(url, { const response = await fetch(url, {
method: "GET", method: "GET",
headers: { headers: {
@ -120,6 +121,7 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
}, },
}); });
const responseData = await response.json(); const responseData = await response.json();
const comments: any[] = []; const comments: any[] = [];
for (const comment of responseData) { for (const comment of responseData) {
if (comment.identifier && comment.name) { if (comment.identifier && comment.name) {
@ -163,6 +165,9 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
}, },
}); });
const responseData = await response.json(); const responseData = await response.json();
// console.log("url is: ", url);
// console.log("response is: ", responseData);
let comments: any[] = []; let comments: any[] = [];
for (const comment of responseData) { for (const comment of responseData) {
if (comment.identifier && comment.name) { if (comment.identifier && comment.name) {
@ -222,18 +227,13 @@ export const CommentSection = ({ postId, postName }: CommentSectionProps) => {
return ( return (
<> <>
<Panel> <Panel>
<CrowdfundSubTitleRow>
<CrowdfundSubTitle>Comments</CrowdfundSubTitle>
</CrowdfundSubTitleRow>
<CommentsContainer> <CommentsContainer>
{loadingComments ? ( {loadingComments ? (
<NoCommentsRow> <NoCommentsRow>
<CircularProgress /> <CircularProgress />
</NoCommentsRow> </NoCommentsRow>
) : listComments.length === 0 ? ( ) : listComments.length === 0 ? (
<NoCommentsRow> <></>
There are no comments yet. Be the first to comment!
</NoCommentsRow>
) : ( ) : (
<CommentContainer> <CommentContainer>
{structuredCommentList.map((comment: any) => { {structuredCommentList.map((comment: any) => {

8
src/components/common/Comments/Comments-styles.tsx

@ -93,7 +93,7 @@ export const StyledCardComment = styled(Typography)(({ theme }) => ({
fontWeight: 400, fontWeight: 400,
color: theme.palette.text.primary, color: theme.palette.text.primary,
fontSize: "19px", fontSize: "19px",
wordBreak: "break-word" wordBreak: "break-word",
})); }));
export const TitleText = styled(Typography)({ export const TitleText = styled(Typography)({
@ -159,7 +159,7 @@ export const BlockIconContainer = styled(Box)({
}); });
export const CommentsContainer = styled(Box)({ export const CommentsContainer = styled(Box)({
width: "90%", width: "70%",
maxWidth: "1000px", maxWidth: "1000px",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
@ -180,7 +180,7 @@ export const CommentContainer = styled(Box)({
export const NoCommentsRow = styled(Box)({ export const NoCommentsRow = styled(Box)({
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "start",
flex: "1", flex: "1",
padding: "10px 0px", padding: "10px 0px",
fontFamily: "Mulish", fontFamily: "Mulish",
@ -218,7 +218,7 @@ export const CommentActionButtonRow = styled(Box)({
export const CommentEditorContainer = styled(Box)({ export const CommentEditorContainer = styled(Box)({
width: "100%", width: "100%",
display: "flex", display: "flex",
justifyContent: "center", justifyContent: "start",
}); });
export const CommentDateText = styled(Typography)(({ theme }) => ({ export const CommentDateText = styled(Typography)(({ theme }) => ({

20
src/components/common/Notifications/Notifications.tsx

@ -16,15 +16,15 @@ import React, {
useState, useState,
} from "react"; } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { RootState } from "../../../state/store";
import NotificationsIcon from "@mui/icons-material/Notifications";
import { formatDate } from "../../../utils/time";
import ThumbUpIcon from "@mui/icons-material/ThumbUp";
import { import {
extractSigValue, extractSigValue,
getPaymentInfo, getPaymentInfo,
isTimestampWithinRange, isTimestampWithinRange,
} from "../../../pages/ContentPages/VideoContent/VideoContent"; } from "../../../pages/ContentPages/VideoContent/VideoContent-functions.ts";
import { RootState } from "../../../state/store";
import NotificationsIcon from "@mui/icons-material/Notifications";
import { formatDate } from "../../../utils/time";
import ThumbUpIcon from "@mui/icons-material/ThumbUp";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import localForage from "localforage"; import localForage from "localforage";
import moment from "moment"; import moment from "moment";
@ -148,7 +148,7 @@ export const Notifications = () => {
) { ) {
let urlReference = null; let urlReference = null;
try { try {
let idForUrl = extractIdValue(comment?.metadata?.description); const idForUrl = extractIdValue(comment?.metadata?.description);
const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&identifier=${idForUrl}&limit=1&includemetadata=false&reverse=false&excludeblocked=true&offset=0&name=${username}`; const url = `/arbitrary/resources/search?mode=ALL&service=DOCUMENT&identifier=${idForUrl}&limit=1&includemetadata=false&reverse=false&excludeblocked=true&offset=0&name=${username}`;
const response2 = await fetch(url, { const response2 = await fetch(url, {
method: "GET", method: "GET",
@ -160,7 +160,9 @@ export const Notifications = () => {
if (responseSearch.length > 0) { if (responseSearch.length > 0) {
urlReference = responseSearch[0]; urlReference = responseSearch[0];
} }
} catch (error) {} } catch (error) {
console.log(error);
}
// const url = `/arbitrary/BLOG_COMMENT/${comment.name}/${comment.identifier}`; // const url = `/arbitrary/BLOG_COMMENT/${comment.name}/${comment.identifier}`;
// const response = await fetch(url, { // const response = await fetch(url, {
// method: "GET", // method: "GET",
@ -180,7 +182,9 @@ export const Notifications = () => {
}, },
]; ];
} }
} catch (error) {} } catch (error) {
console.log(error);
}
} }
} }
setNotifications(prev => { setNotifications(prev => {

6
src/components/common/SuperLikesList/Comments-styles.tsx

@ -93,7 +93,7 @@ export const StyledCardComment = styled(Typography)(({ theme }) => ({
fontWeight: 400, fontWeight: 400,
color: theme.palette.text.primary, color: theme.palette.text.primary,
fontSize: "19px", fontSize: "19px",
wordBreak: "break-word" wordBreak: "break-word",
})); }));
export const TitleText = styled(Typography)({ export const TitleText = styled(Typography)({
@ -159,7 +159,7 @@ export const BlockIconContainer = styled(Box)({
}); });
export const CommentsContainer = styled(Box)({ export const CommentsContainer = styled(Box)({
width: "90%", width: "70%",
maxWidth: "1000px", maxWidth: "1000px",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
@ -180,7 +180,7 @@ export const CommentContainer = styled(Box)({
export const NoCommentsRow = styled(Box)({ export const NoCommentsRow = styled(Box)({
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "start",
flex: "1", flex: "1",
padding: "10px 0px", padding: "10px 0px",
fontFamily: "Mulish", fontFamily: "Mulish",

24
src/components/common/SuperLikesList/SuperLikesSection.tsx

@ -24,15 +24,15 @@ interface CommentSectionProps {
postId: string; postId: string;
postName: string; postName: string;
superlikes: any[]; superlikes: any[];
getMore: () => void; getMore?: () => void;
loadingSuperLikes: boolean; loadingSuperLikes: boolean;
} }
const Panel = styled("div")` const Panel = styled("div")`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: start;
align-items: center; align-items: start;
width: 100%; width: 100%;
padding-bottom: 10px; padding-bottom: 10px;
height: 100%; height: 100%;
@ -199,30 +199,18 @@ export const SuperLikesSection = ({
return ( return (
<> <>
<Panel> <Panel>
<CrowdfundSubTitleRow>
<CrowdfundSubTitle
sx={{
fontSize: "18px",
color: "gold",
}}
>
Super Likes
</CrowdfundSubTitle>
</CrowdfundSubTitleRow>
<CommentsContainer> <CommentsContainer>
{loadingComments || loadingSuperLikes ? ( {loadingComments || loadingSuperLikes ? (
<NoCommentsRow> <NoCommentsRow>
<CircularProgress /> <CircularProgress />
</NoCommentsRow> </NoCommentsRow>
) : listComments.length === 0 ? ( ) : listComments.length === 0 ? (
<NoCommentsRow> <></>
There are no super likes yet. Be the first!
</NoCommentsRow>
) : ( ) : (
<CommentContainer> <CommentContainer>
{structuredCommentList.map((comment: any) => { {structuredCommentList.map((comment: any) => {
let hasHash = false; let hasHash = false;
let message = { ...comment }; const message = { ...comment };
let hash = {}; let hash = {};
if (hashMapSuperlikes[comment?.identifier]) { if (hashMapSuperlikes[comment?.identifier]) {
message.message = message.message =
@ -249,7 +237,7 @@ export const SuperLikesSection = ({
<LoadMoreCommentsButtonRow> <LoadMoreCommentsButtonRow>
<LoadMoreCommentsButton <LoadMoreCommentsButton
onClick={() => { onClick={() => {
getMore(); if (getMore) getMore();
}} }}
variant="contained" variant="contained"
size="small" size="small"

23
src/components/common/VideoPlayer/VideoPlayer.tsx

@ -34,7 +34,11 @@ import {
VideoElement, VideoElement,
} from "./VideoPlayer-styles.ts"; } from "./VideoPlayer-styles.ts";
import CSS from "csstype"; import CSS from "csstype";
import { setReduxPlaybackRate } from "../../../state/features/persistSlice.ts"; import {
setReduxPlaybackRate,
setStretchVideoSetting,
StretchVideoType,
} from "../../../state/features/persistSlice.ts";
export interface VideoStyles { export interface VideoStyles {
videoContainer?: CSS.Properties; videoContainer?: CSS.Properties;
@ -101,6 +105,10 @@ export const VideoPlayer = React.forwardRef<refType, VideoPlayerProps>(
const [anchorEl, setAnchorEl] = useState(null); const [anchorEl, setAnchorEl] = useState(null);
const [showControlsFullScreen, setShowControlsFullScreen] = const [showControlsFullScreen, setShowControlsFullScreen] =
useState<boolean>(true); useState<boolean>(true);
const [videoObjectFit, setVideoObjectFit] = useState<StretchVideoType>(
persistSelector.stretchVideoSetting
);
const videoPlaying = useSelector( const videoPlaying = useSelector(
(state: RootState) => state.global.videoPlaying (state: RootState) => state.global.videoPlaying
); );
@ -597,10 +605,21 @@ export const VideoPlayer = React.forwardRef<refType, VideoPlayerProps>(
} }
}; };
const toggleStretchVideoSetting = () => {
const newStretchVideoSetting =
persistSelector.stretchVideoSetting === "contain" ? "fill" : "contain";
setVideoObjectFit(newStretchVideoSetting);
dispatch(setStretchVideoSetting(newStretchVideoSetting));
};
const keyboardShortcutsDown = (e: React.KeyboardEvent<HTMLDivElement>) => { const keyboardShortcutsDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
e.preventDefault(); e.preventDefault();
switch (e.key) { switch (e.key) {
case "o":
toggleStretchVideoSetting();
break;
case Key.Add: case Key.Add:
increaseSpeed(false); increaseSpeed(false);
break; break;
@ -825,7 +844,7 @@ export const VideoPlayer = React.forwardRef<refType, VideoPlayerProps>(
startPlay startPlay
? { ? {
...videoStyles?.video, ...videoStyles?.video,
objectFit: persistSelector.stretchVideoSetting, objectFit: videoObjectFit,
} }
: { height: "100%", ...videoStyles } : { height: "100%", ...videoStyles }
} }

1
src/pages/ContentPages/PlaylistContent/PlaylistContent-styles.tsx

@ -2,7 +2,6 @@ import { styled } from "@mui/system";
import { Box, Grid, Typography, Checkbox } from "@mui/material"; import { Box, Grid, Typography, Checkbox } from "@mui/material";
export const VideoPlayerContainer = styled(Box)(({ theme }) => ({ export const VideoPlayerContainer = styled(Box)(({ theme }) => ({
maxWidth: "95%",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "flex-start", alignItems: "flex-start",

221
src/pages/ContentPages/PlaylistContent/PlaylistContent.tsx

@ -20,6 +20,11 @@ import AttachFileIcon from "@mui/icons-material/AttachFile";
import DownloadIcon from "@mui/icons-material/Download"; import DownloadIcon from "@mui/icons-material/Download";
import mockImg from "../../../test/mockimg.jpg"; import mockImg from "../../../test/mockimg.jpg";
import {
extractSigValue,
getPaymentInfo,
isTimestampWithinRange,
} from "../VideoContent/VideoContent-functions.ts";
import { import {
AuthorTextComment, AuthorTextComment,
FileAttachmentContainer, FileAttachmentContainer,
@ -48,11 +53,6 @@ import { DisplayHtml } from "../../../components/common/TextEditor/DisplayHtml.t
import FileElement from "../../../components/common/FileElement.tsx"; import FileElement from "../../../components/common/FileElement.tsx";
import { SuperLike } from "../../../components/common/ContentButtons/SuperLike.tsx"; import { SuperLike } from "../../../components/common/ContentButtons/SuperLike.tsx";
import { useFetchSuperLikes } from "../../../hooks/useFetchSuperLikes.tsx"; import { useFetchSuperLikes } from "../../../hooks/useFetchSuperLikes.tsx";
import {
extractSigValue,
getPaymentInfo,
isTimestampWithinRange,
} from "../VideoContent/VideoContent.tsx";
import { SuperLikesSection } from "../../../components/common/SuperLikesList/SuperLikesSection.tsx"; import { SuperLikesSection } from "../../../components/common/SuperLikesList/SuperLikesSection.tsx";
import { import {
QTUBE_VIDEO_BASE, QTUBE_VIDEO_BASE,
@ -196,6 +196,7 @@ export const PlaylistContent = () => {
setVideoData(combinedData); setVideoData(combinedData);
dispatch(addToHashMap(combinedData)); dispatch(addToHashMap(combinedData));
checkforPlaylist(name, id); checkforPlaylist(name, id);
} }
} }
@ -275,11 +276,8 @@ export const PlaylistContent = () => {
const fullId = vid ? `${vid.identifier}-${vid.name}` : undefined; const fullId = vid ? `${vid.identifier}-${vid.name}` : undefined;
const existingVideo = hashMapVideos[fullId]; const existingVideo = hashMapVideos[fullId];
if (existingVideo) { if (existingVideo) setVideoData(existingVideo);
setVideoData(existingVideo); else getVideoData(vid?.name, vid?.identifier);
} else {
getVideoData(vid?.name, vid?.identifier);
}
} }
} }
} }
@ -298,13 +296,12 @@ export const PlaylistContent = () => {
} }
}, [id, channelName]); }, [id, channelName]);
const descriptionThreshold = 200;
useEffect(() => { useEffect(() => {
if (contentRef.current) { if (contentRef.current) {
const height = contentRef.current.offsetHeight; const height = contentRef.current.offsetHeight;
if (height > 100) { if (height > descriptionThreshold)
// Assuming 100px is your threshold setDescriptionHeight(descriptionThreshold);
setDescriptionHeight(100);
}
} }
}, [videoData]); }, [videoData]);
@ -409,13 +406,27 @@ export const PlaylistContent = () => {
}, [getComments, videoData?.id, nameAddress]); }, [getComments, videoData?.id, nameAddress]);
const focusVideo = (e: React.MouseEvent<HTMLDivElement>) => { const focusVideo = (e: React.MouseEvent<HTMLDivElement>) => {
const focusRef = containerRef.current?.getContainerRef()?.current; console.log("in focusVideo");
const isCorrectTarget = e.currentTarget == e.target; const target = e.target as Element;
if (focusRef && isCorrectTarget) {
const textTagNames = ["TEXTAREA", "P", "H[1-6]", "STRONG", "svg", "A"];
const noText =
textTagNames.findIndex(s => {
return target?.tagName.match(s);
}) < 0;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const clickOnEmptySpace = !target?.onclick && noText;
console.log("tagName is: ", target?.tagName);
if (target == e.currentTarget || clickOnEmptySpace) {
console.log("in correctTarget");
const focusRef = containerRef.current?.getContainerRef()?.current;
focusRef.focus({ preventScroll: true }); focusRef.focus({ preventScroll: true });
} }
}; };
return ( return (
<Box <Box
sx={{ sx={{
@ -423,6 +434,7 @@ export const PlaylistContent = () => {
alignItems: "center", alignItems: "center",
flexDirection: "column", flexDirection: "column",
padding: "0px 10px", padding: "0px 10px",
marginLeft: "5%",
}} }}
onClick={focusVideo} onClick={focusVideo}
> >
@ -492,7 +504,6 @@ export const PlaylistContent = () => {
gridTemplateColumns: "1fr 1fr", gridTemplateColumns: "1fr 1fr",
}} }}
> >
{" "}
<Box> <Box>
<StyledCardHeaderComment <StyledCardHeaderComment
sx={{ sx={{
@ -627,108 +638,104 @@ export const PlaylistContent = () => {
)} )}
<Spacer height="30px" /> <Spacer height="30px" />
<Box {videoData?.fullDescription && (
sx={{
background: "#333333",
borderRadius: "5px",
padding: "5px",
width: "100%",
cursor: !descriptionHeight
? "default"
: isExpandedDescription
? "default"
: "pointer",
position: "relative",
}}
className={
!descriptionHeight
? ""
: isExpandedDescription
? ""
: "hover-click"
}
>
{descriptionHeight && !isExpandedDescription && (
<Box
sx={{
position: "absolute",
top: "0px",
right: "0px",
left: "0px",
bottom: "0px",
cursor: "pointer",
}}
onClick={() => {
if (isExpandedDescription) return;
setIsExpandedDescription(true);
}}
/>
)}
<Box <Box
ref={contentRef}
sx={{ sx={{
height: !descriptionHeight background: "#333333",
? "auto" borderRadius: "5px",
padding: "5px",
width: "100%",
cursor: !descriptionHeight
? "default"
: isExpandedDescription : isExpandedDescription
? "auto" ? "default"
: "100px", : "pointer",
overflow: "hidden", position: "relative",
}} }}
className={
!descriptionHeight
? ""
: isExpandedDescription
? ""
: "hover-click"
}
> >
{videoData?.htmlDescription ? ( {descriptionHeight && !isExpandedDescription && (
<DisplayHtml html={videoData?.htmlDescription} /> <Box
) : (
<VideoDescription
variant="body1"
color="textPrimary"
sx={{ sx={{
cursor: "default", position: "absolute",
top: "0px",
right: "0px",
left: "0px",
bottom: "0px",
cursor: "pointer",
}} }}
> onClick={() => {
{videoData?.fullDescription} if (isExpandedDescription) return;
</VideoDescription> setIsExpandedDescription(true);
}}
/>
)} )}
</Box> <Box
{descriptionHeight && ( ref={contentRef}
<Typography
onClick={() => {
setIsExpandedDescription(prev => !prev);
}}
sx={{ sx={{
fontWeight: "bold", height: !descriptionHeight
fontSize: "16px", ? "auto"
cursor: "pointer", : isExpandedDescription
paddingLeft: "15px", ? "auto"
paddingTop: "15px", : `${descriptionHeight}px`,
overflow: "hidden",
}} }}
> >
{isExpandedDescription ? "Show less" : "...more"} {videoData?.htmlDescription ? (
</Typography> <DisplayHtml html={videoData?.htmlDescription} />
)} ) : (
</Box> <VideoDescription
variant="body1"
color="textPrimary"
sx={{
cursor: "default",
}}
>
{videoData?.fullDescription}
</VideoDescription>
)}
</Box>
{descriptionHeight >= descriptionThreshold && (
<Typography
onClick={() => {
setIsExpandedDescription(prev => !prev);
}}
sx={{
fontWeight: "bold",
fontSize: "16px",
cursor: "pointer",
paddingLeft: "15px",
paddingTop: "15px",
}}
>
{isExpandedDescription ? "Show less" : "...more"}
</Typography>
)}
</Box>
)}
</> </>
)} )}
{videoData?.id && videoData?.user && (
<SuperLikesSection
loadingSuperLikes={loadingSuperLikes}
superlikes={superlikeList}
postId={videoData?.id || ""}
postName={videoData?.user || ""}
/>
)}
{videoData?.id && channelName && (
<CommentSection
postId={videoData?.id || ""}
postName={channelName || ""}
/>
)}
</VideoPlayerContainer> </VideoPlayerContainer>
<SuperLikesSection
getMore={() => {}}
loadingSuperLikes={loadingSuperLikes}
superlikes={superlikeList}
postId={videoData?.id || ""}
postName={videoData?.user || ""}
/>
<Box
sx={{
display: "flex",
gap: "20px",
width: "100%",
maxWidth: "1200px",
}}
>
<CommentSection
postId={videoData?.id || ""}
postName={channelName || ""}
/>
</Box>
</Box> </Box>
); );
}; };

56
src/pages/ContentPages/VideoContent/VideoContent-functions.ts

@ -0,0 +1,56 @@
export function isTimestampWithinRange(resTimestamp, resCreated) {
// Calculate the absolute difference in milliseconds
const difference = Math.abs(resTimestamp - resCreated);
// 2 minutes in milliseconds
const twoMinutesInMilliseconds = 3 * 60 * 1000;
// Check if the difference is within 2 minutes
return difference <= twoMinutesInMilliseconds;
}
export function extractSigValue(metadescription) {
// Function to extract the substring within double asterisks
function extractSubstring(str) {
const match = str.match(/\*\*(.*?)\*\*/);
return match ? match[1] : null;
}
// Function to extract the 'sig' value
function extractSig(str) {
const regex = /sig:(.*?)(;|$)/;
const match = str.match(regex);
return match ? match[1] : null;
}
// Extracting the relevant substring
const relevantSubstring = extractSubstring(metadescription);
if (relevantSubstring) {
// Extracting the 'sig' value
return extractSig(relevantSubstring);
} else {
return null;
}
}
export const getPaymentInfo = async (signature: string) => {
try {
const url = `/transactions/signature/${signature}`;
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
// Coin payment info must be added to responseData so we can display it to the user
const responseData = await response.json();
if (responseData && !responseData.error) {
return responseData;
} else {
throw new Error("unable to get payment");
}
} catch (error) {
throw new Error("unable to get payment");
}
};

11
src/pages/ContentPages/VideoContent/VideoContent-styles.tsx

@ -1,12 +1,15 @@
import { styled } from "@mui/system"; import { styled } from "@mui/system";
import { Box, Grid, Typography, Checkbox } from "@mui/material"; import { Box, Grid, Typography, Checkbox } from "@mui/material";
export const VideoPlayerContainer = styled(Box)(({ theme }) => ({ export const VideoContentContainer = styled(Box)(({ theme }) => ({
maxWidth: "95%",
width: "1000px",
display: "flex", display: "flex",
flexDirection: "column", flexDirection: "column",
alignItems: "flex-start", alignItems: "start",
}));
export const VideoPlayerContainer = styled(Box)(({ theme }) => ({
width: "55vw",
marginLeft: "5%",
})); }));
export const VideoTitle = styled(Typography)(({ theme }) => ({ export const VideoTitle = styled(Typography)(({ theme }) => ({

627
src/pages/ContentPages/VideoContent/VideoContent.tsx

@ -1,26 +1,45 @@
import DownloadIcon from "@mui/icons-material/Download";
import { Avatar, Box, Typography, useTheme } from "@mui/material";
import React, { import React, {
useState, useCallback,
useEffect,
useMemo, useMemo,
useRef, useRef,
useEffect, useState,
useCallback,
} from "react"; } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useNavigate, useParams } from "react-router-dom"; import { useNavigate, useParams } from "react-router-dom";
import ResponsiveImage from "../../../components/ResponsiveImage.tsx"; import DeletedVideo from "../../../assets/img/DeletedVideo.jpg";
import { setIsLoadingGlobal } from "../../../state/features/globalSlice.ts"; import { CommentSection } from "../../../components/common/Comments/CommentSection.tsx";
import { Avatar, Box, Typography, useTheme } from "@mui/material"; import { FollowButton } from "../../../components/common/ContentButtons/FollowButton.tsx";
import { LikeAndDislike } from "../../../components/common/ContentButtons/LikeAndDislike.tsx";
import { SubscribeButton } from "../../../components/common/ContentButtons/SubscribeButton.tsx";
import { SuperLike } from "../../../components/common/ContentButtons/SuperLike.tsx";
import FileElement from "../../../components/common/FileElement.tsx";
import { SuperLikesSection } from "../../../components/common/SuperLikesList/SuperLikesSection.tsx";
import { DisplayHtml } from "../../../components/common/TextEditor/DisplayHtml.tsx";
import { import {
refType, refType,
VideoPlayer, VideoPlayer,
} from "../../../components/common/VideoPlayer/VideoPlayer.tsx"; } from "../../../components/common/VideoPlayer/VideoPlayer.tsx";
import { RootState } from "../../../state/store.ts"; import {
QTUBE_VIDEO_BASE,
SUPER_LIKE_BASE,
} from "../../../constants/Identifiers.ts";
import {
minPriceSuperlike,
titleFormatterOnSave,
} from "../../../constants/Misc.ts";
import { useFetchSuperLikes } from "../../../hooks/useFetchSuperLikes.tsx";
import { setIsLoadingGlobal } from "../../../state/features/globalSlice.ts";
import { addToHashMap } from "../../../state/features/videoSlice.ts"; import { addToHashMap } from "../../../state/features/videoSlice.ts";
import AttachFileIcon from "@mui/icons-material/AttachFile"; import { RootState } from "../../../state/store.ts";
import DownloadIcon from "@mui/icons-material/Download"; import { formatDate } from "../../../utils/time.ts";
import DeletedVideo from "../../../assets/img/DeletedVideo.jpg"; import {
extractSigValue,
import mockImg from "../../../test/mockimg.jpg"; getPaymentInfo,
isTimestampWithinRange,
} from "./VideoContent-functions.ts";
import { import {
AuthorTextComment, AuthorTextComment,
FileAttachmentContainer, FileAttachmentContainer,
@ -29,98 +48,10 @@ import {
StyledCardColComment, StyledCardColComment,
StyledCardHeaderComment, StyledCardHeaderComment,
VideoDescription, VideoDescription,
VideoPlayerContainer, VideoContentContainer,
VideoTitle, VideoTitle,
VideoPlayerContainer,
} from "./VideoContent-styles.tsx"; } from "./VideoContent-styles.tsx";
import { setUserAvatarHash } from "../../../state/features/globalSlice.ts";
import {
formatDate,
formatDateSeconds,
formatTimestampSeconds,
} from "../../../utils/time.ts";
import { NavbarName } from "../../../components/layout/Navbar/Navbar-styles.tsx";
import { CommentSection } from "../../../components/common/Comments/CommentSection.tsx";
import {
CrowdfundSubTitle,
CrowdfundSubTitleRow,
} from "../../../components/Publish/PublishVideo/PublishVideo-styles.tsx";
import { Playlists } from "../../../components/Playlists/Playlists.tsx";
import { DisplayHtml } from "../../../components/common/TextEditor/DisplayHtml.tsx";
import FileElement from "../../../components/common/FileElement.tsx";
import { SuperLike } from "../../../components/common/ContentButtons/SuperLike.tsx";
import { CommentContainer } from "../../../components/common/Comments/Comments-styles.tsx";
import { Comment } from "../../../components/common/Comments/Comment.tsx";
import { SuperLikesSection } from "../../../components/common/SuperLikesList/SuperLikesSection.tsx";
import { useFetchSuperLikes } from "../../../hooks/useFetchSuperLikes.tsx";
import {
FOR_SUPER_LIKE,
QTUBE_VIDEO_BASE,
SUPER_LIKE_BASE,
} from "../../../constants/Identifiers.ts";
import {
minPriceSuperlike,
titleFormatterOnSave,
} from "../../../constants/Misc.ts";
import { SubscribeButton } from "../../../components/common/ContentButtons/SubscribeButton.tsx";
import { FollowButton } from "../../../components/common/ContentButtons/FollowButton.tsx";
import { LikeAndDislike } from "../../../components/common/ContentButtons/LikeAndDislike.tsx";
export function isTimestampWithinRange(resTimestamp, resCreated) {
// Calculate the absolute difference in milliseconds
const difference = Math.abs(resTimestamp - resCreated);
// 2 minutes in milliseconds
const twoMinutesInMilliseconds = 3 * 60 * 1000;
// Check if the difference is within 2 minutes
return difference <= twoMinutesInMilliseconds;
}
export function extractSigValue(metadescription) {
// Function to extract the substring within double asterisks
function extractSubstring(str) {
const match = str.match(/\*\*(.*?)\*\*/);
return match ? match[1] : null;
}
// Function to extract the 'sig' value
function extractSig(str) {
const regex = /sig:(.*?)(;|$)/;
const match = str.match(regex);
return match ? match[1] : null;
}
// Extracting the relevant substring
const relevantSubstring = extractSubstring(metadescription);
if (relevantSubstring) {
// Extracting the 'sig' value
return extractSig(relevantSubstring);
} else {
return null;
}
}
export const getPaymentInfo = async (signature: string) => {
try {
const url = `/transactions/signature/${signature}`;
const response = await fetch(url, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
});
// Coin payment info must be added to responseData so we can display it to the user
const responseData = await response.json();
if (responseData && !responseData.error) {
return responseData;
} else {
throw new Error("unable to get payment");
}
} catch (error) {
throw new Error("unable to get payment");
}
};
export const VideoContent = () => { export const VideoContent = () => {
const { name: channelName, id } = useParams(); const { name: channelName, id } = useParams();
@ -130,6 +61,7 @@ export const VideoContent = () => {
useState<boolean>(false); useState<boolean>(false);
const [superlikeList, setSuperlikelist] = useState<any[]>([]); const [superlikeList, setSuperlikelist] = useState<any[]>([]);
const [loadingSuperLikes, setLoadingSuperLikes] = useState<boolean>(false); const [loadingSuperLikes, setLoadingSuperLikes] = useState<boolean>(false);
const { addSuperlikeRawDataGetToList } = useFetchSuperLikes(); const { addSuperlikeRawDataGetToList } = useFetchSuperLikes();
const containerRef = useRef<refType>(null); const containerRef = useRef<refType>(null);
@ -149,6 +81,8 @@ export const VideoContent = () => {
const [descriptionHeight, setDescriptionHeight] = useState<null | number>( const [descriptionHeight, setDescriptionHeight] = useState<null | number>(
null null
); );
const [videoData, setVideoData] = useState<any>(null);
const [isVideoLoaded, setIsVideoLoaded] = useState<boolean>(false);
const userAvatarHash = useSelector( const userAvatarHash = useSelector(
(state: RootState) => state.global.userAvatarHash (state: RootState) => state.global.userAvatarHash
@ -183,8 +117,6 @@ export const VideoContent = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const theme = useTheme(); const theme = useTheme();
const [videoData, setVideoData] = useState<any>(null);
const saveAsFilename = useMemo(() => { const saveAsFilename = useMemo(() => {
// nb. we prefer to construct the local filename to use for // nb. we prefer to construct the local filename to use for
// saving, from the video "title" when possible // saving, from the video "title" when possible
@ -224,6 +156,7 @@ export const VideoContent = () => {
videoReference?.name && videoReference?.name &&
videoReference?.service videoReference?.service
) { ) {
setIsVideoLoaded(true);
return videoReference; return videoReference;
} else { } else {
return null; return null;
@ -302,13 +235,12 @@ export const VideoContent = () => {
} }
}, [id, channelName]); }, [id, channelName]);
const descriptionThreshold = 200;
useEffect(() => { useEffect(() => {
if (contentRef.current) { if (contentRef.current) {
const height = contentRef.current.offsetHeight; const height = contentRef.current.offsetHeight;
if (height > 100) { if (height > descriptionThreshold)
// Assuming 100px is your threshold setDescriptionHeight(descriptionThreshold);
setDescriptionHeight(100);
}
} }
}, [videoData]); }, [videoData]);
@ -382,35 +314,42 @@ export const VideoContent = () => {
); );
const focusVideo = (e: React.MouseEvent<HTMLDivElement>) => { const focusVideo = (e: React.MouseEvent<HTMLDivElement>) => {
const focusRef = containerRef.current?.getContainerRef()?.current; console.log("in focusVideo");
const isCorrectTarget = e.currentTarget == e.target; const target = e.target as Element;
if (focusRef && isCorrectTarget) {
const textTagNames = ["TEXTAREA", "P", "H[1-6]", "STRONG", "svg", "A"];
const noText =
textTagNames.findIndex(s => {
return target?.tagName.match(s);
}) < 0;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const clickOnEmptySpace = !target?.onclick && noText;
console.log("tagName is: ", target?.tagName);
// clicking on link in superlikes bar shows deleted video when loading
if (target == e.currentTarget || clickOnEmptySpace) {
console.log("in correctTarget");
const focusRef = containerRef.current?.getContainerRef()?.current;
focusRef.focus({ preventScroll: true }); focusRef.focus({ preventScroll: true });
} }
}; };
return ( return (
<Box <>
sx={{ <Box
display: "flex",
alignItems: "center",
flexDirection: "column",
padding: "0px 10px",
}}
onClick={focusVideo}
>
<VideoPlayerContainer
sx={{ sx={{
width: "55vw", display: "flex",
aspectRatio: "16/9", marginLeft: "5%",
flexDirection: "column",
padding: "0px 10px",
}} }}
onClick={focusVideo}
> >
{videoReference ? ( {videoReference ? (
<Box <VideoPlayerContainer>
sx={{
aspectRatio: "16/9",
}}
>
<VideoPlayer <VideoPlayer
name={videoReference?.name} name={videoReference?.name}
service={videoReference?.service} service={videoReference?.service}
@ -424,46 +363,35 @@ export const VideoContent = () => {
video: { aspectRatio: "16 / 9" }, video: { aspectRatio: "16 / 9" },
}} }}
/> />
</Box> </VideoPlayerContainer>
) : isVideoLoaded ? (
<img
src={DeletedVideo}
width={"70%"}
height={"37%"}
style={{ marginLeft: "5%" }}
/>
) : ( ) : (
<img src={DeletedVideo} width={"100%"} height={"100%"} /> <Box sx={{ width: "55vw", aspectRatio: "16/9" }}></Box>
)} )}
<Box <VideoContentContainer>
sx={{ <Box
width: "100%", sx={{
display: "grid", width: "80%",
gridTemplateColumns: "1fr 1fr", display: "grid",
marginTop: "15px", gridTemplateColumns: "1fr 1fr",
}} marginTop: "15px",
> }}
<Box> >
<StyledCardHeaderComment <Box>
sx={{ <StyledCardHeaderComment
"& .MuiCardHeader-content": {
overflow: "hidden",
},
}}
>
<Box
sx={{ sx={{
cursor: "pointer", "& .MuiCardHeader-content": {
}} overflow: "hidden",
onClick={() => { },
navigate(`/channel/${channelName}`);
}} }}
> >
<Avatar <Box
src={`/arbitrary/THUMBNAIL/${channelName}/qortal_avatar`}
alt={`${channelName}'s avatar`}
/>
</Box>
<StyledCardColComment>
<AuthorTextComment
color={
theme.palette.mode === "light"
? theme.palette.text.secondary
: "#d6e8ff"
}
sx={{ sx={{
cursor: "pointer", cursor: "pointer",
}} }}
@ -471,196 +399,223 @@ export const VideoContent = () => {
navigate(`/channel/${channelName}`); navigate(`/channel/${channelName}`);
}} }}
> >
{channelName} <Avatar
{channelName !== userName && ( src={`/arbitrary/THUMBNAIL/${channelName}/qortal_avatar`}
<> alt={`${channelName}'s avatar`}
<SubscribeButton />
subscriberName={channelName} </Box>
sx={{ marginLeft: "20px" }} <StyledCardColComment>
/> <AuthorTextComment
<FollowButton color={
followerName={channelName} theme.palette.mode === "light"
sx={{ marginLeft: "20px" }} ? theme.palette.text.secondary
/> : "#d6e8ff"
</> }
)} sx={{
</AuthorTextComment> cursor: "pointer",
</StyledCardColComment> }}
</StyledCardHeaderComment> onClick={() => {
navigate(`/channel/${channelName}`);
}}
>
{channelName}
{channelName !== userName && (
<>
<SubscribeButton
subscriberName={channelName}
sx={{ marginLeft: "20px" }}
/>
<FollowButton
followerName={channelName}
sx={{ marginLeft: "20px" }}
/>
</>
)}
</AuthorTextComment>
</StyledCardColComment>
</StyledCardHeaderComment>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "row",
}}
>
{videoData && (
<>
<LikeAndDislike
name={videoData?.user}
identifier={videoData?.id}
/>
<SuperLike
numberOfSuperlikes={numberOfSuperlikes}
totalAmount={calculateAmountSuperlike}
name={videoData?.user}
service={videoData?.service}
identifier={videoData?.id}
onSuccess={val => {
setSuperlikelist(prev => [val, ...prev]);
}}
/>
</>
)}
{videoData?.filename && (
<FileAttachmentContainer>
<FileAttachmentFont>Save to Disk</FileAttachmentFont>
<FileElement
fileInfo={{
...videoReference,
filename: saveAsFilename,
mimeType: videoData?.videoType || '"video/mp4',
}}
title={
videoData?.filename || videoData?.title?.slice(0, 20)
}
customStyles={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
}}
>
<DownloadIcon />
</FileElement>
</FileAttachmentContainer>
)}
</Box>
</Box> </Box>
<Box <Box
sx={{ sx={{
display: "flex", display: "flex",
flexDirection: "row", justifyContent: "space-between",
alignItems: "center",
width: "100%",
marginTop: "20px",
gap: "10px",
}} }}
> >
{videoData && ( <VideoTitle
<> variant="h1"
<LikeAndDislike color="textPrimary"
name={videoData?.user}
identifier={videoData?.id}
/>
<SuperLike
numberOfSuperlikes={numberOfSuperlikes}
totalAmount={calculateAmountSuperlike}
name={videoData?.user}
service={videoData?.service}
identifier={videoData?.id}
onSuccess={val => {
setSuperlikelist(prev => [val, ...prev]);
}}
/>
</>
)}
<FileAttachmentContainer>
<FileAttachmentFont>Save to Disk</FileAttachmentFont>
<FileElement
fileInfo={{
...videoReference,
filename: saveAsFilename,
mimeType: videoData?.videoType || '"video/mp4',
}}
title={videoData?.filename || videoData?.title?.slice(0, 20)}
customStyles={{
display: "flex",
alignItems: "center",
justifyContent: "flex-end",
}}
>
<DownloadIcon />
</FileElement>
</FileAttachmentContainer>
</Box>
</Box>
<Box
sx={{
display: "flex",
justifyContent: "space-between",
alignItems: "center",
width: "100%",
marginTop: "20px",
gap: "10px",
}}
>
<VideoTitle
variant="h1"
color="textPrimary"
sx={{
textAlign: "start",
}}
>
{videoData?.title}
</VideoTitle>
</Box>
{videoData?.created && (
<Typography
variant="h6"
sx={{
fontSize: "16px",
}}
color={theme.palette.text.primary}
>
{formatDate(videoData.created)}
</Typography>
)}
<Spacer height="30px" />
<Box
sx={{
background: "#333333",
borderRadius: "5px",
padding: "5px",
width: "100%",
cursor: !descriptionHeight
? "default"
: isExpandedDescription
? "default"
: "pointer",
position: "relative",
}}
className={
!descriptionHeight ? "" : isExpandedDescription ? "" : "hover-click"
}
>
{descriptionHeight && !isExpandedDescription && (
<Box
sx={{ sx={{
position: "absolute", textAlign: "start",
top: "0px",
right: "0px",
left: "0px",
bottom: "0px",
cursor: "pointer",
}}
onClick={() => {
if (isExpandedDescription) return;
setIsExpandedDescription(true);
}} }}
/> >
)} {videoData?.title}
<Box </VideoTitle>
ref={contentRef}
sx={{
height: !descriptionHeight
? "auto"
: isExpandedDescription
? "auto"
: "100px",
overflow: "hidden",
}}
>
{videoData?.htmlDescription ? (
<DisplayHtml html={videoData?.htmlDescription} />
) : (
<VideoDescription
variant="body1"
color="textPrimary"
sx={{
cursor: "default",
}}
>
{videoData?.fullDescription}
</VideoDescription>
)}
</Box> </Box>
{descriptionHeight && (
{videoData?.created && (
<Typography <Typography
onClick={() => { variant="h6"
setIsExpandedDescription(prev => !prev);
}}
sx={{ sx={{
fontWeight: "bold",
fontSize: "16px", fontSize: "16px",
cursor: "pointer",
paddingLeft: "15px",
paddingTop: "15px",
}} }}
color={theme.palette.text.primary}
> >
{isExpandedDescription ? "Show less" : "...more"} {formatDate(videoData.created)}
</Typography> </Typography>
)} )}
</Box>
</VideoPlayerContainer>
<SuperLikesSection
/* eslint-disable-next-line @typescript-eslint/no-empty-function */
getMore={() => {}}
loadingSuperLikes={loadingSuperLikes}
superlikes={superlikeList}
postId={id || ""}
postName={channelName || ""}
/>
<Box <Spacer height="30px" />
sx={{ {videoData?.fullDescription && (
display: "flex", <Box
gap: "20px", sx={{
width: "100%", background: "#333333",
maxWidth: "1200px", borderRadius: "5px",
}} padding: "5px",
> width: "70%",
<CommentSection postId={id || ""} postName={channelName || ""} /> cursor: !descriptionHeight
? "default"
: isExpandedDescription
? "default"
: "pointer",
position: "relative",
marginBottom: "30px",
}}
className={
!descriptionHeight
? ""
: isExpandedDescription
? ""
: "hover-click"
}
>
{descriptionHeight && !isExpandedDescription && (
<Box
sx={{
position: "absolute",
top: "0px",
right: "0px",
left: "0px",
bottom: "0px",
cursor: "pointer",
}}
onClick={() => {
if (isExpandedDescription) return;
setIsExpandedDescription(true);
}}
/>
)}
<Box
ref={contentRef}
sx={{
height: !descriptionHeight
? "auto"
: isExpandedDescription
? "auto"
: "200px",
overflow: "hidden",
}}
>
{videoData?.htmlDescription ? (
<DisplayHtml html={videoData?.htmlDescription} />
) : (
<VideoDescription
variant="body1"
color="textPrimary"
sx={{
cursor: "default",
}}
>
{videoData?.fullDescription}
</VideoDescription>
)}
</Box>
{descriptionHeight >= descriptionThreshold && (
<Typography
onClick={() => {
setIsExpandedDescription(prev => !prev);
}}
sx={{
fontWeight: "bold",
fontSize: "16px",
cursor: "pointer",
paddingLeft: "15px",
paddingTop: "15px",
}}
>
{isExpandedDescription ? "Show less" : "...more"}
</Typography>
)}
</Box>
)}
{id && channelName && (
<>
<SuperLikesSection
/* eslint-disable-next-line @typescript-eslint/no-empty-function */
getMore={() => {}}
loadingSuperLikes={loadingSuperLikes}
superlikes={superlikeList}
postId={id || ""}
postName={channelName || ""}
/>
<CommentSection postId={id || ""} postName={channelName || ""} />
</>
)}
</VideoContentContainer>
</Box> </Box>
</Box> </>
); );
}; };

1
src/state/features/persistSlice.ts

@ -77,6 +77,7 @@ export const persistSlice = createSlice({
export const { export const {
setHomePageSelectedTab, setHomePageSelectedTab,
setStretchVideoSetting,
subscribe, subscribe,
unSubscribe, unSubscribe,
setReduxPlaybackRate, setReduxPlaybackRate,

15
src/wrappers/GlobalWrapper.tsx

@ -6,6 +6,11 @@ import React, {
useMemo, useMemo,
} from "react"; } from "react";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import {
extractSigValue,
getPaymentInfo,
isTimestampWithinRange,
} from "../pages/ContentPages/VideoContent/VideoContent-functions.ts";
import { addUser } from "../state/features/authSlice"; import { addUser } from "../state/features/authSlice";
import NavBar from "../components/layout/Navbar/Navbar"; import NavBar from "../components/layout/Navbar/Navbar";
@ -21,11 +26,6 @@ import { RequestQueue } from "../utils/queue";
import { EditVideo } from "../components/Publish/EditVideo/EditVideo"; import { EditVideo } from "../components/Publish/EditVideo/EditVideo";
import { EditPlaylist } from "../components/Publish/EditPlaylist/EditPlaylist"; import { EditPlaylist } from "../components/Publish/EditPlaylist/EditPlaylist";
import ConsentModal from "../components/common/ConsentModal"; import ConsentModal from "../components/common/ConsentModal";
import {
extractSigValue,
getPaymentInfo,
isTimestampWithinRange,
} from "../pages/ContentPages/VideoContent/VideoContent";
import { useFetchSuperLikes } from "../hooks/useFetchSuperLikes"; import { useFetchSuperLikes } from "../hooks/useFetchSuperLikes";
import { SUPER_LIKE_BASE } from "../constants/Identifiers.ts"; import { SUPER_LIKE_BASE } from "../constants/Identifiers.ts";
import { minPriceSuperlike } from "../constants/Misc.ts"; import { minPriceSuperlike } from "../constants/Misc.ts";
@ -185,7 +185,9 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
]; ];
validCount++; validCount++;
} }
} catch (error) {} } catch (error) {
console.log(error);
}
} }
} }
} }
@ -194,7 +196,6 @@ const GlobalWrapper: React.FC<Props> = ({ children, setTheme }) => {
dispatch(setSuperlikesAll(comments)); dispatch(setSuperlikesAll(comments));
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} finally {
} }
}, []); }, []);

Loading…
Cancel
Save