mirror of
https://github.com/p-stream/p-stream.git
synced 2026-01-11 20:10:32 +00:00
update popup modal logic
This commit is contained in:
parent
520c32235c
commit
a02ea7c684
4 changed files with 230 additions and 284 deletions
|
|
@ -1,7 +1,12 @@
|
|||
import { ReactNode, useCallback } from "react";
|
||||
import classNames from "classnames";
|
||||
import { ReactNode, useCallback, useEffect } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
|
||||
import { IconPatch } from "@/components/buttons/IconPatch";
|
||||
import { Icons } from "@/components/Icon";
|
||||
import { OverlayPortal } from "@/components/overlays/OverlayDisplay";
|
||||
import { Flare } from "@/components/utils/Flare";
|
||||
import { Heading2 } from "@/components/utils/Text";
|
||||
import { useQueryParam } from "@/hooks/useQueryParams";
|
||||
|
||||
export function useModal(id: string) {
|
||||
|
|
@ -40,3 +45,74 @@ export function Modal(props: { id: string; children?: ReactNode }) {
|
|||
</OverlayPortal>
|
||||
);
|
||||
}
|
||||
|
||||
export function FancyModal(props: {
|
||||
id: string;
|
||||
children?: ReactNode;
|
||||
title?: string;
|
||||
size?: "md" | "xl";
|
||||
oneTime?: boolean;
|
||||
}) {
|
||||
const modal = useModal(props.id);
|
||||
|
||||
useEffect(() => {
|
||||
if (props.oneTime) {
|
||||
const isDismissed = localStorage.getItem(`modal-${props.id}-dismissed`);
|
||||
if (!isDismissed) {
|
||||
modal.show();
|
||||
}
|
||||
}
|
||||
}, [modal, props.id, props.oneTime]);
|
||||
|
||||
const handleClose = () => {
|
||||
if (props.oneTime) {
|
||||
localStorage.setItem(`modal-${props.id}-dismissed`, "true");
|
||||
}
|
||||
modal.hide();
|
||||
};
|
||||
|
||||
return (
|
||||
<OverlayPortal darken close={handleClose} show={modal.isShown}>
|
||||
<Helmet>
|
||||
<html data-no-scroll />
|
||||
</Helmet>
|
||||
<div className="flex absolute inset-0 items-center justify-center">
|
||||
<Flare.Base
|
||||
className={classNames(
|
||||
"group -m-[0.705em] rounded-3xl bg-background-main transition-colors duration-300 focus:relative focus:z-10",
|
||||
"w-full mx-4 p-6 bg-mediaCard-hoverBackground bg-opacity-60 backdrop-filter backdrop-blur-lg shadow-lg",
|
||||
props.size === "md" ? "max-w-md" : "max-w-2xl",
|
||||
)}
|
||||
>
|
||||
<div className="transition-transform duration-300 overflow-y-scroll max-h-[90dvh] scrollbar-none">
|
||||
<Flare.Light
|
||||
flareSize={300}
|
||||
cssColorVar="--colors-mediaCard-hoverAccent"
|
||||
backgroundClass="bg-mediaCard-hoverBackground duration-100"
|
||||
className="rounded-3xl bg-background-main group-hover:opacity-100"
|
||||
/>
|
||||
<Flare.Child className="pointer-events-auto relative mb-2p-[0.4em] transition-transform duration-300">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
{props.title && (
|
||||
<Heading2 className="!mt-0 !mb-0 pr-6">
|
||||
{props.title}
|
||||
</Heading2>
|
||||
)}
|
||||
<button
|
||||
type="button"
|
||||
className="text-s font-semibold text-type-secondary hover:text-white transition-transform hover:scale-95"
|
||||
onClick={handleClose}
|
||||
>
|
||||
<IconPatch icon={Icons.X} />
|
||||
</button>
|
||||
</div>
|
||||
<div className="text-lg text-type-secondary">
|
||||
{props.children}
|
||||
</div>
|
||||
</Flare.Child>
|
||||
</div>
|
||||
</Flare.Base>
|
||||
</div>
|
||||
</OverlayPortal>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,6 +50,7 @@ export function HomePage() {
|
|||
const s = useSearch(search);
|
||||
const [showBookmarks, setShowBookmarks] = useState(false);
|
||||
const [showWatching, setShowWatching] = useState(false);
|
||||
// const modal = useModal("notice");
|
||||
|
||||
const handleClick = (path: To) => {
|
||||
window.scrollTo(0, 0);
|
||||
|
|
@ -58,48 +59,12 @@ export function HomePage() {
|
|||
|
||||
const enableDiscover = usePreferencesStore((state) => state.enableDiscover);
|
||||
|
||||
/*
|
||||
// Safari Notice
|
||||
const [showModal, setShowModal] = useState(() => {
|
||||
const isSafari =
|
||||
typeof navigator !== "undefined" &&
|
||||
/Safari/.test(navigator.userAgent) &&
|
||||
!/Chrome/.test(navigator.userAgent);
|
||||
|
||||
const isMac =
|
||||
typeof navigator !== "undefined" && /Mac/.test(navigator.platform);
|
||||
|
||||
const isIOS =
|
||||
typeof navigator !== "undefined" &&
|
||||
/iPhone|iPad|iPod/.test(navigator.userAgent);
|
||||
|
||||
return isSafari && (isMac || isIOS);
|
||||
});
|
||||
*/
|
||||
|
||||
/* One time notice
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const isDismissed = localStorage.getItem("popupDismissed");
|
||||
if (!isDismissed) {
|
||||
setShowModal(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setShowModal(false);
|
||||
localStorage.setItem("popupDismissed", "true");
|
||||
};
|
||||
*/
|
||||
|
||||
// const { loggedIn } = useAuth(); // Adjust padding for popup show button based on logged in state
|
||||
|
||||
return (
|
||||
<HomeLayout showBg={showBg}>
|
||||
{/* Popup show button
|
||||
<a
|
||||
onClick={() => setShowModal(true)}
|
||||
{/* <a
|
||||
onClick={() => modal.show()}
|
||||
className={` text-white tabbable rounded-full z-50 fixed top-5 ${
|
||||
loggedIn
|
||||
? "right-[7.5rem] lg:right-[12.5rem] lg:text-2xl"
|
||||
|
|
@ -110,8 +75,7 @@ export function HomePage() {
|
|||
<IconPill icon={Icons.WARNING}>
|
||||
<span className="font-bold select-none">READ</span>
|
||||
</IconPill>
|
||||
</a>
|
||||
*/}
|
||||
</a> */}
|
||||
<div className="mb-16 sm:mb-24">
|
||||
<Helmet>
|
||||
<style type="text/css">{`
|
||||
|
|
@ -122,100 +86,96 @@ export function HomePage() {
|
|||
<title>{t("global.name")}</title>
|
||||
</Helmet>
|
||||
|
||||
{/* Popup
|
||||
{showModal && (
|
||||
<PopupModal
|
||||
styles="max-w-2xl" // max-w-md for short
|
||||
title="We’re changing our backend server!"
|
||||
message={
|
||||
<div>
|
||||
<p>
|
||||
On <strong>January 8th</strong>, the backend server will
|
||||
change from:
|
||||
</p>
|
||||
<p>
|
||||
<strong>server.vidbinge.com</strong> →{" "}
|
||||
<strong>server.fifthwit.tech</strong>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
You will need to <strong>migrate your account </strong> to the
|
||||
new server or choose to continue using the old server by
|
||||
updating your settings.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<strong>What You Need to Know:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
1. <strong>Migrating Your Account:</strong> Your data (e.g.,
|
||||
bookmarks) will not be automatically transferred. You’ll
|
||||
need to migrate your account from the settings page. Or from
|
||||
below.
|
||||
</li>
|
||||
<li>
|
||||
2. <strong>Staying on the Old Server:</strong> If you don’t
|
||||
want to change to the new server, your data will remain safe
|
||||
on <strong>server.vidbinge.com</strong>. You can change the
|
||||
Backend URL in your settings to
|
||||
"https://server.vidbinge.com".
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
<p>
|
||||
<strong>Steps to Move Your Data:</strong>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
1. Log into your account on{" "}
|
||||
<strong>server.vidbinge.com</strong>.
|
||||
</li>
|
||||
<li>
|
||||
(If you already are logged in, press here:{" "}
|
||||
<a href="/migration" className="text-type-link">
|
||||
Migrate my data.
|
||||
</a>
|
||||
)
|
||||
</li>
|
||||
<li>
|
||||
2. Go to the <strong>Settings</strong> page.
|
||||
</li>
|
||||
<li>
|
||||
3. Scroll down to{" "}
|
||||
<strong>Connections > Custom Server</strong>.
|
||||
</li>
|
||||
<li>
|
||||
3. Press the "Migrate my data to a new server."
|
||||
button.
|
||||
</li>
|
||||
<li>
|
||||
4. Enter the new server url:{" "}
|
||||
<strong>https://server.fifthwit.tech</strong> and press
|
||||
"Migrate".
|
||||
</li>
|
||||
<li>5. Login to your account with the same passphrase!</li>
|
||||
</ol>
|
||||
<br />
|
||||
<p>
|
||||
Thank you for your understanding and support during this
|
||||
transition! If you have questions or need help, feel free to
|
||||
reach out on the{" "}
|
||||
<a
|
||||
href="https://discord.com/invite/7z6znYgrTG"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-type-link"
|
||||
>
|
||||
P-Stream Discord
|
||||
</a>
|
||||
!
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
onClose={handleCloseModal}
|
||||
/>
|
||||
)}
|
||||
{/* Popup
|
||||
<FancyModal
|
||||
id="notice"
|
||||
title="We're changing our backend server!"
|
||||
oneTime
|
||||
>
|
||||
<div>
|
||||
<p>
|
||||
On <strong>January 8th</strong>, the backend server will change
|
||||
from:
|
||||
</p>
|
||||
<p>
|
||||
<strong>server.vidbinge.com</strong> →{" "}
|
||||
<strong>server.fifthwit.tech</strong>
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
You will need to <strong>migrate your account </strong> to the new
|
||||
server or choose to continue using the old server by updating your
|
||||
settings.
|
||||
</p>
|
||||
<br />
|
||||
<p>
|
||||
<strong>What You Need to Know:</strong>
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
1. <strong>Migrating Your Account:</strong> Your data (e.g.,
|
||||
bookmarks) will not be automatically transferred. You'll
|
||||
need to migrate your account from the settings page. Or from
|
||||
below.
|
||||
</li>
|
||||
<li>
|
||||
2. <strong>Staying on the Old Server:</strong> If you don't
|
||||
want to change to the new server, your data will remain safe on{" "}
|
||||
<strong>server.vidbinge.com</strong>. You can change the Backend
|
||||
URL in your settings to "https://server.vidbinge.com".
|
||||
</li>
|
||||
</ul>
|
||||
<br />
|
||||
<p>
|
||||
<strong>Steps to Move Your Data:</strong>
|
||||
</p>
|
||||
<ol>
|
||||
<li>
|
||||
1. Log into your account on <strong>server.vidbinge.com</strong>
|
||||
.
|
||||
</li>
|
||||
<li>
|
||||
(If you already are logged in, press here:{" "}
|
||||
<a href="/migration" className="text-type-link">
|
||||
Migrate my data.
|
||||
</a>
|
||||
)
|
||||
</li>
|
||||
<li>
|
||||
2. Go to the <strong>Settings</strong> page.
|
||||
</li>
|
||||
<li>
|
||||
3. Scroll down to{" "}
|
||||
<strong>Connections > Custom Server</strong>.
|
||||
</li>
|
||||
<li>
|
||||
3. Press the "Migrate my data to a new server."
|
||||
button.
|
||||
</li>
|
||||
<li>
|
||||
4. Enter the new server url:{" "}
|
||||
<strong>https://server.fifthwit.tech</strong> and press
|
||||
"Migrate".
|
||||
</li>
|
||||
<li>5. Login to your account with the same passphrase!</li>
|
||||
</ol>
|
||||
<br />
|
||||
<p>
|
||||
Thank you for your understanding and support during this
|
||||
transition! If you have questions or need help, feel free to reach
|
||||
out on the{" "}
|
||||
<a
|
||||
href="https://discord.com/invite/7z6znYgrTG"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-type-link"
|
||||
>
|
||||
P-Stream Discord
|
||||
</a>
|
||||
!
|
||||
</p>
|
||||
</div>
|
||||
</FancyModal>
|
||||
*/}
|
||||
|
||||
<HeroPart searchParams={searchParams} setIsSticky={setShowBg} />
|
||||
|
|
|
|||
|
|
@ -8,7 +8,12 @@ import { SettingsCard } from "@/components/layout/SettingsCard";
|
|||
import { Stepper } from "@/components/layout/Stepper";
|
||||
import { BiggerCenterContainer } from "@/components/layout/ThinContainer";
|
||||
import { VerticalLine } from "@/components/layout/VerticalLine";
|
||||
import { Modal, ModalCard, useModal } from "@/components/overlays/Modal";
|
||||
import {
|
||||
FancyModal,
|
||||
Modal,
|
||||
ModalCard,
|
||||
useModal,
|
||||
} from "@/components/overlays/Modal";
|
||||
import {
|
||||
StatusCircle,
|
||||
StatusCircleProps,
|
||||
|
|
@ -33,7 +38,6 @@ import { conf } from "@/setup/config";
|
|||
import { useAuthStore } from "@/stores/auth";
|
||||
import { getProxyUrls } from "@/utils/proxyUrls";
|
||||
|
||||
import { PopupModal } from "../parts/home/PopupModal";
|
||||
import { Status, testFebboxToken } from "../parts/settings/SetupPart";
|
||||
|
||||
async function getFebboxTokenStatus(febboxToken: string | null) {
|
||||
|
|
@ -179,6 +183,7 @@ export function FEDAPISetup() {
|
|||
export function OnboardingPage() {
|
||||
const navigate = useNavigateOnboarding();
|
||||
const skipModal = useModal("skip");
|
||||
const infoModal = useModal("info");
|
||||
const { completeAndRedirect } = useRedirectBack();
|
||||
const { t } = useTranslation();
|
||||
const noProxies = getProxyUrls().length === 0;
|
||||
|
|
@ -189,12 +194,6 @@ export function OnboardingPage() {
|
|||
!/Chrome/.test(navigator.userAgent) &&
|
||||
!/Edg/.test(navigator.userAgent);
|
||||
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
|
||||
const handleCloseModal = () => {
|
||||
setShowModal(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<MinimalPageLayout>
|
||||
<PageTitle subpage k="global.pages.onboarding" />
|
||||
|
|
@ -216,68 +215,59 @@ export function OnboardingPage() {
|
|||
</div>
|
||||
</ModalCard>
|
||||
</Modal>
|
||||
{showModal && (
|
||||
<PopupModal
|
||||
styles="max-w-2xl" // max-w-md for short max-w-2xl long
|
||||
title="Understanding a setup"
|
||||
message={
|
||||
<div>
|
||||
<p>
|
||||
P-Stream doesn't host videos. It relies on third-party
|
||||
websites for content, so you need to choose how it connects to
|
||||
those sites.
|
||||
<FancyModal id={infoModal.id} title="Understanding a setup" size="xl">
|
||||
<div>
|
||||
<p>
|
||||
P-Stream doesn't host videos. It relies on third-party websites
|
||||
for content, so you need to choose how it connects to those sites.
|
||||
<br />
|
||||
<br />
|
||||
<strong>Your Options:</strong>
|
||||
<br />
|
||||
<strong>1. Extension (Recommended)</strong>
|
||||
<br />
|
||||
The extension gives you access to the most sources. It acts as a
|
||||
local proxy and can handle sites that need special cookies or
|
||||
headers to load.
|
||||
<br />
|
||||
<br />
|
||||
<strong>2. Proxy</strong>
|
||||
<br />
|
||||
The proxy scrapes media from other websites. It bypasses browser
|
||||
restrictions (like CORS) to allow scraping.
|
||||
<br />
|
||||
<br />
|
||||
<strong>3. Default Setup</strong>
|
||||
<br />
|
||||
Uses P-Stream's built-in proxy. It's the easiest option
|
||||
but might be slower due to shared bandwidth.
|
||||
<br />
|
||||
<br />
|
||||
{conf().ALLOW_FEBBOX_KEY && (
|
||||
<>
|
||||
<strong>Optional FED API (Febbox) UI token</strong>
|
||||
<br />
|
||||
Bringing your own Febbox account allows you to unlock FED API,
|
||||
our best source with 4K quality, Dolby Atmos, the most content,
|
||||
and the best (fastest) load times. This the highly recommended!
|
||||
<br />
|
||||
<br />
|
||||
<strong>Your Options:</strong>
|
||||
<br />
|
||||
<strong>1. Extension (Recommended)</strong>
|
||||
<br />
|
||||
The extension gives you access to the most sources. It acts as a
|
||||
local proxy and can handle sites that need special cookies or
|
||||
headers to load.
|
||||
<br />
|
||||
<br />
|
||||
<strong>2. Proxy</strong>
|
||||
<br />
|
||||
The proxy scrapes media from other websites. It bypasses browser
|
||||
restrictions (like CORS) to allow scraping.
|
||||
<br />
|
||||
<br />
|
||||
<strong>3. Default Setup</strong>
|
||||
<br />
|
||||
Uses P-Stream's built-in proxy. It's the easiest
|
||||
option but might be slower due to shared bandwidth.
|
||||
<br />
|
||||
<br />
|
||||
{conf().ALLOW_FEBBOX_KEY && (
|
||||
<>
|
||||
<strong>Optional FED API (Febbox) UI token</strong>
|
||||
<br />
|
||||
Bringing your own Febbox account allows you to unlock FED
|
||||
API, our best source with 4K quality, Dolby Atmos, the most
|
||||
content, and the best (fastest) load times. This the highly
|
||||
recommended!
|
||||
<br />
|
||||
<br />
|
||||
</>
|
||||
)}
|
||||
If you have more questions on how this works, feel free to ask
|
||||
on the{" "}
|
||||
<a
|
||||
href="https://discord.com/invite/7z6znYgrTG"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-type-link"
|
||||
>
|
||||
P-Stream Discord
|
||||
</a>{" "}
|
||||
server!
|
||||
</p>
|
||||
</div>
|
||||
}
|
||||
onClose={handleCloseModal}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
If you have more questions on how this works, feel free to ask on
|
||||
the{" "}
|
||||
<a
|
||||
href="https://discord.com/invite/7z6znYgrTG"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-type-link"
|
||||
>
|
||||
P-Stream Discord
|
||||
</a>{" "}
|
||||
server!
|
||||
</p>
|
||||
</div>
|
||||
</FancyModal>
|
||||
<BiggerCenterContainer>
|
||||
<Stepper steps={2} current={1} className="mb-12" />
|
||||
<Heading2 className="!mt-0 !text-3xl">
|
||||
|
|
@ -287,7 +277,7 @@ export function OnboardingPage() {
|
|||
{t("onboarding.start.explainer")}
|
||||
<div
|
||||
className="pt-4 flex cursor-pointer items-center text-type-link"
|
||||
onClick={() => setShowModal(true)}
|
||||
onClick={() => infoModal.show()}
|
||||
>
|
||||
<p>More info</p>
|
||||
<Icon className="pl-2" icon={Icons.CIRCLE_QUESTION} />
|
||||
|
|
|
|||
|
|
@ -1,80 +0,0 @@
|
|||
import classNames from "classnames";
|
||||
import { ReactNode, useEffect } from "react";
|
||||
|
||||
import { IconPatch } from "@/components/buttons/IconPatch";
|
||||
import { Icons } from "@/components/Icon";
|
||||
import { Flare } from "@/components/utils/Flare";
|
||||
import { Heading2 } from "@/components/utils/Text";
|
||||
|
||||
export interface PopupModalProps {
|
||||
title: string;
|
||||
message: ReactNode;
|
||||
closable?: boolean;
|
||||
onClose?: () => void;
|
||||
styles?: string;
|
||||
}
|
||||
|
||||
export function PopupModal({
|
||||
title,
|
||||
message,
|
||||
closable = true,
|
||||
onClose,
|
||||
styles,
|
||||
}: PopupModalProps) {
|
||||
useEffect(() => {
|
||||
document.body.style.overflow = "hidden";
|
||||
|
||||
return () => {
|
||||
document.body.style.overflow = "";
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
"fixed inset-0 z-[100] flex items-center justify-center",
|
||||
"bg-background-main bg-opacity-75 backdrop-filter backdrop-blur-sm",
|
||||
"transition-opacity duration-400",
|
||||
"pointer-events-auto",
|
||||
)}
|
||||
onClick={onClose}
|
||||
>
|
||||
<Flare.Base
|
||||
className={classNames(
|
||||
"group -m-[0.705em] rounded-3xl bg-background-main transition-colors duration-300 focus:relative focus:z-10",
|
||||
"fixed top-0 left-0 right-0 z-50 p-6 bg-mediaCard-hoverBackground bg-opacity-60 backdrop-filter backdrop-blur-lg shadow-lg mx-auto",
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={classNames(
|
||||
"transition-transform duration-300",
|
||||
"overflow-y-scroll max-h-[90dvh] md:max-h-[90dvh] scrollbar-none",
|
||||
styles,
|
||||
)}
|
||||
>
|
||||
<Flare.Light
|
||||
flareSize={300}
|
||||
cssColorVar="--colors-mediaCard-hoverAccent"
|
||||
backgroundClass="bg-mediaCard-hoverBackground duration-100"
|
||||
className="rounded-3xl bg-background-main group-hover:opacity-100"
|
||||
/>
|
||||
<Flare.Child className="pointer-events-auto relative mb-2p-[0.4em] transition-transform duration-300">
|
||||
<div className="flex justify-between items-center mb-4">
|
||||
<Heading2 className="!mt-0 !mb-0 pr-6">{title}</Heading2>
|
||||
{closable && (
|
||||
<button
|
||||
type="button"
|
||||
className="fixed right-4 text-s font-semibold text-type-secondary hover:text-white transition-transform hover:scale-110"
|
||||
onClick={onClose}
|
||||
>
|
||||
<IconPatch icon={Icons.X} />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-lg text-type-secondary">{message}</p>
|
||||
</Flare.Child>
|
||||
</div>
|
||||
</Flare.Base>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Reference in a new issue