Skip to content

Commit

Permalink
implement history
Browse files Browse the repository at this point in the history
  • Loading branch information
TheAlan404 committed Jun 7, 2024
1 parent a825a78 commit 019f28e
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 30 deletions.
26 changes: 20 additions & 6 deletions src/api/pref/History.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { useLocalStorage } from "@mantine/hooks";
import { usePreference } from "./Preferences";

export type HistoryItem = {
t: "v" | "s",
d: string,
};
export type PartialHistoryItem = ["v" | "s", string];
export type HistoryItem = ["v" | "s", string, number];

export const useNekoTubeHistory = () => {
const useLocalHistory = usePreference("useLocalHistory");
Expand All @@ -16,10 +14,26 @@ export const useNekoTubeHistory = () => {
return {
history: value,
setHistory: setValue,
add: (item: HistoryItem) => {
add: (partial: PartialHistoryItem) => {
if(!useLocalHistory) return;

setValue(v => [...v, item]);
let item = [...partial, Date.now()] as HistoryItem;

setValue(v => {
if(item[0] == "s") {
let contains = v.some(([t, d]) => t == "s" && d == item[1]);

if (contains)
return v.map(([t, d, ts]) => (t == "s" && d == item[1]) ? [t, d, Date.now()] : [t, d, ts]);
else
return [...v, item];
} else {
let last = v[v.length - 1];

if(last && last[0] == "v" && last[1] == item[1]) return v.map((item, idx, arr) => (idx == (arr.length - 1)) ? [item[0], item[1], Date.now()] : item);
return [...v, item];
}
});
},
clear: () => setValue([]),
};
Expand Down
42 changes: 41 additions & 1 deletion src/components/cards/VideoCard.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Grid, Group, Paper, Stack, Text, Title } from "@mantine/core";
import { Box, Grid, Group, Loader, Paper, Stack, Text, Title } from "@mantine/core";
import { ThumbnailRender } from "./ThumbnailRender";
import { VideoInfo } from "../../api/types/video";
import { Link } from "react-router-dom";
Expand All @@ -10,6 +10,46 @@ import { useContext, useEffect, useState } from "react";
import { usePreference } from "../../api/pref/Preferences";
import { APIContext } from "../../api/provider/APIController";

export const FetchVideoWrapper = ({
id,
component: Component,
}: {
id: string,
component: ({ video }: { video: VideoInfo }) => any,
}) => {
const { api } = useContext(APIContext);
const [video, setVideo] = useState<VideoInfo | null>(null);

useEffect(() => {
(async () => {
setVideo(await api.getVideoInfo(id));
})()
}, []);

return (
<Box>
{video ? (
<Component video={video} />
) : (
<Paper
withBorder
p="md"
>
<Group>
<Loader />
<Text>
Fetching video
</Text>
<Text fw="bold">
{id}
</Text>
</Group>
</Paper>
)}
</Box>
)
};

export const HorizontalVideoCard = ({
video: originalVideo,
}: {
Expand Down
7 changes: 6 additions & 1 deletion src/components/options/OptionsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Button, Drawer, Group, ScrollArea, Text } from "@mantine/core";
import { OptionsRouter } from "./OptionsRouter";
import { IconArrowLeft } from "@tabler/icons-react";

export type OptionsView = "main" | "instanceSelect" | "openWith" | "formatSelect";
export type OptionsView = "main" | "instanceSelect" | "openWith" | "formatSelect" | "history";

export interface OptionsContextAPI {
opened: boolean;
Expand Down Expand Up @@ -56,6 +56,10 @@ export const OptionsProvider = ({ children }: React.PropsWithChildren) => {

useHotkeys([
["Ctrl + o", () => toggle()],
["Ctrl + h", () => {
open();
setView("history");
}],
], [], true);

return (
Expand Down Expand Up @@ -101,6 +105,7 @@ export const OptionsProvider = ({ children }: React.PropsWithChildren) => {
formatSelect: "Select Format",
instanceSelect: "Select Instance",
openWith: "Open with...",
history: "History",
} as Record<OptionsView, string>)[view]}
</Text>
</Group>
Expand Down
2 changes: 2 additions & 0 deletions src/components/options/OptionsRouter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { OptionsMainView } from "./views/MainView";
import { OptionsInstanceView } from "./views/InstanceView";
import { OptionsOpenWithView } from "./views/OpenWith";
import { OptionsFormatView } from "./views/FormatView";
import { OptionsHistoryView } from "./views/HistoryView";

export const OptionsRouter = () => {
const { view } = useContext(OptionsContext);
Expand All @@ -15,6 +16,7 @@ export const OptionsRouter = () => {
{view == "instanceSelect" && <OptionsInstanceView />}
{view == "openWith" && <OptionsOpenWithView />}
{view == "formatSelect" && <OptionsFormatView />}
{view == "history" && <OptionsHistoryView />}
</Stack>
);
};
99 changes: 99 additions & 0 deletions src/components/options/views/HistoryView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import React, { useContext, useState } from "react";
import { VideoPlayerContext } from "../../../api/player/VideoPlayerContext";
import { ActionIcon, Button, Divider, Grid, Group, Paper, SegmentedControl, Space, Stack, Text, Tooltip } from "@mantine/core";
import { InstanceSelect } from "../comps/InstanceSelect";
import { FormatSelect } from "../comps/FormatSelect";
import { PlaybackSpeed } from "../comps/PlaybackSpeed";
import { PreferencesList } from "../comps/PreferencesList";
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";
import { HistoryItem, useNekoTubeHistory } from "../../../api/pref/History";
import { IconSearch, IconTrash } from "@tabler/icons-react";
import { FetchVideoWrapper, HorizontalVideoCard } from "../../cards/VideoCard";
import { DateCard } from "../../cards/DateCard";

export const OptionsHistoryView = () => {
const history = useNekoTubeHistory();
const [showTypes, setShowTypes] = useState<"*" | "s" | "v">("*");

return (
<Stack w="100%">
<Divider w="100%" label="Manage" labelPosition="left" />
<Group grow>
<Button
variant="light"
color="red"
leftSection={<IconTrash />}
onDoubleClick={() => history.clear()}
>
Clear All (double click)
</Button>
</Group>

<Divider w="100%" label="History" labelPosition="left" />

<Group justify="space-between">
<Text>
Filter by:
</Text>
<SegmentedControl
data={[
{ label: "All", value: "*" },
{ label: "Videos", value: "v" },
{ label: "Search", value: "s" },
]}
value={showTypes}
onChange={(v: "*" | "v" | "s") => setShowTypes(v)}
/>
</Group>

{history.history
.sort(([_, __, a], [___, ____, b]) => b-a)
.filter(([t]) => showTypes == "*" || t == showTypes)
.map(([type, data, ts], idx) => (
<Stack gap={0}>
{({
s: () => (
<Paper p="sm" withBorder key={idx}>
<Group align="center">
<IconSearch />
<Text>
{data}
</Text>
</Group>
</Paper>
),
v: () => (
<FetchVideoWrapper
id={data}
component={HorizontalVideoCard}
/>
),
} as Record<HistoryItem[0], () => React.ReactNode>)[type]()}
<Group justify="space-between">
<DateCard date={new Date(ts)} />
<Group>
<Tooltip label="Delete">
<ActionIcon
variant="light"
color="red"
onClick={() => {
history.setHistory(v => v
.filter(([a, b, c]) => !((a == type && b == data) && (ts == c))))
}}
>
<IconTrash />
</ActionIcon>
</Tooltip>
</Group>
</Group>
</Stack>
))}

<Space h="20vh" />
</Stack>
);
};
14 changes: 13 additions & 1 deletion src/components/options/views/MainView.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useContext, useState } from "react";
import { VideoPlayerContext } from "../../../api/player/VideoPlayerContext";
import { Divider, Grid, Space, Stack, Text } from "@mantine/core";
import { Button, Divider, Grid, Space, Stack, Text } from "@mantine/core";
import { InstanceSelect } from "../comps/InstanceSelect";
import { FormatSelect } from "../comps/FormatSelect";
import { PlaybackSpeed } from "../comps/PlaybackSpeed";
Expand All @@ -10,9 +10,12 @@ import { OpenWithButton } from "../links/OpenWithButton";
import { LoopVideo } from "../comps/LoopVideo";
import { ThemeSection } from "../comps/ThemeSection";
import { FlavorOption } from "../comps/Flavor";
import { OptionsContext } from "../OptionsContext";
import { IconClock } from "@tabler/icons-react";

export const OptionsMainView = () => {
const { videoInfo } = useContext(VideoPlayerContext);
const { setView } = useContext(OptionsContext);

const loaded = !!videoInfo;

Expand All @@ -34,6 +37,15 @@ export const OptionsMainView = () => {
<FlavorOption />
<Divider w="100%" label="Theme" labelPosition="left" />
<ThemeSection />
<Divider w="100%" label="History" labelPosition="left" />
<Button
fullWidth
variant="light"
leftSection={<IconClock />}
onClick={() => setView("history")}
>
History
</Button>
<Divider w="100%" label="Instance" labelPosition="left" />
<InstanceSelect />
<Divider w="100%" label="Debugging" labelPosition="left" />
Expand Down
Loading

0 comments on commit 019f28e

Please sign in to comment.