mirror of
https://github.com/sussy-code/smov.git
synced 2024-12-29 16:07:40 +01:00
Fix banner and direct link to media + improve load time
This commit is contained in:
parent
21a5804317
commit
7a8e78e767
3 changed files with 58 additions and 53 deletions
|
@ -1,6 +1,6 @@
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import { ReactNode, useEffect, useState } from "react";
|
import { ReactNode, useEffect, useState } from "react";
|
||||||
import { Link } from "react-router-dom"; // Import Link from react-router-dom
|
import { useNavigate } from "react-router-dom"; // Import Link from react-router-dom
|
||||||
|
|
||||||
import { ThiccContainer } from "@/components/layout/ThinContainer";
|
import { ThiccContainer } from "@/components/layout/ThinContainer";
|
||||||
import { Divider } from "@/components/utils/Divider";
|
import { Divider } from "@/components/utils/Divider";
|
||||||
|
@ -43,14 +43,10 @@ function isShowOrMovie(tmdbFullId: string): "series" | "movie" | "unknown" {
|
||||||
|
|
||||||
function directLinkToContent(tmdbFullId: string) {
|
function directLinkToContent(tmdbFullId: string) {
|
||||||
if (isShowOrMovie(tmdbFullId) === "series") {
|
if (isShowOrMovie(tmdbFullId) === "series") {
|
||||||
return `/media/tmdb-tv-${tmdbFullId.split("-")[1]}#/media/tmdb-tv-${
|
return `/media/tmdb-tv-${tmdbFullId.split("-")[1]}`;
|
||||||
tmdbFullId.split("-")[1]
|
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
if (isShowOrMovie(tmdbFullId) === "movie") {
|
if (isShowOrMovie(tmdbFullId) === "movie") {
|
||||||
return `/media/tmdb-movie-${tmdbFullId.split("-")[1]}#/media/tmdb-movie-${
|
return `/media/tmdb-movie-${tmdbFullId.split("-")[1]}`;
|
||||||
tmdbFullId.split("-")[1]
|
|
||||||
}`;
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -61,15 +57,16 @@ function ConfigValue(props: {
|
||||||
id: string;
|
id: string;
|
||||||
children?: ReactNode;
|
children?: ReactNode;
|
||||||
}) {
|
}) {
|
||||||
|
const navigate = useNavigate();
|
||||||
const link = directLinkToContent(props.id);
|
const link = directLinkToContent(props.id);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<p className="flex-1 font-bold text-white pr-5 pl-3">
|
<p className="flex-1 font-bold text-white pr-5 pl-3">
|
||||||
{link ? (
|
{link ? (
|
||||||
<Link to={link} className="hover:underline">
|
<p onClick={() => navigate(link)} className="hover:underline">
|
||||||
{props.name}
|
{props.name}
|
||||||
</Link>
|
</p>
|
||||||
) : (
|
) : (
|
||||||
<p>{props.name}</p>
|
<p>{props.name}</p>
|
||||||
)}
|
)}
|
||||||
|
@ -160,14 +157,12 @@ async function getTimeSinceProcessStart(): Promise<string> {
|
||||||
const timeDifference =
|
const timeDifference =
|
||||||
currentTime.getTime() - new Date(processStartTime).getTime();
|
currentTime.getTime() - new Date(processStartTime).getTime();
|
||||||
|
|
||||||
// Convert the time difference to a human-readable format
|
|
||||||
const hours = Math.floor(timeDifference / (1000 * 60 * 60));
|
const hours = Math.floor(timeDifference / (1000 * 60 * 60));
|
||||||
const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
|
const minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
|
||||||
const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
|
const seconds = Math.floor((timeDifference % (1000 * 60)) / 1000);
|
||||||
const percentageOfHour = Math.ceil(minutes / 60);
|
|
||||||
|
|
||||||
if (hours > 0) {
|
if (hours > 0) {
|
||||||
return `${hours}.${percentageOfHour} hours`;
|
return `${hours} hours`;
|
||||||
}
|
}
|
||||||
if (minutes > 0) {
|
if (minutes > 0) {
|
||||||
return `${minutes} minutes`;
|
return `${minutes} minutes`;
|
||||||
|
@ -178,7 +173,6 @@ async function getTimeSinceProcessStart(): Promise<string> {
|
||||||
export function TopFlix() {
|
export function TopFlix() {
|
||||||
const [recentPlayedItems, setRecentPlayedItems] = useState<any[]>([]);
|
const [recentPlayedItems, setRecentPlayedItems] = useState<any[]>([]);
|
||||||
const [totalViews, setTotalViews] = useState<string | null>(null);
|
const [totalViews, setTotalViews] = useState<string | null>(null);
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [currentPage, setCurrentPage] = useState(1);
|
const [currentPage, setCurrentPage] = useState(1);
|
||||||
const itemsPerPage = 10;
|
const itemsPerPage = 10;
|
||||||
const maxItemsToShow = 100; // Maximum items to show
|
const maxItemsToShow = 100; // Maximum items to show
|
||||||
|
@ -203,9 +197,6 @@ export function TopFlix() {
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Error fetching recent played items:", error);
|
console.error("Error fetching recent played items:", error);
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
setLoading(false);
|
|
||||||
});
|
});
|
||||||
getTotalViews()
|
getTotalViews()
|
||||||
.then((views) => {
|
.then((views) => {
|
||||||
|
@ -237,12 +228,6 @@ export function TopFlix() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return (
|
|
||||||
<p className="flex items-center justify-center h-screen">Loading...</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SubPageLayout>
|
<SubPageLayout>
|
||||||
<ThiccContainer>
|
<ThiccContainer>
|
||||||
|
|
|
@ -28,7 +28,6 @@ export function Layout(props: { children: ReactNode }) {
|
||||||
const location = useBannerStore((s) => s.location);
|
const location = useBannerStore((s) => s.location);
|
||||||
const [extensionState, setExtensionState] =
|
const [extensionState, setExtensionState] =
|
||||||
useState<ExtensionStatus>("unknown");
|
useState<ExtensionStatus>("unknown");
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [isMobile, setIsMobile] = useState(false);
|
const [isMobile, setIsMobile] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -37,7 +36,6 @@ export function Layout(props: { children: ReactNode }) {
|
||||||
getExtensionState().then((state) => {
|
getExtensionState().then((state) => {
|
||||||
if (isMounted) {
|
if (isMounted) {
|
||||||
setExtensionState(state);
|
setExtensionState(state);
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -56,12 +54,6 @@ export function Layout(props: { children: ReactNode }) {
|
||||||
};
|
};
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (loading) {
|
|
||||||
return (
|
|
||||||
<p className="flex items-center justify-center h-screen">Loading...</p>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{extensionState !== "success" && !isMobile && (
|
{extensionState !== "success" && !isMobile && (
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { Trans, useTranslation } from "react-i18next";
|
||||||
import { useLocation, useNavigate } from "react-router-dom";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { Icon, Icons } from "@/components/Icon";
|
import { Icon, Icons } from "@/components/Icon";
|
||||||
|
@ -22,6 +22,13 @@ export function Banner(props: {
|
||||||
info: Icons.CIRCLE_EXCLAMATION,
|
info: Icons.CIRCLE_EXCLAMATION,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const hideBannerFlag = sessionStorage.getItem("hideBanner");
|
||||||
|
if (hideBannerFlag) {
|
||||||
|
hideBanner(props.id, true);
|
||||||
|
}
|
||||||
|
}, [hideBanner, props.id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div ref={ref}>
|
<div ref={ref}>
|
||||||
<div
|
<div
|
||||||
|
@ -36,7 +43,10 @@ export function Banner(props: {
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
className="absolute right-4 hover:cursor-pointer"
|
className="absolute right-4 hover:cursor-pointer"
|
||||||
onClick={() => hideBanner(props.id, true)}
|
onClick={() => {
|
||||||
|
hideBanner(props.id, true);
|
||||||
|
sessionStorage.setItem("hideBanner", "true");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Icon icon={Icons.X} />
|
<Icon icon={Icons.X} />
|
||||||
</span>
|
</span>
|
||||||
|
@ -57,45 +67,60 @@ export function ExtensionBanner(props: {
|
||||||
const { pathname } = useLocation();
|
const { pathname } = useLocation();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!loc) return;
|
if (loc) {
|
||||||
setLocation(loc);
|
setLocation(loc);
|
||||||
return () => {
|
return () => {
|
||||||
setLocation(null);
|
setLocation(null);
|
||||||
};
|
};
|
||||||
|
}
|
||||||
}, [setLocation, loc]);
|
}, [setLocation, loc]);
|
||||||
|
|
||||||
|
const hideBannerFlag = sessionStorage.getItem("hideBanner");
|
||||||
|
if (hideBannerFlag) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (currentLocation !== loc || pathname === "/onboarding/extension")
|
if (currentLocation !== loc || pathname === "/onboarding/extension")
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// Show the banner with a 45% chance
|
// Show the banner with a 40% chance
|
||||||
if (Math.random() < 0.45) {
|
if (Math.random() < 0.4) {
|
||||||
let bannerText = "";
|
let bannerText = "";
|
||||||
switch (props.extensionState) {
|
switch (props.extensionState) {
|
||||||
case "noperms":
|
case "noperms":
|
||||||
bannerText =
|
bannerText = "The extension does'nt have the necessary permissions.";
|
||||||
"You don't have the necessary permissions to use the extension.";
|
|
||||||
break;
|
break;
|
||||||
case "outdated":
|
case "outdated":
|
||||||
bannerText =
|
bannerText = "Your extension is outdated. Please update it here.";
|
||||||
"Your extension is outdated. Please update it for better performance.";
|
|
||||||
break;
|
break;
|
||||||
case "disallowed":
|
case "disallowed":
|
||||||
bannerText = "The extension is not enabled on this page.";
|
bannerText =
|
||||||
|
"The extension is not enabled, click <bold>here</bold> to fix it.";
|
||||||
|
break;
|
||||||
|
case "failed":
|
||||||
|
bannerText =
|
||||||
|
"The extension is broken... Please click <bold>here</bold>.";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
bannerText =
|
bannerText =
|
||||||
"You don't have the extension! Download it here for better quality.";
|
"You don't have the extension! Download it <bold>here</bold> for better quality.";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<Banner id="extension" type="info">
|
||||||
onClick={() => navigate("/onboarding/extension")}
|
<div
|
||||||
style={{ cursor: "pointer" }}
|
onClick={() => navigate("/onboarding/extension")}
|
||||||
>
|
style={{ cursor: "pointer" }}
|
||||||
<Banner id="extension" type="info">
|
>
|
||||||
{bannerText}
|
<Trans
|
||||||
</Banner>
|
i18nKey={bannerText}
|
||||||
</div>
|
components={{
|
||||||
|
bold: <span className="font-bold" />,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Banner>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -119,6 +144,9 @@ export function BannerLocation(props: { location?: string }) {
|
||||||
|
|
||||||
if (currentLocation !== loc) return null;
|
if (currentLocation !== loc) return null;
|
||||||
|
|
||||||
|
const hideBannerFlag = sessionStorage.getItem("hideBanner");
|
||||||
|
if (hideBannerFlag) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{!isOnline && !ignoredBannerIds.includes("offline") ? (
|
{!isOnline && !ignoredBannerIds.includes("offline") ? (
|
||||||
|
|
Loading…
Reference in a new issue