Skip to content

Commit

Permalink
sob
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlan404 committed May 29, 2024
1 parent 7acb4e4 commit 86f35ef
Show file tree
Hide file tree
Showing 12 changed files with 198 additions and 13 deletions.
41 changes: 37 additions & 4 deletions src/components/cards/CommentCard.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,51 @@
import { ActionIcon, Box, Button, CopyButton, Grid, Group, Paper, Stack, Tooltip } from "@mantine/core";
import { ActionIcon, Box, Button, Collapse, CopyButton, Grid, Group, Loader, Paper, Stack, Tooltip } from "@mantine/core";
import { Comment } from "../../api/types/comment";
import { MarkdownText } from "../ui/MarkdownText";
import { ChannelCard } from "./ChannelCard";
import { VotingCard } from "./VotingCard";
import { IconArrowDown, IconCopy, IconPencil, IconPinned, IconTableImport, IconTableOff } from "@tabler/icons-react";
import { IconArrowDown, IconArrowUp, IconCopy, IconPencil, IconPinned, IconTableImport, IconTableOff } from "@tabler/icons-react";
import { parseChapters } from "../../utils/parseChapters";
import { useContext } from "react";
import { useContext, useState } from "react";
import { VideoPlayerContext } from "../../api/player/VideoPlayerContext";
import { parseFormattedText, textPartsToString } from "../../utils/parseFormattedText";
import { DateCard } from "./DateCard";
import { TimestampRegex } from "../../utils/timestamp";
import { useDisclosure } from "@mantine/hooks";
import { APIContext } from "../../api/provider/APIController";

