mirror of
https://github.com/Qortal/q-tube.git
synced 2025-02-11 17:55:51 +00:00
Merge pull request #18 from QortalSeth/main
Final updates to new Q-Tube 2.0 release
This commit is contained in:
commit
0fc8fb5c5c
@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "qtube",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"version": "2.0.0",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
|
48
src/App.tsx
48
src/App.tsx
@ -1,8 +1,8 @@
|
||||
import { useState } from "react";
|
||||
import { Routes, Route } from "react-router-dom";
|
||||
import { useEffect, useState } from "react";
|
||||
import { Route, Routes } from "react-router-dom";
|
||||
import { ThemeProvider } from "@mui/material/styles";
|
||||
import { CssBaseline } from "@mui/material";
|
||||
import { lightTheme, darkTheme } from "./styles/theme";
|
||||
import { darkTheme, lightTheme } from "./styles/theme";
|
||||
import { store } from "./state/store";
|
||||
import { Provider } from "react-redux";
|
||||
import GlobalWrapper from "./wrappers/GlobalWrapper";
|
||||
@ -14,6 +14,8 @@ import { IndividualProfile } from "./pages/IndividualProfile/IndividualProfile";
|
||||
import { PlaylistContent } from "./pages/PlaylistContent/PlaylistContent";
|
||||
import { PersistGate } from "redux-persist/integration/react";
|
||||
import { persistStore } from "redux-persist";
|
||||
import { setFilteredSubscriptions } from "./state/features/videoSlice.ts";
|
||||
import { SubscriptionObject } from "./state/features/persistSlice.ts";
|
||||
|
||||
function App() {
|
||||
// const themeColor = window._qdnTheme
|
||||
@ -21,6 +23,46 @@ function App() {
|
||||
const [theme, setTheme] = useState("dark");
|
||||
let persistor = persistStore(store);
|
||||
|
||||
const filterVideosByName = (
|
||||
subscriptionList: SubscriptionObject[],
|
||||
userName: string
|
||||
) => {
|
||||
return subscriptionList.filter(item => {
|
||||
return item.userName === userName;
|
||||
});
|
||||
};
|
||||
|
||||
const getUserName = async () => {
|
||||
const account = await qortalRequest({
|
||||
action: "GET_USER_ACCOUNT",
|
||||
});
|
||||
const nameData = await qortalRequest({
|
||||
action: "GET_ACCOUNT_NAMES",
|
||||
address: account.address,
|
||||
});
|
||||
|
||||
if (nameData?.length > 0) return nameData[0].name;
|
||||
else return "";
|
||||
};
|
||||
|
||||
const subscriptionListFilter = async () => {
|
||||
const subscriptionList = store.getState().persist.subscriptionList;
|
||||
const filterByUserName =
|
||||
store.getState().persist.subscriptionListFilter === "currentNameOnly";
|
||||
const userName = await getUserName();
|
||||
|
||||
if (filterByUserName && userName) {
|
||||
return filterVideosByName(subscriptionList, userName);
|
||||
} else return subscriptionList;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const subscriptionList = store.getState().persist.subscriptionList;
|
||||
subscriptionListFilter().then(filteredList => {
|
||||
store.dispatch(setFilteredSubscriptions(filteredList));
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Provider store={store}>
|
||||
<PersistGate loading={null} persistor={persistor}>
|
||||
|
@ -9,7 +9,7 @@ import {
|
||||
Rating,
|
||||
TextField,
|
||||
Typography,
|
||||
Select
|
||||
Select,
|
||||
} from "@mui/material";
|
||||
import AddPhotoAlternateIcon from "@mui/icons-material/AddPhotoAlternate";
|
||||
import { TimesSVG } from "../../assets/svgs/TimesSVG";
|
||||
@ -51,6 +51,9 @@ export const CreateContainer = styled(Box)(({ theme }) => ({
|
||||
borderRadius: "50%",
|
||||
}));
|
||||
|
||||
export const CodecTypography = styled(Typography)(({ theme }) => ({
|
||||
fontSize: "18px",
|
||||
}));
|
||||
export const ModalBody = styled(Box)(({ theme }) => ({
|
||||
position: "absolute",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
@ -159,8 +162,6 @@ export const CustomInputField = styled(TextField)(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
|
||||
export const CrowdfundTitle = styled(Typography)(({ theme }) => ({
|
||||
fontFamily: "Copse",
|
||||
letterSpacing: "1px",
|
||||
@ -539,8 +540,8 @@ export const NoReviewsFont = styled(Typography)(({ theme }) => ({
|
||||
|
||||
export const StyledButton = styled(Button)(({ theme }) => ({
|
||||
fontWeight: 600,
|
||||
color: theme.palette.text.primary
|
||||
}))
|
||||
color: theme.palette.text.primary,
|
||||
}));
|
||||
|
||||
export const CustomSelect = styled(Select)(({ theme }) => ({
|
||||
fontFamily: "Mulish",
|
||||
@ -549,34 +550,34 @@ export const CustomSelect = styled(Select)(({ theme }) => ({
|
||||
fontWeight: 400,
|
||||
color: theme.palette.text.primary,
|
||||
backgroundColor: theme.palette.background.default,
|
||||
'& .MuiSelect-select': {
|
||||
padding: '12px',
|
||||
"& .MuiSelect-select": {
|
||||
padding: "12px",
|
||||
fontFamily: "Mulish",
|
||||
fontSize: "19px",
|
||||
letterSpacing: "0px",
|
||||
fontWeight: 400,
|
||||
borderRadius: theme.shape.borderRadius, // Match border radius
|
||||
},
|
||||
'&:before': {
|
||||
"&:before": {
|
||||
// Underline style
|
||||
borderBottomColor: theme.palette.mode === "light" ? "#B2BAC2" : "#c9cccf",
|
||||
},
|
||||
'&:after': {
|
||||
"&:after": {
|
||||
// Underline style when focused
|
||||
borderBottomColor: theme.palette.secondary.main,
|
||||
},
|
||||
'& .MuiOutlinedInput-root': {
|
||||
'& fieldset': {
|
||||
"& .MuiOutlinedInput-root": {
|
||||
"& fieldset": {
|
||||
borderColor: "#E0E3E7",
|
||||
},
|
||||
'&:hover fieldset': {
|
||||
"&:hover fieldset": {
|
||||
borderColor: "#B2BAC2",
|
||||
},
|
||||
'&.Mui-focused fieldset': {
|
||||
"&.Mui-focused fieldset": {
|
||||
borderColor: "#6F7E8C",
|
||||
},
|
||||
},
|
||||
'& .MuiInputBase-root': {
|
||||
"& .MuiInputBase-root": {
|
||||
fontFamily: "Mulish",
|
||||
fontSize: "19px",
|
||||
letterSpacing: "0px",
|
||||
|
@ -3,6 +3,7 @@ import Compressor from "compressorjs";
|
||||
import {
|
||||
AddCoverImageButton,
|
||||
AddLogoIcon,
|
||||
CodecTypography,
|
||||
CoverImagePreview,
|
||||
CrowdfundActionButton,
|
||||
CrowdfundActionButtonRow,
|
||||
@ -713,15 +714,23 @@ export const PublishVideo = ({ editId, editContent }: NewCrowdfundProps) => {
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Typography sx={{fontSize: "14px"}}>
|
||||
Supported File Containers: MP4, Ogg, WebM, WAV
|
||||
</Typography>
|
||||
<Typography sx={{fontSize: "14px"}}>
|
||||
Audio Codecs: FLAC, MP3, Opus, PCM (8/16/32-bit, μ-law), Vorbis
|
||||
</Typography>
|
||||
<Typography sx={{fontSize: "14px"}}>
|
||||
Video Codecs: AV1, VP8, VP9
|
||||
</Typography>
|
||||
<CodecTypography>
|
||||
Supported File Containers:{" "}
|
||||
<span style={{ fontWeight: "bold" }}>MP4</span>, Ogg, WebM,
|
||||
WAV
|
||||
</CodecTypography>
|
||||
<CodecTypography>
|
||||
Audio Codecs: <span style={{ fontWeight: "bold" }}>Opus</span>
|
||||
, MP3, FLAC, PCM (8/16/32-bit, μ-law), Vorbis
|
||||
</CodecTypography>
|
||||
<CodecTypography>
|
||||
Video Codecs: <span style={{ fontWeight: "bold" }}>AV1</span>,
|
||||
VP8, VP9, H.264
|
||||
</CodecTypography>
|
||||
<CodecTypography sx={{ fontWeight: "800", color: "red" }}>
|
||||
Using unsupported Codecs may result in video or audio not
|
||||
working properly
|
||||
</CodecTypography>
|
||||
</Box>
|
||||
|
||||
<Box
|
||||
|
@ -2,29 +2,57 @@ import { Button, ButtonProps } from "@mui/material";
|
||||
import { MouseEvent, useEffect, useState } from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { RootState } from "../../state/store.ts";
|
||||
import { subscribe, unSubscribe } from "../../state/features/persistSlice.ts";
|
||||
import {
|
||||
resetSubscriptions,
|
||||
subscribe,
|
||||
unSubscribe,
|
||||
} from "../../state/features/persistSlice.ts";
|
||||
import { setFilteredSubscriptions } from "../../state/features/videoSlice.ts";
|
||||
|
||||
interface SubscribeButtonProps extends ButtonProps {
|
||||
name: string;
|
||||
subscriberName: string;
|
||||
}
|
||||
|
||||
export const SubscribeButton = ({ name, ...props }: SubscribeButtonProps) => {
|
||||
export const SubscribeButton = ({
|
||||
subscriberName,
|
||||
...props
|
||||
}: SubscribeButtonProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const persistSelector = useSelector((state: RootState) => {
|
||||
return state.persist;
|
||||
const filteredSubscriptionList = useSelector((state: RootState) => {
|
||||
return state.video.filteredSubscriptionList;
|
||||
});
|
||||
const userName = useSelector((state: RootState) => state.auth.user?.name);
|
||||
const [isSubscribed, setIsSubscribed] = useState<boolean>(false);
|
||||
|
||||
useEffect(() => {
|
||||
setIsSubscribed(persistSelector.subscriptionList.includes(name));
|
||||
const isSubscribedToName =
|
||||
filteredSubscriptionList.find(item => {
|
||||
return item.subscriberName === subscriberName;
|
||||
}) !== undefined;
|
||||
|
||||
setIsSubscribed(isSubscribedToName);
|
||||
}, []);
|
||||
|
||||
const subscriptionData = {
|
||||
userName: userName,
|
||||
subscriberName: subscriberName,
|
||||
};
|
||||
const subscribeToRedux = () => {
|
||||
dispatch(subscribe(name));
|
||||
dispatch(subscribe(subscriptionData));
|
||||
dispatch(
|
||||
setFilteredSubscriptions([...filteredSubscriptionList, subscriptionData])
|
||||
);
|
||||
setIsSubscribed(true);
|
||||
};
|
||||
const unSubscribeFromRedux = () => {
|
||||
dispatch(unSubscribe(name));
|
||||
dispatch(unSubscribe(subscriptionData));
|
||||
dispatch(
|
||||
setFilteredSubscriptions(
|
||||
filteredSubscriptionList.filter(
|
||||
item => item.subscriberName !== subscriptionData.subscriberName
|
||||
)
|
||||
)
|
||||
);
|
||||
setIsSubscribed(false);
|
||||
};
|
||||
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
QTUBE_VIDEO_BASE,
|
||||
} from "../constants/Identifiers.ts";
|
||||
import { allTabValue, subscriptionTabValue } from "../constants/Misc.ts";
|
||||
import { persistReducer } from "redux-persist";
|
||||
|
||||
export const useFetchVideos = () => {
|
||||
const dispatch = useDispatch();
|
||||
@ -48,9 +49,7 @@ export const useFetchVideos = () => {
|
||||
(state: RootState) => state.video.filteredVideos
|
||||
);
|
||||
|
||||
const subscriptions = useSelector(
|
||||
(state: RootState) => state.persist.subscriptionList
|
||||
);
|
||||
const videoReducer = useSelector((state: RootState) => state.video);
|
||||
|
||||
const checkAndUpdateVideo = React.useCallback(
|
||||
(video: Video) => {
|
||||
@ -189,22 +188,38 @@ export const useFetchVideos = () => {
|
||||
}
|
||||
}, [videos, hashMapVideos]);
|
||||
|
||||
type FilterType = {
|
||||
name?: string;
|
||||
category?: string;
|
||||
subcategory?: string;
|
||||
keywords?: string;
|
||||
type?: string;
|
||||
};
|
||||
|
||||
const emptyFilters = {
|
||||
name: "",
|
||||
category: "",
|
||||
subcategory: "",
|
||||
keywords: "",
|
||||
type: "",
|
||||
};
|
||||
const getVideos = React.useCallback(
|
||||
async (
|
||||
filters = {},
|
||||
filters = emptyFilters,
|
||||
reset?: boolean,
|
||||
resetFilters?: boolean,
|
||||
limit?: number,
|
||||
listType = allTabValue
|
||||
) => {
|
||||
emptyFilters.type = filters.type;
|
||||
try {
|
||||
const {
|
||||
name = "",
|
||||
category = "",
|
||||
subcategory = "",
|
||||
keywords = "",
|
||||
type = "",
|
||||
}: any = resetFilters ? {} : filters;
|
||||
type = filters.type,
|
||||
}: FilterType = resetFilters ? emptyFilters : filters;
|
||||
let offset = videos.length;
|
||||
if (reset) {
|
||||
offset = 0;
|
||||
@ -217,8 +232,9 @@ export const useFetchVideos = () => {
|
||||
defaultUrl = defaultUrl + `&name=${name}`;
|
||||
}
|
||||
if (listType === subscriptionTabValue) {
|
||||
subscriptions.map(sub => {
|
||||
defaultUrl += `&name=${sub}`;
|
||||
const filteredSubscribeList = videoReducer.filteredSubscriptionList;
|
||||
filteredSubscribeList.map(sub => {
|
||||
defaultUrl += `&name=${sub.subscriberName}`;
|
||||
});
|
||||
}
|
||||
|
||||
|
18
src/main.tsx
18
src/main.tsx
@ -1,17 +1,17 @@
|
||||
import ReactDOM from 'react-dom/client'
|
||||
import App from './App'
|
||||
import './index.css'
|
||||
import { BrowserRouter } from 'react-router-dom'
|
||||
import ReactDOM from "react-dom/client";
|
||||
import App from "./App";
|
||||
import "./index.css";
|
||||
import { BrowserRouter } from "react-router-dom";
|
||||
interface CustomWindow extends Window {
|
||||
_qdnBase: string
|
||||
_qdnBase: string;
|
||||
}
|
||||
|
||||
const customWindow = window as unknown as CustomWindow
|
||||
const customWindow = window as unknown as CustomWindow;
|
||||
|
||||
const baseUrl = customWindow?._qdnBase || ''
|
||||
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
|
||||
const baseUrl = customWindow?._qdnBase || "";
|
||||
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
||||
<BrowserRouter basename={baseUrl}>
|
||||
<App />
|
||||
<div id="modal-root" />
|
||||
</BrowserRouter>
|
||||
)
|
||||
);
|
||||
|
@ -25,6 +25,7 @@ import {
|
||||
FiltersSubContainer,
|
||||
ProductManagerRow,
|
||||
FiltersRadioButton,
|
||||
StatsCol,
|
||||
} from "./VideoList-styles";
|
||||
import { SubtitleContainer } from "./Home-styles";
|
||||
|
||||
@ -34,7 +35,10 @@ import {
|
||||
changefilterName,
|
||||
changefilterSearch,
|
||||
} from "../../state/features/videoSlice";
|
||||
import { changeFilterType } from "../../state/features/persistSlice.ts";
|
||||
import {
|
||||
changeFilterType,
|
||||
resetSubscriptions,
|
||||
} from "../../state/features/persistSlice.ts";
|
||||
import { categories, subCategories } from "../../constants/Categories.ts";
|
||||
import { ListSuperLikeContainer } from "../../components/common/ListSuperLikes/ListSuperLikeContainer.tsx";
|
||||
import { TabContext, TabList, TabPanel } from "@mui/lab";
|
||||
@ -53,7 +57,7 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
const filterValue = useSelector(
|
||||
(state: RootState) => state.video.filterValue
|
||||
);
|
||||
const persistSelector = useSelector((state: RootState) => state.persist);
|
||||
const persistReducer = useSelector((state: RootState) => state.persist);
|
||||
const filterType = useSelector(
|
||||
(state: RootState) => state.persist.filterType
|
||||
);
|
||||
@ -74,12 +78,12 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
(state: RootState) => state.global.videosPerNamePublished
|
||||
);
|
||||
|
||||
const { videos: globalVideos } = useSelector(
|
||||
const { videos: globalVideos, filteredSubscriptionList } = useSelector(
|
||||
(state: RootState) => state.video
|
||||
);
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||
const [tabValue, setTabValue] = useState<string>(persistSelector.selectedTab);
|
||||
const [tabValue, setTabValue] = useState<string>(persistReducer.selectedTab);
|
||||
|
||||
const tabFontSize = "20px";
|
||||
|
||||
@ -120,8 +124,13 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
const afterFetch = useRef(false);
|
||||
const isFetching = useRef(false);
|
||||
|
||||
const { getVideos, getNewVideos, checkNewVideos, getVideosFiltered, getVideosCount } =
|
||||
useFetchVideos();
|
||||
const {
|
||||
getVideos,
|
||||
getNewVideos,
|
||||
checkNewVideos,
|
||||
getVideosFiltered,
|
||||
getVideosCount,
|
||||
} = useFetchVideos();
|
||||
|
||||
const getVideosHandler = React.useCallback(
|
||||
async (reset?: boolean, resetFilters?: boolean) => {
|
||||
@ -170,7 +179,19 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
firstFetch.current = true;
|
||||
setIsLoading(true);
|
||||
|
||||
await getVideos({ type: filterType }, null, null, 20, tabValue);
|
||||
await getVideos(
|
||||
{
|
||||
name: "",
|
||||
category: "",
|
||||
subcategory: "",
|
||||
keywords: "",
|
||||
type: filterType,
|
||||
},
|
||||
null,
|
||||
null,
|
||||
20,
|
||||
tabValue
|
||||
);
|
||||
afterFetch.current = true;
|
||||
isFetching.current = false;
|
||||
|
||||
@ -227,7 +248,6 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
}, [getVideosHandlerMount, globalVideos]);
|
||||
|
||||
const filtersToDefault = async () => {
|
||||
setFilterType("videos");
|
||||
setFilterSearch("");
|
||||
setFilterName("");
|
||||
setSelectedCategoryVideos(null);
|
||||
@ -273,293 +293,302 @@ export const Home = ({ mode }: HomeProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box sx={{ width: "100%" }}>
|
||||
<Grid container spacing={2} justifyContent="space-around">
|
||||
<Grid item xs={12} sm={4}>
|
||||
Total Videos Published: {totalVideosPublished}
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
Total Names Publishing: {totalNamesPublished}
|
||||
</Grid>
|
||||
<Grid item xs={12} sm={4}>
|
||||
Average Videos per Name: {videosPerNamePublished}
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
<Grid container sx={{ width: "100%" }}>
|
||||
<FiltersCol item xs={12} md={2} lg={2} xl={2} sm={3}>
|
||||
<FiltersContainer>
|
||||
<Input
|
||||
id="standard-adornment-name"
|
||||
onChange={e => {
|
||||
setFilterSearch(e.target.value);
|
||||
}}
|
||||
value={filterSearch}
|
||||
placeholder="Search"
|
||||
onKeyDown={handleInputKeyDown}
|
||||
sx={{
|
||||
borderBottom: "1px solid white",
|
||||
"&&:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:after": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:hover:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
fontSize: "18px",
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
id="standard-adornment-name"
|
||||
onChange={e => {
|
||||
setFilterName(e.target.value);
|
||||
}}
|
||||
value={filterName}
|
||||
placeholder="User's Name (Exact)"
|
||||
onKeyDown={handleInputKeyDown}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
borderBottom: "1px solid white",
|
||||
"&&:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:after": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:hover:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
fontSize: "18px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<FiltersSubContainer>
|
||||
<FormControl sx={{ width: "100%", marginTop: "30px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<FormControl fullWidth sx={{ marginBottom: 1 }}>
|
||||
<InputLabel
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
}}
|
||||
id="Category"
|
||||
>
|
||||
Category
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="Category"
|
||||
input={<OutlinedInput label="Category" />}
|
||||
value={selectedCategoryVideos?.id || ""}
|
||||
onChange={handleOptionCategoryChangeVideos}
|
||||
sx={{
|
||||
// Target the input field
|
||||
".MuiSelect-select": {
|
||||
fontSize: "16px", // Change font size for the selected value
|
||||
padding: "10px 5px 15px 15px;",
|
||||
},
|
||||
// Target the dropdown icon
|
||||
".MuiSelect-icon": {
|
||||
fontSize: "20px", // Adjust if needed
|
||||
},
|
||||
// Target the dropdown menu
|
||||
"& .MuiMenu-paper": {
|
||||
".MuiMenuItem-root": {
|
||||
fontSize: "14px", // Change font size for the menu items
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{categories.map(option => (
|
||||
<MenuItem key={option.id} value={option.id}>
|
||||
{option.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
{selectedCategoryVideos &&
|
||||
subCategories[selectedCategoryVideos?.id] && (
|
||||
<FormControl fullWidth sx={{ marginBottom: 2 }}>
|
||||
<InputLabel
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
}}
|
||||
id="Sub-Category"
|
||||
>
|
||||
Sub-Category
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="Sub-Category"
|
||||
input={<OutlinedInput label="Sub-Category" />}
|
||||
value={selectedSubCategoryVideos?.id || ""}
|
||||
onChange={e =>
|
||||
handleOptionSubCategoryChangeVideos(
|
||||
e,
|
||||
subCategories[selectedCategoryVideos?.id]
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
// Target the input field
|
||||
".MuiSelect-select": {
|
||||
fontSize: "16px", // Change font size for the selected value
|
||||
padding: "10px 5px 15px 15px;",
|
||||
},
|
||||
// Target the dropdown icon
|
||||
".MuiSelect-icon": {
|
||||
fontSize: "20px", // Adjust if needed
|
||||
},
|
||||
// Target the dropdown menu
|
||||
"& .MuiMenu-paper": {
|
||||
".MuiMenuItem-root": {
|
||||
fontSize: "14px", // Change font size for the menu items
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{subCategories[selectedCategoryVideos.id].map(
|
||||
option => (
|
||||
<MenuItem key={option.id} value={option.id}>
|
||||
{option.name}
|
||||
</MenuItem>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
</Box>
|
||||
</FormControl>
|
||||
</FiltersSubContainer>
|
||||
<FiltersSubContainer>
|
||||
<FiltersRow>
|
||||
Videos
|
||||
<FiltersRadioButton
|
||||
checked={filterType === "videos"}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilterType("videos");
|
||||
}}
|
||||
inputProps={{ "aria-label": "controlled" }}
|
||||
/>
|
||||
</FiltersRow>
|
||||
<FiltersRow>
|
||||
Playlists
|
||||
<FiltersRadioButton
|
||||
checked={filterType === "playlists"}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilterType("playlists");
|
||||
}}
|
||||
inputProps={{ "aria-label": "controlled" }}
|
||||
/>
|
||||
</FiltersRow>
|
||||
</FiltersSubContainer>
|
||||
<Button
|
||||
onClick={() => {
|
||||
filtersToDefault();
|
||||
}}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
reset
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
getVideosHandler(true);
|
||||
}}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
Search
|
||||
</Button>
|
||||
</FiltersContainer>
|
||||
</FiltersCol>
|
||||
<Grid item xs={12} md={10} lg={7} xl={8} sm={9}>
|
||||
<ProductManagerRow>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
marginTop: "20px",
|
||||
}}
|
||||
>
|
||||
<SubtitleContainer
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
paddingLeft: "15px",
|
||||
width: "100%",
|
||||
maxWidth: "1400px",
|
||||
<Grid container sx={{ width: "100%" }}>
|
||||
<FiltersCol item xs={12} md={2} lg={2} xl={2} sm={3}>
|
||||
<FiltersContainer>
|
||||
<StatsCol
|
||||
sx={{ display: persistReducer.showStats ? "block" : "none" }}
|
||||
>
|
||||
<div>
|
||||
# of Videos:{" "}
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
{totalVideosPublished}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
Names Publishing:{" "}
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
{totalNamesPublished}
|
||||
</span>
|
||||
</div>
|
||||
<div>
|
||||
Videos per Name:{" "}
|
||||
<span style={{ fontWeight: "bold" }}>
|
||||
{videosPerNamePublished}
|
||||
</span>
|
||||
</div>
|
||||
</StatsCol>
|
||||
<Input
|
||||
id="standard-adornment-name"
|
||||
onChange={e => {
|
||||
setFilterSearch(e.target.value);
|
||||
}}
|
||||
></SubtitleContainer>
|
||||
<TabContext value={tabValue}>
|
||||
<TabList
|
||||
onChange={changeTab}
|
||||
textColor={"secondary"}
|
||||
indicatorColor={"secondary"}
|
||||
>
|
||||
<Tab
|
||||
label="All Videos"
|
||||
value={allTabValue}
|
||||
sx={{ fontSize: tabFontSize }}
|
||||
value={filterSearch}
|
||||
placeholder="Search"
|
||||
onKeyDown={handleInputKeyDown}
|
||||
sx={{
|
||||
borderBottom: "1px solid white",
|
||||
"&&:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:after": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:hover:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
fontSize: "18px",
|
||||
}}
|
||||
/>
|
||||
<Input
|
||||
id="standard-adornment-name"
|
||||
onChange={e => {
|
||||
setFilterName(e.target.value);
|
||||
}}
|
||||
value={filterName}
|
||||
placeholder="User's Name (Exact)"
|
||||
onKeyDown={handleInputKeyDown}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
borderBottom: "1px solid white",
|
||||
"&&:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:after": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&:hover:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused:before": {
|
||||
borderBottom: "none",
|
||||
},
|
||||
"&&.Mui-focused": {
|
||||
outline: "none",
|
||||
},
|
||||
fontSize: "18px",
|
||||
}}
|
||||
/>
|
||||
|
||||
<FiltersSubContainer>
|
||||
<FormControl sx={{ width: "100%", marginTop: "30px" }}>
|
||||
<Box
|
||||
sx={{
|
||||
display: "flex",
|
||||
gap: "20px",
|
||||
alignItems: "center",
|
||||
flexDirection: "column",
|
||||
}}
|
||||
>
|
||||
<FormControl fullWidth sx={{ marginBottom: 1 }}>
|
||||
<InputLabel
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
}}
|
||||
id="Category"
|
||||
>
|
||||
Category
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="Category"
|
||||
input={<OutlinedInput label="Category" />}
|
||||
value={selectedCategoryVideos?.id || ""}
|
||||
onChange={handleOptionCategoryChangeVideos}
|
||||
sx={{
|
||||
// Target the input field
|
||||
".MuiSelect-select": {
|
||||
fontSize: "16px", // Change font size for the selected value
|
||||
padding: "10px 5px 15px 15px;",
|
||||
},
|
||||
// Target the dropdown icon
|
||||
".MuiSelect-icon": {
|
||||
fontSize: "20px", // Adjust if needed
|
||||
},
|
||||
// Target the dropdown menu
|
||||
"& .MuiMenu-paper": {
|
||||
".MuiMenuItem-root": {
|
||||
fontSize: "14px", // Change font size for the menu items
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{categories.map(option => (
|
||||
<MenuItem key={option.id} value={option.id}>
|
||||
{option.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
{selectedCategoryVideos &&
|
||||
subCategories[selectedCategoryVideos?.id] && (
|
||||
<FormControl fullWidth sx={{ marginBottom: 2 }}>
|
||||
<InputLabel
|
||||
sx={{
|
||||
fontSize: "16px",
|
||||
}}
|
||||
id="Sub-Category"
|
||||
>
|
||||
Sub-Category
|
||||
</InputLabel>
|
||||
<Select
|
||||
labelId="Sub-Category"
|
||||
input={<OutlinedInput label="Sub-Category" />}
|
||||
value={selectedSubCategoryVideos?.id || ""}
|
||||
onChange={e =>
|
||||
handleOptionSubCategoryChangeVideos(
|
||||
e,
|
||||
subCategories[selectedCategoryVideos?.id]
|
||||
)
|
||||
}
|
||||
sx={{
|
||||
// Target the input field
|
||||
".MuiSelect-select": {
|
||||
fontSize: "16px", // Change font size for the selected value
|
||||
padding: "10px 5px 15px 15px;",
|
||||
},
|
||||
// Target the dropdown icon
|
||||
".MuiSelect-icon": {
|
||||
fontSize: "20px", // Adjust if needed
|
||||
},
|
||||
// Target the dropdown menu
|
||||
"& .MuiMenu-paper": {
|
||||
".MuiMenuItem-root": {
|
||||
fontSize: "14px", // Change font size for the menu items
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{subCategories[selectedCategoryVideos.id].map(
|
||||
option => (
|
||||
<MenuItem key={option.id} value={option.id}>
|
||||
{option.name}
|
||||
</MenuItem>
|
||||
)
|
||||
)}
|
||||
</Select>
|
||||
</FormControl>
|
||||
)}
|
||||
</Box>
|
||||
</FormControl>
|
||||
</FiltersSubContainer>
|
||||
<FiltersSubContainer>
|
||||
<FiltersRow>
|
||||
Videos
|
||||
<FiltersRadioButton
|
||||
checked={filterType === "videos"}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilterType("videos");
|
||||
}}
|
||||
inputProps={{ "aria-label": "controlled" }}
|
||||
/>
|
||||
<Tab
|
||||
label="Subscriptions"
|
||||
value={subscriptionTabValue}
|
||||
sx={{ fontSize: tabFontSize }}
|
||||
</FiltersRow>
|
||||
<FiltersRow>
|
||||
Playlists
|
||||
<FiltersRadioButton
|
||||
checked={filterType === "playlists"}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setFilterType("playlists");
|
||||
}}
|
||||
inputProps={{ "aria-label": "controlled" }}
|
||||
/>
|
||||
</TabList>
|
||||
<TabPanel value={allTabValue} sx={{ width: "100%" }}>
|
||||
<VideoList videos={videos} />
|
||||
<LazyLoad
|
||||
onLoadMore={getVideosHandler}
|
||||
isLoading={isLoading}
|
||||
></LazyLoad>
|
||||
</TabPanel>
|
||||
<TabPanel value={subscriptionTabValue} sx={{ width: "100%" }}>
|
||||
{persistSelector.subscriptionList.length > 0 ? (
|
||||
<>
|
||||
<VideoList videos={videos} />
|
||||
<LazyLoad
|
||||
onLoadMore={getVideosHandler}
|
||||
isLoading={isLoading}
|
||||
></LazyLoad>
|
||||
</>
|
||||
) : (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
You have no subscriptions
|
||||
</div>
|
||||
)}
|
||||
</TabPanel>
|
||||
</TabContext>
|
||||
</Box>
|
||||
</ProductManagerRow>
|
||||
</FiltersRow>
|
||||
</FiltersSubContainer>
|
||||
<Button
|
||||
onClick={() => {
|
||||
filtersToDefault();
|
||||
}}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
reset
|
||||
</Button>
|
||||
<Button
|
||||
onClick={() => {
|
||||
getVideosHandler(true);
|
||||
}}
|
||||
sx={{
|
||||
marginTop: "20px",
|
||||
}}
|
||||
variant="contained"
|
||||
>
|
||||
Search
|
||||
</Button>
|
||||
</FiltersContainer>
|
||||
</FiltersCol>
|
||||
<Grid item xs={12} md={10} lg={7} xl={8} sm={9}>
|
||||
<ProductManagerRow>
|
||||
<Box
|
||||
sx={{
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
marginTop: "20px",
|
||||
}}
|
||||
>
|
||||
<SubtitleContainer
|
||||
sx={{
|
||||
justifyContent: "flex-start",
|
||||
paddingLeft: "15px",
|
||||
width: "100%",
|
||||
maxWidth: "1400px",
|
||||
}}
|
||||
></SubtitleContainer>
|
||||
<TabContext value={tabValue}>
|
||||
<TabList
|
||||
onChange={changeTab}
|
||||
textColor={"secondary"}
|
||||
indicatorColor={"secondary"}
|
||||
>
|
||||
<Tab
|
||||
label="All Videos"
|
||||
value={allTabValue}
|
||||
sx={{ fontSize: tabFontSize }}
|
||||
/>
|
||||
<Tab
|
||||
label="Subscriptions"
|
||||
value={subscriptionTabValue}
|
||||
sx={{ fontSize: tabFontSize }}
|
||||
/>
|
||||
</TabList>
|
||||
<TabPanel value={allTabValue} sx={{ width: "100%" }}>
|
||||
<VideoList videos={videos} />
|
||||
<LazyLoad
|
||||
onLoadMore={getVideosHandler}
|
||||
isLoading={isLoading}
|
||||
></LazyLoad>
|
||||
</TabPanel>
|
||||
<TabPanel value={subscriptionTabValue} sx={{ width: "100%" }}>
|
||||
{filteredSubscriptionList.length > 0 ? (
|
||||
<>
|
||||
<VideoList videos={videos} />
|
||||
<LazyLoad
|
||||
onLoadMore={getVideosHandler}
|
||||
isLoading={isLoading}
|
||||
></LazyLoad>
|
||||
</>
|
||||
) : (
|
||||
<div style={{ textAlign: "center" }}>
|
||||
You have no subscriptions
|
||||
</div>
|
||||
)}
|
||||
</TabPanel>
|
||||
</TabContext>
|
||||
</Box>
|
||||
</ProductManagerRow>
|
||||
</Grid>
|
||||
<FiltersCol item xs={0} lg={3} xl={2}>
|
||||
<ListSuperLikeContainer />
|
||||
</FiltersCol>
|
||||
</Grid>
|
||||
<FiltersCol item xs={0} lg={3} xl={2}>
|
||||
<ListSuperLikeContainer />
|
||||
</FiltersCol>
|
||||
</Grid>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
@ -237,6 +237,16 @@ export const FiltersCol = styled(Grid)(({ theme }) => ({
|
||||
borderRight: `1px solid ${theme.palette.background.paper}`,
|
||||
}));
|
||||
|
||||
export const StatsCol = styled(Grid)(({ theme }) => ({
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
width: "100%",
|
||||
padding: "20px 15px",
|
||||
backgroundColor: theme.palette.background.default,
|
||||
borderTop: `1px solid ${theme.palette.background.paper}`,
|
||||
borderRight: `1px solid ${theme.palette.background.paper}`,
|
||||
}));
|
||||
|
||||
export const FiltersContainer = styled(Box)(({ theme }) => ({
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
|
@ -1,65 +1,74 @@
|
||||
import React, { useMemo } from 'react'
|
||||
import { VideoListComponentLevel } from '../Home/VideoListComponentLevel'
|
||||
import { HeaderContainer, ProfileContainer } from './Profile-styles'
|
||||
import { AuthorTextComment, StyledCardColComment, StyledCardHeaderComment } from '../VideoContent/VideoContent-styles'
|
||||
import { Avatar, Box, useTheme } from '@mui/material'
|
||||
import { useParams } from 'react-router-dom'
|
||||
import { useSelector } from 'react-redux'
|
||||
import { setUserAvatarHash } from '../../state/features/globalSlice'
|
||||
import { RootState } from '../../state/store'
|
||||
import React, { useMemo } from "react";
|
||||
import { VideoListComponentLevel } from "../Home/VideoListComponentLevel";
|
||||
import { HeaderContainer, ProfileContainer } from "./Profile-styles";
|
||||
import {
|
||||
AuthorTextComment,
|
||||
StyledCardColComment,
|
||||
StyledCardHeaderComment,
|
||||
} from "../VideoContent/VideoContent-styles";
|
||||
import { Avatar, Box, useTheme } from "@mui/material";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { useSelector } from "react-redux";
|
||||
import { setUserAvatarHash } from "../../state/features/globalSlice";
|
||||
import { RootState } from "../../state/store";
|
||||
import { SubscribeButton } from "../../components/common/SubscribeButton.tsx";
|
||||
|
||||
export const IndividualProfile = () => {
|
||||
const { name: paramName } = useParams()
|
||||
const { name: paramName } = useParams();
|
||||
|
||||
const userAvatarHash = useSelector(
|
||||
(state: RootState) => state.global.userAvatarHash
|
||||
)
|
||||
const theme = useTheme()
|
||||
);
|
||||
const theme = useTheme();
|
||||
|
||||
|
||||
|
||||
const avatarUrl = useMemo(()=> {
|
||||
let url = ''
|
||||
if(paramName && userAvatarHash[paramName]){
|
||||
url = userAvatarHash[paramName]
|
||||
const avatarUrl = useMemo(() => {
|
||||
let url = "";
|
||||
if (paramName && userAvatarHash[paramName]) {
|
||||
url = userAvatarHash[paramName];
|
||||
}
|
||||
|
||||
return url
|
||||
}, [userAvatarHash, paramName])
|
||||
return url;
|
||||
}, [userAvatarHash, paramName]);
|
||||
return (
|
||||
<ProfileContainer>
|
||||
<HeaderContainer>
|
||||
<Box sx={{
|
||||
cursor: 'pointer'
|
||||
}} >
|
||||
<Box
|
||||
sx={{
|
||||
cursor: "pointer",
|
||||
}}
|
||||
>
|
||||
<StyledCardHeaderComment
|
||||
sx={{
|
||||
'& .MuiCardHeader-content': {
|
||||
overflow: 'hidden'
|
||||
}
|
||||
"& .MuiCardHeader-content": {
|
||||
overflow: "hidden",
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Box>
|
||||
<Avatar src={`/arbitrary/THUMBNAIL/${paramName}/qortal_avatar`} alt={`${paramName}'s avatar`} />
|
||||
<Avatar
|
||||
src={`/arbitrary/THUMBNAIL/${paramName}/qortal_avatar`}
|
||||
alt={`${paramName}'s avatar`}
|
||||
/>
|
||||
</Box>
|
||||
<StyledCardColComment>
|
||||
<AuthorTextComment
|
||||
color={
|
||||
theme.palette.mode === 'light'
|
||||
theme.palette.mode === "light"
|
||||
? theme.palette.text.secondary
|
||||
: '#d6e8ff'
|
||||
: "#d6e8ff"
|
||||
}
|
||||
>
|
||||
{paramName}
|
||||
</AuthorTextComment>
|
||||
</StyledCardColComment>
|
||||
<SubscribeButton name={paramName} sx={{marginLeft:'10px'}}/>
|
||||
<SubscribeButton
|
||||
subscriberName={paramName}
|
||||
sx={{ marginLeft: "10px" }}
|
||||
/>
|
||||
</StyledCardHeaderComment>
|
||||
</Box>
|
||||
</HeaderContainer>
|
||||
<VideoListComponentLevel />
|
||||
</ProfileContainer>
|
||||
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
@ -497,7 +497,7 @@ export const PlaylistContent = () => {
|
||||
>
|
||||
{name}
|
||||
<SubscribeButton
|
||||
name={name}
|
||||
subscriberName={name}
|
||||
sx={{ marginLeft: "20px" }}
|
||||
/>
|
||||
</AuthorTextComment>
|
||||
|
@ -437,7 +437,10 @@ export const VideoContent = () => {
|
||||
}}
|
||||
>
|
||||
{name}
|
||||
<SubscribeButton name={name} sx={{ marginLeft: "20px" }} />
|
||||
<SubscribeButton
|
||||
subscriberName={name}
|
||||
sx={{ marginLeft: "20px" }}
|
||||
/>
|
||||
</AuthorTextComment>
|
||||
</StyledCardColComment>
|
||||
</StyledCardHeaderComment>
|
||||
|
@ -2,12 +2,21 @@ import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { subscriptionTabValue } from "../../constants/Misc.ts";
|
||||
|
||||
type StretchVideoType = "contain" | "fill" | "cover" | "none" | "scale-down";
|
||||
type SubscriptionListFilterType = "ALL" | "currentNameOnly";
|
||||
|
||||
export type SubscriptionObject = {
|
||||
userName: string;
|
||||
subscriberName: string;
|
||||
};
|
||||
|
||||
interface settingsState {
|
||||
selectedTab: string;
|
||||
stretchVideoSetting: StretchVideoType;
|
||||
filterType: string;
|
||||
subscriptionList: string[];
|
||||
subscriptionList: SubscriptionObject[];
|
||||
playbackRate: number;
|
||||
subscriptionListFilter: SubscriptionListFilterType;
|
||||
showStats: boolean;
|
||||
}
|
||||
|
||||
const initialState: settingsState = {
|
||||
@ -16,6 +25,8 @@ const initialState: settingsState = {
|
||||
filterType: "videos",
|
||||
subscriptionList: [],
|
||||
playbackRate: 1,
|
||||
subscriptionListFilter: "currentNameOnly",
|
||||
showStats: true,
|
||||
};
|
||||
|
||||
export const persistSlice = createSlice({
|
||||
@ -28,16 +39,28 @@ export const persistSlice = createSlice({
|
||||
setStretchVideoSetting: (state, action) => {
|
||||
state.stretchVideoSetting = action.payload;
|
||||
},
|
||||
subscribe: (state, action: PayloadAction<string>) => {
|
||||
setShowStats: (state, action) => {
|
||||
state.showStats = action.payload;
|
||||
},
|
||||
subscribe: (state, action: PayloadAction<SubscriptionObject>) => {
|
||||
const currentSubscriptions = state.subscriptionList;
|
||||
if (!currentSubscriptions.includes(action.payload)) {
|
||||
const notSubscribedToName =
|
||||
currentSubscriptions.find(item => {
|
||||
return item.subscriberName === action.payload.subscriberName;
|
||||
}) === undefined;
|
||||
if (notSubscribedToName) {
|
||||
state.subscriptionList = [...currentSubscriptions, action.payload];
|
||||
}
|
||||
console.log("subscribeList after subscribe: ", state.subscriptionList);
|
||||
},
|
||||
unSubscribe: (state, action) => {
|
||||
unSubscribe: (state, action: PayloadAction<SubscriptionObject>) => {
|
||||
state.subscriptionList = state.subscriptionList.filter(
|
||||
item => item !== action.payload
|
||||
item => item.subscriberName !== action.payload.subscriberName
|
||||
);
|
||||
console.log("subscribeList after unsubscribe: ", state.subscriptionList);
|
||||
},
|
||||
resetSubscriptions: state => {
|
||||
state.subscriptionList = [];
|
||||
},
|
||||
setReduxPlaybackRate: (state, action) => {
|
||||
state.playbackRate = action.payload;
|
||||
@ -54,6 +77,7 @@ export const {
|
||||
unSubscribe,
|
||||
setReduxPlaybackRate,
|
||||
changeFilterType,
|
||||
resetSubscriptions,
|
||||
} = persistSlice.actions;
|
||||
|
||||
export default persistSlice.reducer;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { SubscriptionObject } from "./persistSlice.ts";
|
||||
|
||||
interface GlobalState {
|
||||
videos: Video[];
|
||||
@ -14,6 +15,7 @@ interface GlobalState {
|
||||
selectedSubCategoryVideos: any;
|
||||
editVideoProperties: any;
|
||||
editPlaylistProperties: any;
|
||||
filteredSubscriptionList: SubscriptionObject[];
|
||||
}
|
||||
|
||||
const initialState: GlobalState = {
|
||||
@ -30,6 +32,7 @@ const initialState: GlobalState = {
|
||||
selectedSubCategoryVideos: null,
|
||||
editVideoProperties: null,
|
||||
editPlaylistProperties: null,
|
||||
filteredSubscriptionList: [],
|
||||
};
|
||||
|
||||
export interface Video {
|
||||
@ -168,6 +171,13 @@ export const videoSlice = createSlice({
|
||||
|
||||
state.videos = state.videos.filter(item => item.user !== username);
|
||||
},
|
||||
|
||||
setFilteredSubscriptions: (
|
||||
state,
|
||||
action: PayloadAction<SubscriptionObject[]>
|
||||
) => {
|
||||
state.filteredSubscriptionList = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@ -196,6 +206,7 @@ export const {
|
||||
setEditVideo,
|
||||
setEditPlaylist,
|
||||
addtoHashMapSuperlikes,
|
||||
setFilteredSubscriptions,
|
||||
} = videoSlice.actions;
|
||||
|
||||
export default videoSlice.reducer;
|
||||
|
@ -3,7 +3,7 @@ import notificationsReducer from "./features/notificationsSlice";
|
||||
import authReducer from "./features/authSlice";
|
||||
import globalReducer from "./features/globalSlice";
|
||||
import videoReducer from "./features/videoSlice";
|
||||
import settingsReducer from "./features/persistSlice.ts";
|
||||
import persistDataReducer from "./features/persistSlice.ts";
|
||||
import {
|
||||
persistReducer,
|
||||
FLUSH,
|
||||
@ -26,7 +26,7 @@ const reducer = combineReducers({
|
||||
auth: authReducer,
|
||||
global: globalReducer,
|
||||
video: videoReducer,
|
||||
persist: persistReducer(persistSettingsConfig, settingsReducer),
|
||||
persist: persistReducer(persistSettingsConfig, persistDataReducer),
|
||||
});
|
||||
|
||||
export const store = configureStore({
|
||||
|
Loading…
x
Reference in New Issue
Block a user