Removed all top level imports (bundle size), added search to appbar

main
Guus van Meerveld 2 years ago
parent 03f5688f90
commit c6ecdb7819
Signed by: Guusvanmeerveld
GPG Key ID: 2BA7D7912771966E

@ -1,10 +1,15 @@
import { FC } from "react"; import { FC } from "react";
import Box from "@mui/material/Box";
import Navbar from "@components/Navbar"; import Navbar from "@components/Navbar";
const Layout: FC = ({ children }) => ( const Layout: FC = ({ children }) => (
<> <>
<Navbar /> <Navbar />
<Box
sx={{ height: { sm: 64, xs: 56 }, display: "block", width: "100%" }}
></Box>
{children} {children}
</> </>
); );

@ -13,23 +13,24 @@ import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText"; import ListItemText from "@mui/material/ListItemText";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { Settings } from "@mui/icons-material"; import Settings from "@mui/icons-material/Settings";
const MuiDrawer: FC<{ const AppDrawer: FC<{
drawerIsOpen: boolean; drawerIsOpen: boolean;
toggleDrawer: ( toggleDrawer: (
isOpen: boolean isOpen: boolean
) => (event: React.KeyboardEvent | React.MouseEvent) => void; ) => (event: React.KeyboardEvent | React.MouseEvent) => void;
width: number;
pages: { pages: {
name: string; name: string;
icon: JSX.Element; icon: JSX.Element;
link: string; link: string;
}[]; }[];
}> = ({ drawerIsOpen, toggleDrawer, pages }) => { }> = ({ drawerIsOpen, toggleDrawer, pages, width }) => {
return ( return (
<Drawer anchor="left" open={drawerIsOpen} onClose={toggleDrawer(false)}> <Drawer anchor="left" open={drawerIsOpen} onClose={toggleDrawer(false)}>
<Box <Box
sx={{ width: 250 }} sx={{ width }}
role="presentation" role="presentation"
onClick={toggleDrawer(false)} onClick={toggleDrawer(false)}
onKeyDown={toggleDrawer(false)} onKeyDown={toggleDrawer(false)}
@ -62,4 +63,4 @@ const MuiDrawer: FC<{
); );
}; };
export default MuiDrawer; export default AppDrawer;

@ -0,0 +1,43 @@
import InputBase from "@mui/material/InputBase";
import { alpha, styled } from "@mui/material/styles";
const Search = styled("div")(({ theme }) => ({
position: "relative",
borderRadius: theme.shape.borderRadius,
backgroundColor: alpha(theme.palette.common.white, 0.15),
"&:hover": {
backgroundColor: alpha(theme.palette.common.white, 0.25)
},
marginRight: theme.spacing(2),
marginLeft: 0,
width: "100%",
[theme.breakpoints.up("sm")]: {
marginLeft: theme.spacing(3),
width: "auto"
}
}));
export const SearchIconWrapper = styled("div")(({ theme }) => ({
padding: theme.spacing(0, 2),
height: "100%",
position: "absolute",
pointerEvents: "none",
display: "flex",
alignItems: "center",
justifyContent: "center"
}));
export const StyledInputBase = styled(InputBase)(({ theme }) => ({
color: "inherit",
"& .MuiInputBase-input": {
padding: theme.spacing(1, 1, 1, 0),
paddingLeft: `calc(1em + ${theme.spacing(4)})`,
transition: theme.transitions.create("width"),
width: "100%",
[theme.breakpoints.up("md")]: {
width: "20ch"
}
}
}));
export default Search;

@ -1,6 +1,7 @@
import packageInfo from "../../../package.json"; import packageInfo from "../../../package.json";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router";
import { FC, useState } from "react"; import { FC, useState } from "react";
@ -11,20 +12,26 @@ import IconButton from "@mui/material/IconButton";
import Toolbar from "@mui/material/Toolbar"; import Toolbar from "@mui/material/Toolbar";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { import History from "@mui/icons-material/History";
History, import Menu from "@mui/icons-material/Menu";
Subscriptions, import PlayCircleOutline from "@mui/icons-material/PlayCircleOutline";
Menu, import PlaylistAddCheck from "@mui/icons-material/PlaylistAddCheck";
Whatshot, import SearchIcon from "@mui/icons-material/Search";
PlaylistAddCheck, import Settings from "@mui/icons-material/Settings";
Settings, import Subscriptions from "@mui/icons-material/Subscriptions";
PlayCircleOutline import Whatshot from "@mui/icons-material/Whatshot";
} from "@mui/icons-material";
import Drawer from "@components/Navbar/Drawer"; import Drawer from "@components/Navbar/Drawer";
import Search, {
SearchIconWrapper,
StyledInputBase
} from "@components/Navbar/Search";
export const drawerWidth = 240;
const Navbar: FC = () => { const Navbar: FC = () => {
const [drawerIsOpen, setDrawerState] = useState(false); const [drawerIsOpen, setDrawerState] = useState(false);
const router = useRouter();
const toggleDrawer = const toggleDrawer =
(open: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => { (open: boolean) => (event: React.KeyboardEvent | React.MouseEvent) => {
@ -61,12 +68,13 @@ const Navbar: FC = () => {
return ( return (
<> <>
<Drawer <Drawer
width={drawerWidth}
drawerIsOpen={drawerIsOpen} drawerIsOpen={drawerIsOpen}
toggleDrawer={toggleDrawer} toggleDrawer={toggleDrawer}
pages={pages} pages={pages}
/> />
<Box sx={{ flexGrow: 1 }}> <Box sx={{ flexGrow: 1 }}>
<AppBar position="static" enableColorOnDark> <AppBar position="fixed" enableColorOnDark>
<Toolbar> <Toolbar>
<IconButton <IconButton
size="large" size="large"
@ -74,10 +82,11 @@ const Navbar: FC = () => {
color="inherit" color="inherit"
aria-label="menu" aria-label="menu"
sx={{ mr: 2, display: { md: "none", xs: "flex" } }} sx={{ mr: 2, display: { md: "none", xs: "flex" } }}
onClick={toggleDrawer(true)} onClick={() => setDrawerState(!drawerIsOpen)}
> >
<Menu /> <Menu />
</IconButton> </IconButton>
<Typography <Typography
variant="h6" variant="h6"
component="div" component="div"
@ -86,14 +95,20 @@ const Navbar: FC = () => {
<PlayCircleOutline sx={{ mr: 1 }} /> <PlayCircleOutline sx={{ mr: 1 }} />
{packageInfo.displayName} {packageInfo.displayName}
</Typography> </Typography>
<Box sx={{ flexGrow: 1, display: { md: "flex", xs: "none" } }}>
<Box
sx={{
flexGrow: 1,
display: "flex",
alignItems: "center"
}}
>
{pages.map((page, i) => ( {pages.map((page, i) => (
<Link key={i} href={"/" + page.link} passHref> <Link key={i} href={"/" + page.link} passHref>
<Button <Button
sx={{ sx={{
my: 2,
color: "white", color: "white",
display: "flex", display: { lg: "flex", xs: "none" },
alignItems: "center" alignItems: "center"
}} }}
> >
@ -104,7 +119,21 @@ const Navbar: FC = () => {
</Button> </Button>
</Link> </Link>
))} ))}
<Search>
<SearchIconWrapper>
<SearchIcon />
</SearchIconWrapper>
<form action={`${router.basePath}/results`} method="get">
<StyledInputBase
name="search_query"
placeholder="Search…"
inputProps={{ "aria-label": "search" }}
/>
</form>
</Search>
</Box> </Box>
<Link href="/settings" passHref> <Link href="/settings" passHref>
<IconButton <IconButton
sx={{ display: { md: "flex", xs: "none" } }} sx={{ display: { md: "flex", xs: "none" } }}

@ -1,6 +1,6 @@
import { FC } from "react"; import { FC } from "react";
import { Grid } from "@mui/material"; import Grid from "@mui/material/Grid";
import { Video as VideoModel } from "@interfaces/video"; import { Video as VideoModel } from "@interfaces/video";

@ -1,3 +1,5 @@
import axios, { AxiosError } from "axios";
import Link from "next/link"; import Link from "next/link";
import { useRouter } from "next/router"; import { useRouter } from "next/router";
@ -11,14 +13,18 @@ import Card from "@mui/material/Card";
import CardActionArea from "@mui/material/CardActionArea"; import CardActionArea from "@mui/material/CardActionArea";
import CardContent from "@mui/material/CardContent"; import CardContent from "@mui/material/CardContent";
import CardMedia from "@mui/material/CardMedia"; import CardMedia from "@mui/material/CardMedia";
import CircularProgress from "@mui/material/CircularProgress";
import Tooltip from "@mui/material/Tooltip"; import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { abbreviateNumber } from "@src/utils"; import { abbreviateNumber } from "@src/utils";
import { Channel, Quality } from "@interfaces/channel";
import { Video as VideoModel } from "@interfaces/video"; import { Video as VideoModel } from "@interfaces/video";
interface Channel {
authorThumbnails: { url: string; width: number; height: number }[];
}
const Video: FC<VideoModel> = ({ const Video: FC<VideoModel> = ({
thumbnail, thumbnail,
title, title,
@ -27,6 +33,24 @@ const Video: FC<VideoModel> = ({
views, views,
published published
}) => { }) => {
const requestFields = ["authorThumbnails"];
const { isLoading, error, data } = useQuery<Channel, AxiosError<Error>>(
`channelData-${author.id}`,
() =>
axios
.get(`https://invidious.privacy.gd/api/v1/channels/${author.id}`, {
params: {
fields: requestFields.join(",")
}
})
.then((res) => res.data),
{
retry: 1,
retryDelay: 5000
}
);
const router = useRouter(); const router = useRouter();
return ( return (
@ -46,7 +70,18 @@ const Video: FC<VideoModel> = ({
</Tooltip> </Tooltip>
<Link passHref href={`/channel/${author.id}`}> <Link passHref href={`/channel/${author.id}`}>
<Box sx={{ display: "flex", alignItems: "center" }}> <Box sx={{ display: "flex", alignItems: "center" }}>
<Avatar sx={{ mr: 2 }} alt={author.name} /> {isLoading && <CircularProgress sx={{ mr: 2 }} />}
{data && (
<Avatar
sx={{ mr: 2 }}
alt={author.name}
src={
data.authorThumbnails.find(
(thumbnail) => thumbnail.width == 100
)?.url as string
}
/>
)}
<Typography color="text.secondary" variant="subtitle1"> <Typography color="text.secondary" variant="subtitle1">
{author.name} {author.name}
</Typography> </Typography>

@ -8,7 +8,7 @@ import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import { PlayCircleOutline } from "@mui/icons-material"; import PlayCircleOutline from "@mui/icons-material/PlayCircleOutline";
import Layout from "@components/Layout"; import Layout from "@components/Layout";

Loading…
Cancel
Save