update popup modal logic

This commit is contained in:
Pas 2025-03-29 12:20:04 -06:00
parent 520c32235c
commit a02ea7c684
4 changed files with 230 additions and 284 deletions

View file

@ -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>
);
}

View file

@ -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">{`
@ -123,15 +87,15 @@ export function HomePage() {
</Helmet>
{/* Popup
{showModal && (
<PopupModal
styles="max-w-2xl" // max-w-md for short
title="Were changing our backend server!"
message={
<FancyModal
id="notice"
title="We're changing our backend server!"
oneTime
>
<div>
<p>
On <strong>January 8th</strong>, the backend server will
change from:
On <strong>January 8th</strong>, the backend server will change
from:
</p>
<p>
<strong>server.vidbinge.com</strong> {" "}
@ -139,9 +103,9 @@ export function HomePage() {
</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.
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>
@ -150,16 +114,15 @@ export function HomePage() {
<ul>
<li>
1. <strong>Migrating Your Account:</strong> Your data (e.g.,
bookmarks) will not be automatically transferred. Youll
bookmarks) will not be automatically transferred. You&apos;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 dont
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
&quot;https://server.vidbinge.com&quot;.
2. <strong>Staying on the Old Server:</strong> If you don&apos;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 &quot;https://server.vidbinge.com&quot;.
</li>
</ul>
<br />
@ -168,8 +131,8 @@ export function HomePage() {
</p>
<ol>
<li>
1. Log into your account on{" "}
<strong>server.vidbinge.com</strong>.
1. Log into your account on <strong>server.vidbinge.com</strong>
.
</li>
<li>
(If you already are logged in, press here:{" "}
@ -199,8 +162,8 @@ export function HomePage() {
<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{" "}
transition! If you have questions or need help, feel free to reach
out on the{" "}
<a
href="https://discord.com/invite/7z6znYgrTG"
target="_blank"
@ -212,10 +175,7 @@ export function HomePage() {
!
</p>
</div>
}
onClose={handleCloseModal}
/>
)}
</FancyModal>
*/}
<HeroPart searchParams={searchParams} setIsSticky={setShowBg} />

View file

@ -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,16 +215,11 @@ 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={
<FancyModal id={infoModal.id} title="Understanding a setup" size="xl">
<div>
<p>
P-Stream doesn&apos;t host videos. It relies on third-party
websites for content, so you need to choose how it connects to
those sites.
P-Stream doesn&apos;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>
@ -245,24 +239,23 @@ export function OnboardingPage() {
<br />
<strong>3. Default Setup</strong>
<br />
Uses P-Stream&apos;s built-in proxy. It&apos;s the easiest
option but might be slower due to shared bandwidth.
Uses P-Stream&apos;s built-in proxy. It&apos;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!
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{" "}
If you have more questions on how this works, feel free to ask on
the{" "}
<a
href="https://discord.com/invite/7z6znYgrTG"
target="_blank"
@ -274,10 +267,7 @@ export function OnboardingPage() {
server!
</p>
</div>
}
onClose={handleCloseModal}
/>
)}
</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} />

View file

@ -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>
);
}