mirror of
https://github.com/p-stream/p-stream.git
synced 2026-04-19 13:42:05 +00:00
182 lines
5.4 KiB
TypeScript
182 lines
5.4 KiB
TypeScript
import { Trans, useTranslation } from "react-i18next";
|
|
import { Icons } from "@/components/Icon";
|
|
import { SectionHeading } from "@/components/layout/SectionHeading";
|
|
import { MediaGrid } from "@/components/media/MediaGrid";
|
|
import {
|
|
getIfBookmarkedFromPortable,
|
|
useBookmarkContext,
|
|
} from "@/state/bookmark";
|
|
import { useWatchedContext } from "@/state/watched";
|
|
import { WatchedMediaCard } from "@/components/media/WatchedMediaCard";
|
|
import { EditButton } from "@/components/buttons/EditButton";
|
|
import { useEffect, useState } from "react";
|
|
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
|
import { useHistory } from "react-router-dom";
|
|
import { Modal, ModalCard } from "@/components/layout/Modal";
|
|
import { Button } from "@/components/Button";
|
|
import { EmbedMigration } from "../other/v2Migration";
|
|
|
|
function Bookmarks() {
|
|
const { t } = useTranslation();
|
|
const { getFilteredBookmarks, setItemBookmark } = useBookmarkContext();
|
|
const bookmarks = getFilteredBookmarks();
|
|
const [editing, setEditing] = useState(false);
|
|
const [gridRef] = useAutoAnimate<HTMLDivElement>();
|
|
|
|
if (bookmarks.length === 0) return null;
|
|
|
|
return (
|
|
<div>
|
|
<SectionHeading
|
|
title={t("search.bookmarks") || "Bookmarks"}
|
|
icon={Icons.BOOKMARK}
|
|
>
|
|
<EditButton editing={editing} onEdit={setEditing} />
|
|
</SectionHeading>
|
|
<MediaGrid ref={gridRef}>
|
|
{bookmarks.map((v) => (
|
|
<WatchedMediaCard
|
|
key={v.id}
|
|
media={v}
|
|
closable={editing}
|
|
onClose={() => setItemBookmark(v, false)}
|
|
/>
|
|
))}
|
|
</MediaGrid>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function Watched() {
|
|
const { t } = useTranslation();
|
|
const { getFilteredBookmarks } = useBookmarkContext();
|
|
const { getFilteredWatched, removeProgress } = useWatchedContext();
|
|
const [editing, setEditing] = useState(false);
|
|
const [gridRef] = useAutoAnimate<HTMLDivElement>();
|
|
|
|
const bookmarks = getFilteredBookmarks();
|
|
const watchedItems = getFilteredWatched().filter(
|
|
(v) => !getIfBookmarkedFromPortable(bookmarks, v.item.meta)
|
|
);
|
|
|
|
if (watchedItems.length === 0) return null;
|
|
|
|
return (
|
|
<div>
|
|
<SectionHeading
|
|
title={t("search.continueWatching") || "Continue Watching"}
|
|
icon={Icons.CLOCK}
|
|
>
|
|
<EditButton editing={editing} onEdit={setEditing} />
|
|
</SectionHeading>
|
|
<MediaGrid ref={gridRef}>
|
|
{watchedItems.map((v) => (
|
|
<WatchedMediaCard
|
|
key={v.item.meta.id}
|
|
media={v.item.meta}
|
|
closable={editing}
|
|
onClose={() => removeProgress(v.item.meta.id)}
|
|
/>
|
|
))}
|
|
</MediaGrid>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
function NewDomainModal() {
|
|
const [show, setShow] = useState(
|
|
new URLSearchParams(window.location.search).get("migrated") === "1"
|
|
);
|
|
const [loaded, setLoaded] = useState(false);
|
|
const history = useHistory();
|
|
const { t } = useTranslation();
|
|
|
|
useEffect(() => {
|
|
const newParams = new URLSearchParams(history.location.search);
|
|
newParams.delete("migrated");
|
|
history.replace({
|
|
search: newParams.toString(),
|
|
});
|
|
}, [history]);
|
|
|
|
useEffect(() => {
|
|
setTimeout(() => {
|
|
setLoaded(true);
|
|
}, 500);
|
|
}, []);
|
|
|
|
// If you see this bit of code, don't snitch!
|
|
// We need to urge users to update their bookmarks and usage,
|
|
// so we're putting a fake deadline that's only 2 weeks away.
|
|
const day = 1e3 * 60 * 60 * 24;
|
|
const months = [
|
|
"January",
|
|
"February",
|
|
"March",
|
|
"April",
|
|
"May",
|
|
"June",
|
|
"July",
|
|
"August",
|
|
"September",
|
|
"October",
|
|
"November",
|
|
"December",
|
|
];
|
|
const firstVisitToSite = new Date(
|
|
localStorage.getItem("firstVisitToSite") || Date.now()
|
|
);
|
|
localStorage.setItem("firstVisitToSite", firstVisitToSite.toISOString());
|
|
const fakeEndResult = new Date(firstVisitToSite.getTime() + 14 * day);
|
|
const endDateString = `${fakeEndResult.getDate()} ${
|
|
months[fakeEndResult.getMonth()]
|
|
} ${fakeEndResult.getFullYear()}`;
|
|
|
|
return (
|
|
<Modal show={show && loaded}>
|
|
<ModalCard>
|
|
<div className="mb-12">
|
|
<div
|
|
className="absolute left-0 top-0 h-[300px] w-full -translate-y-1/2 opacity-50"
|
|
style={{
|
|
backgroundImage: `radial-gradient(ellipse 70% 9rem, #7831C1 0%, transparent 100%)`,
|
|
}}
|
|
/>
|
|
<div className="relative flex items-center justify-center">
|
|
<div className="rounded-full bg-bink-200 py-4 px-12 text-center text-sm font-bold text-white md:text-xl">
|
|
{t("v3.newDomain")}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="space-y-6">
|
|
<h2 className="text-2xl font-bold text-white">
|
|
{t("v3.newSiteTitle")}
|
|
</h2>
|
|
<p className="leading-7">
|
|
<Trans i18nKey="v3.newDomainText" values={{ date: endDateString }}>
|
|
<span className="text-slate-300" />
|
|
<span className="font-bold text-white" />
|
|
</Trans>
|
|
</p>
|
|
<p>{t("v3.tireless")}</p>
|
|
</div>
|
|
<div className="mt-16 mb-6 flex items-center justify-center">
|
|
<Button icon={Icons.PLAY} onClick={() => setShow(false)}>
|
|
{t("v3.leaveAnnouncement")}
|
|
</Button>
|
|
</div>
|
|
</ModalCard>
|
|
</Modal>
|
|
);
|
|
}
|
|
|
|
export function HomeView() {
|
|
return (
|
|
<div className="mb-16 mt-32">
|
|
<EmbedMigration />
|
|
<NewDomainModal />
|
|
<Bookmarks />
|
|
<Watched />
|
|
</div>
|
|
);
|
|
}
|