export const CommentCard = ({
comment
}: {
comment: Comment,
}) => {
const { api } = useContext(APIContext);
const { activeChapters, setActiveChapters } = useContext(VideoPlayerContext);
const [opened, { toggle }] = useDisclosure(false);
const [isLoading, setLoading] = useState(true);
const [error, setError] = useState();
const [replies, setReplies] = useState<Comment[]>([]);

const onExpand = async () => {
toggle();

// dont fetch when closing
if(opened) return;

// dont fetch if fetched
if(replies.length) return;

setLoading(true);
setError(null);
setReplies([]);

try {

} catch(e) {
setError(e);
} finally {
setLoading(false);
}
};

const hasChapters = comment.content.match(TimestampRegex)?.length > 1;
const isChaptersSource = activeChapters.type == "comment" && activeChapters.id == comment.id;
Expand Down Expand Up @@ -62,7 +91,8 @@ export const CommentCard = ({
<Button
variant="subtle"
size="compact-md"
leftSection={<IconArrowDown />}
leftSection={opened ? <IconArrowUp /> : <IconArrowDown />}
onClick={onExpand}
>
{comment.replyCount} replies
</Button>
Expand Down Expand Up @@ -103,6 +133,9 @@ export const CommentCard = ({
</CopyButton>
</Group>
</Group>
<Collapse in={opened}>
{isLoading && <Loader />}
</Collapse>
</Stack>
</Paper>
);
Expand Down
16 changes: 16 additions & 0 deletions src/components/options/comps/Flavor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { useContext } from "react";
import { TabsContext } from "../../tabs/TabsContext";
import { SegmentedControl } from "@mantine/core";
import { UIFlavor } from "../../tabs/TabTypes";

export const FlavorOption = () => {
const { flavor, setFlavor } = useContext(TabsContext);

return (
<SegmentedControl
value={flavor}
data={["video", "music"] as UIFlavor[]}
onChange={(v) => setFlavor(v as UIFlavor)}
/>
)
};
2 changes: 2 additions & 0 deletions src/components/options/views/MainView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { DebuggingSection } from "../comps/DebuggingSection";
import { OpenWithButton } from "../links/OpenWithButton";
import { LoopVideo } from "../comps/LoopVideo";
import { ThemeSection } from "../comps/ThemeSection";
import { FlavorOption } from "../comps/Flavor";

export const OptionsMainView = () => {
const { videoInfo } = useContext(VideoPlayerContext);
Expand All @@ -31,6 +32,7 @@ export const OptionsMainView = () => {
{loaded && <LoopVideo />}
<Divider w="100%" label="Preferences" labelPosition="left" />
<PreferencesList />
<FlavorOption />
<Divider w="100%" label="Theme" labelPosition="left" />
<ThemeSection />
<Divider w="100%" label="Debugging" labelPosition="left" />
Expand Down
28 changes: 28 additions & 0 deletions src/components/player/controls/LoopButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { ActionIcon, Tooltip } from "@mantine/core";
import { useFullscreen } from "@mantine/hooks";
import { IconMaximize, IconMinimize, IconRepeat, IconRepeatOff } from "@tabler/icons-react";
import { useContext, useState } from "react";
import { VideoPlayerContext } from "../../../api/player/VideoPlayerContext";

export const LoopButton = () => {
const { videoElement } = useContext(VideoPlayerContext);
const [loop, setLoop] = useState(videoElement.loop);

return (
<Tooltip label={loop ? "Turn off loop" : "Click to turn on loop"}>
<ActionIcon
onClick={() => {
videoElement.loop = !videoElement.loop;
setLoop(!videoElement.loop);
}}
variant="light"
>
{loop ? (
<IconRepeatOff />
) : (
<IconRepeat />
)}
</ActionIcon>
</Tooltip>
);
};
4 changes: 2 additions & 2 deletions src/components/player/layout/LayoutTop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ export const PlayerLayoutTop = () => {
p="xs"
onClick={(e) => e.stopPropagation()}
>
<Grid align="center">
<Grid.Col span="content">
<Grid align="center" gutter={0}>
<Grid.Col span="content" pr={(playState == "loading" || playState == "error") ? "md" : 0}>
{playState == "loading" && (
<Loader size="sm" />
)}
Expand Down
28 changes: 28 additions & 0 deletions src/components/player/music/MusicControls.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Group, Paper, Stack } from "@mantine/core"
import { PlayPauseButton } from "../controls/PlayPauseButton"
import { VolumeControls } from "../controls/VolumeControls"
import { PlayerTimestamp } from "../controls/PlayerTimestamp"
import { ProgressBar } from "../bar/ProgressBar"
import { LoopButton } from "../controls/LoopButton"
import { PlayerLayoutTop } from "../layout/LayoutTop"

export const MusicControls = () => {
return (
<Paper withBorder p="sm" bg="dark">
<Stack>
<PlayerLayoutTop />
<ProgressBar />
<Group justify="space-between">
<Group>
<PlayPauseButton />
<VolumeControls />
<PlayerTimestamp />
</Group>
<Group>
<LoopButton />
</Group>
</Group>
</Stack>
</Paper>
)
}
62 changes: 62 additions & 0 deletions src/components/player/music/MusicPlayer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { useContext, useEffect, useRef, useState } from "react";
import { VideoPlayerContext } from "../../../api/player/VideoPlayerContext"
import { Box, Stack, Transition } from "@mantine/core";
import { useDebouncedCallback, useHotkeys, useHover, useMergedRef } from "@mantine/hooks";
import { usePreference } from "../../../api/pref/Preferences";
import { MusicControls } from "./MusicControls";
import { useIsMobile } from "../../../hooks/useIsMobile";

export const MusicPlayer = () => {
const {
videoElement,
seekToChapterOffset,
seekTo,
togglePlay,
playState,
muted,
setMuted,
autoplayDate,
} = useContext(VideoPlayerContext);
const videoContainerRef = useRef<HTMLDivElement>(null);

useEffect(() => {
videoContainerRef.current?.appendChild(videoElement);
if(videoElement.paused && videoElement.currentSrc && videoElement.currentTime)
videoElement.play();
return () => {
videoElement.pause();
};
}, [videoElement, videoContainerRef.current]);

useHotkeys([
["ArrowLeft", () => seekTo(videoElement.currentTime - 5)],
["ArrowRight", () => seekTo(videoElement.currentTime + 5)],
["Shift + ArrowRight", () => seekToChapterOffset(1)],
["Shift + ArrowLeft", () => seekToChapterOffset(-1)],
["J", () => seekTo(videoElement.currentTime - 10)],
["L", () => seekTo(videoElement.currentTime + 10)],
["K", () => togglePlay()],
["Space", () => togglePlay()],
["m", () => setMuted(!muted)],
["0", () => seekTo(0)],
]);
return (
<Box
w="100%"
h="100%"
style={{ position: "relative" }}
>
<Box
bg="dark.9"
style={{
position: "absolute",
height: "0%",
width: "0%",
zIndex: "-100",
}}
ref={videoContainerRef}
/>
<MusicControls />
</Box>
);
};
2 changes: 1 addition & 1 deletion src/hooks/useIsMobile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const useIsMobile = () => {
export const MobileContext = createContext(false);
export const MobileProvider = ({ children }: React.PropsWithChildren) => {
const { breakpoints } = useMantineTheme();
let value = useMediaQuery(`(min-width: ${breakpoints.sm})`, true);
let value = !useMediaQuery(`(min-width: ${breakpoints.sm})`, true);

return (
<MobileContext.Provider
Expand Down
4 changes: 2 additions & 2 deletions src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
}

.progressbar-inner {
background-color: var(--mantine-color-violet-filled);
background-color: var(--mantine-primary-color-filled);
}

.progressbar-buffer {
background-color: var(--mantine-color-blue-light);
background-color: var(--mantine-primary-color-light);
opacity: 0.7;
}

Expand Down
8 changes: 4 additions & 4 deletions src/site/NekoTubeRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ const ContextStack = () => {
<APIControllerProvider>
<PreferencesProvider>
<VideoPlayerProvider>
<OptionsProvider>
<TabsProvider>
<TabsProvider>
<OptionsProvider>
<Root />
</TabsProvider>
</OptionsProvider>
</OptionsProvider>
</TabsProvider>
</VideoPlayerProvider>
</PreferencesProvider>
</APIControllerProvider>
Expand Down
14 changes: 14 additions & 0 deletions src/site/layouts/LayoutDesktopMusic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { Box, Stack } from "@mantine/core";
import { MusicPlayer } from "../../components/player/music/MusicPlayer";
import { TabsRenderer } from "../../components/tabs/TabsRenderer";

export const LayoutDesktopMusic = () => {
return (
<Stack gap={0} h="calc(100vh - var(--app-shell-header-height))" style={{ overflow: "clip" }}>
<Box p="sm">
<MusicPlayer />
</Box>
<TabsRenderer isMobile />
</Stack>
)
};
2 changes: 2 additions & 0 deletions src/site/pages/WatchPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useIsMobile } from "../../hooks/useIsMobile";
import { LayoutDesktopVideo } from "../layouts/LayoutDesktopVideo";
import { LayoutMobileVideo } from "../layouts/LayoutMobileVideo";
import { UIFlavor } from "../../components/tabs/TabTypes";
import { LayoutDesktopMusic } from "../layouts/LayoutDesktopMusic";

export const WatchPage = () => {
const { flavor } = useContext(TabsContext);
Expand All @@ -20,6 +21,7 @@ export const WatchPage = () => {
({
"d:video": <LayoutDesktopVideo />,
"m:video": <LayoutMobileVideo />,
"d:music": <LayoutDesktopMusic />,
} as Record<`${"m" | "d"}:${UIFlavor}`, React.ReactNode>)[`${isMobile ? "m" : "d"}:${flavor}`]
);
};

0 comments on commit 86f35ef

Please sign in to comment.