Browse Source

Merge pull request #18 from QortalSeth/main

Final updates to new Q-Tube 2.0 release
pull/19/head^2
Qortal Dev 7 months ago committed by GitHub
parent
commit
0fc8fb5c5c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      package.json
  2. 48
      src/App.tsx
  3. 29
      src/components/PublishVideo/PublishVideo-styles.tsx
  4. 27
      src/components/PublishVideo/PublishVideo.tsx
  5. 44
      src/components/common/SubscribeButton.tsx
  6. 32
      src/hooks/useFetchVideos.tsx
  7. 18
      src/main.tsx
  8. 73
      src/pages/Home/Home.tsx
  9. 10
      src/pages/Home/VideoList-styles.tsx
  10. 75
      src/pages/IndividualProfile/IndividualProfile.tsx
  11. 2
      src/pages/PlaylistContent/PlaylistContent.tsx
  12. 5
      src/pages/VideoContent/VideoContent.tsx
  13. 34
      src/state/features/persistSlice.ts
  14. 11
      src/state/features/videoSlice.ts
  15. 4
      src/state/store.ts

2
package.json

@ -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

@ -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}>

29
src/components/PublishVideo/PublishVideo-styles.tsx

@ -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",

27
src/components/PublishVideo/PublishVideo.tsx

@ -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

44
src/components/common/SubscribeButton.tsx

@ -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);
};

32
src/hooks/useFetchVideos.tsx

@ -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

@ -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>
)
);

73
src/pages/Home/Home.tsx

@ -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,22 +293,31 @@ 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>
<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 => {
@ -538,7 +567,7 @@ export const Home = ({ mode }: HomeProps) => {
></LazyLoad>
</TabPanel>
<TabPanel value={subscriptionTabValue} sx={{ width: "100%" }}>
{persistSelector.subscriptionList.length > 0 ? (
{filteredSubscriptionList.length > 0 ? (
<>
<VideoList videos={videos} />
<LazyLoad

10
src/pages/Home/VideoList-styles.tsx

@ -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",

75
src/pages/IndividualProfile/IndividualProfile.tsx

@ -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>
)
}
);
};

2
src/pages/PlaylistContent/PlaylistContent.tsx

@ -497,7 +497,7 @@ export const PlaylistContent = () => {
>
{name}
<SubscribeButton
name={name}
subscriberName={name}
sx={{ marginLeft: "20px" }}
/>
</AuthorTextComment>

5
src/pages/VideoContent/VideoContent.tsx

@ -437,7 +437,10 @@ export const VideoContent = () => {
}}
>
{name}
<SubscribeButton name={name} sx={{ marginLeft: "20px" }} />
<SubscribeButton
subscriberName={name}
sx={{ marginLeft: "20px" }}
/>
</AuthorTextComment>
</StyledCardColComment>
</StyledCardHeaderComment>

34
src/state/features/persistSlice.ts

@ -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;

11
src/state/features/videoSlice.ts

@ -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;

4
src/state/store.ts

@ -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…
Cancel
Save