add low performance mode

This commit is contained in:
Pas 2025-06-24 17:59:13 -06:00
parent 7b4a013fae
commit 200d3e69ac
16 changed files with 261 additions and 73 deletions

View file

@ -961,6 +961,7 @@
}
},
"preferences": {
"title": "Preferences",
"language": "Application language",
"languageDescription": "Language applied to the entire application, only English has silly stuff 🙁.",
"thumbnail": "Generate thumbnails",
@ -972,9 +973,11 @@
"skipCredits": "Skip End Credits",
"skipCreditsDescription": "When enabled, automatically play the next episode at 99% completion to skip end credits. When disabled, wait until the episode is fully completed.",
"skipCreditsLabel": "Skip end credits",
"lowPerformanceMode": "Low performance/bandwidth mode",
"lowPerformanceModeDescription": "Optimizes the application for slower connections and devices by disabling bandwidth-heavy features. This mode reduces data usage and improves performance while keeping the core search and watch functionality intact. ",
"lowPerformanceModeLabel": "Low performance mode",
"sourceOrder": "Reordering sources",
"sourceOrderDescription": "Drag and drop to reorder sources. This will determine the order in which sources are checked for the media you are trying to watch. If a source is greyed out, it means the <bold>extension</bold> is required for that source. <br><br> <strong>(The default order is best for most users)</strong>",
"title": "Preferences",
"sourceOrderEnableLabel": "Custom source order"
},
"reset": "Reset",

View file

@ -22,6 +22,7 @@ export interface SettingsInput {
sourceOrder?: string[];
enableSourceOrder?: boolean;
proxyTmdb?: boolean;
enableLowPerformanceMode?: boolean;
}
export interface SettingsResponse {
@ -42,6 +43,7 @@ export interface SettingsResponse {
sourceOrder?: string[];
enableSourceOrder?: boolean;
proxyTmdb?: boolean;
enableLowPerformanceMode?: boolean;
}
export function updateSettings(

View file

@ -13,6 +13,7 @@ import { useAuth } from "@/hooks/auth/useAuth";
import { useBackendUrl } from "@/hooks/auth/useBackendUrl";
import { conf } from "@/setup/config";
import { useAuthStore } from "@/stores/auth";
import { usePreferencesStore } from "@/stores/preferences";
function Divider() {
return <hr className="border-0 w-full h-px bg-dropdown-border" />;
@ -227,6 +228,10 @@ export function LinksDropdown(props: { children: React.ReactNode }) {
setOpen((s) => !s);
}, []);
const enableLowPerformanceMode = usePreferencesStore(
(s) => s.enableLowPerformanceMode,
);
return (
<div className="relative is-dropdown">
<div
@ -271,9 +276,11 @@ export function LinksDropdown(props: { children: React.ReactNode }) {
<DropdownLink href="/about" icon={Icons.CIRCLE_QUESTION}>
{t("navigation.menu.about")}
</DropdownLink>
<DropdownLink href="/discover" icon={Icons.RISING_STAR}>
{t("navigation.menu.discover")}
</DropdownLink>
{!enableLowPerformanceMode && (
<DropdownLink href="/discover" icon={Icons.RISING_STAR}>
{t("navigation.menu.discover")}
</DropdownLink>
)}
<WatchPartyInputLink />
{deviceName ? (
<DropdownLink

View file

@ -11,6 +11,7 @@ import { useAuth } from "@/hooks/auth/useAuth";
import { BlurEllipsis } from "@/pages/layouts/SubPageLayout";
import { conf } from "@/setup/config";
import { useBannerSize } from "@/stores/banner";
import { usePreferencesStore } from "@/stores/preferences";
import { BrandPill } from "./BrandPill";
@ -52,6 +53,10 @@ export function Navigation(props: NavigationProps) {
return minLength + (maxLength - minLength) * (1 - scrollFactor);
};
const enableLowPerformanceMode = usePreferencesStore(
(s) => s.enableLowPerformanceMode,
);
return (
<>
{/* lightbar */}
@ -63,7 +68,7 @@ export function Navigation(props: NavigationProps) {
}}
>
<div className="absolute inset-x-0 -mt-[22%] flex items-center sm:mt-0">
<Lightbar />
<Lightbar noParticles={enableLowPerformanceMode} />
</div>
</div>
) : null}
@ -149,33 +154,34 @@ export function Navigation(props: NavigationProps) {
navigation
/>
</a>
{window.location.pathname !== "/discover" ? (
<a
onClick={() => handleClick("/discover")}
rel="noreferrer"
className="text-xl text-white tabbable rounded-full backdrop-blur-lg"
>
<IconPatch
icon={Icons.RISING_STAR}
clickable
downsized
navigation
/>
</a>
) : (
<a
onClick={() => handleClick("/")}
rel="noreferrer"
className="text-lg text-white tabbable rounded-full backdrop-blur-lg"
>
<IconPatch
icon={Icons.SEARCH}
clickable
downsized
navigation
/>
</a>
)}
{!enableLowPerformanceMode &&
(window.location.pathname !== "/discover" ? (
<a
onClick={() => handleClick("/discover")}
rel="noreferrer"
className="text-xl text-white tabbable rounded-full backdrop-blur-lg"
>
<IconPatch
icon={Icons.RISING_STAR}
clickable
downsized
navigation
/>
</a>
) : (
<a
onClick={() => handleClick("/")}
rel="noreferrer"
className="text-lg text-white tabbable rounded-full backdrop-blur-lg"
>
<IconPatch
icon={Icons.SEARCH}
clickable
downsized
navigation
/>
</a>
))}
</div>
<div className="relative pointer-events-auto">
<LinksDropdown>

View file

@ -67,6 +67,10 @@ function MediaCardContent({
const [searchQuery] = useSearchQuery();
const enableLowPerformanceMode = usePreferencesStore(
(state) => state.enableLowPerformanceMode,
);
if (isReleased() && media.year) {
dotListContent.push(media.year.toFixed());
}
@ -190,7 +194,7 @@ function MediaCardContent({
<DotList className="text-xs" content={dotListContent} />
</div>
{!closable && (
{!closable && !enableLowPerformanceMode && (
<div className="absolute bottom-0 translate-y-1 right-1">
<button
className="media-more-button p-2"

View file

@ -4,6 +4,7 @@ import { Icons } from "@/components/Icon";
import { DetailsModal } from "@/components/overlays/details/DetailsModal";
import { useModal } from "@/components/overlays/Modal";
import { usePlayerStore } from "@/stores/player/store";
import { usePreferencesStore } from "@/stores/preferences";
import { VideoPlayerButton } from "./Button";
@ -30,6 +31,14 @@ export function InfoButton() {
modal.show();
};
const enableLowPerformanceMode = usePreferencesStore(
(state) => state.enableLowPerformanceMode,
);
if (enableLowPerformanceMode) {
return null;
}
return (
<>
<VideoPlayerButton

View file

@ -413,13 +413,13 @@ function ParticlesCanvas() {
return <canvas className="particles" ref={canvasRef} />;
}
export function Lightbar(props: { className?: string }) {
export function Lightbar(props: { className?: string; noParticles?: boolean }) {
return (
<div className="absolute inset-0 w-full h-[680px] overflow-hidden pointer-events-none -mt-64">
<div className="max-w-screen w-full h-[680px] relative pt-64">
<div className={props.className}>
<div className="lightbar">
<ParticlesCanvas />
{!props.noParticles && <ParticlesCanvas />}
<div className="lightbar-visual" />
</div>
</div>

View file

@ -54,6 +54,10 @@ export function useAuthData() {
);
const setProxyTmdb = usePreferencesStore((s) => s.setProxyTmdb);
const setEnableLowPerformanceMode = usePreferencesStore(
(s) => s.setEnableLowPerformanceMode,
);
const login = useCallback(
async (
loginResponse: LoginResponse,
@ -156,6 +160,10 @@ export function useAuthData() {
if (settings.febboxKey !== undefined) {
setFebboxKey(settings.febboxKey);
}
if (settings.enableLowPerformanceMode !== undefined) {
setEnableLowPerformanceMode(settings.enableLowPerformanceMode);
}
},
[
replaceBookmarks,
@ -176,6 +184,7 @@ export function useAuthData() {
setEnableSourceOrder,
setProxyTmdb,
setFebboxKey,
setEnableLowPerformanceMode,
],
);

View file

@ -0,0 +1,16 @@
import { useEffect } from "react";
import { usePreferencesStore } from "@/stores/preferences";
export function useLowPerformanceMode() {
const setEnableLowPerformanceMode = usePreferencesStore(
(s) => s.setEnableLowPerformanceMode,
);
useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has("low-performance")) {
setEnableLowPerformanceMode(true);
}
}, [setEnableLowPerformanceMode]);
}

View file

@ -64,6 +64,7 @@ export function useSettingsState(
enableImageLogos: boolean,
enableCarouselView: boolean,
forceCompactEpisodeView: boolean,
enableLowPerformanceMode: boolean,
) {
const [proxyUrlsState, setProxyUrls, resetProxyUrls, proxyUrlsChanged] =
useDerived(proxyUrls);
@ -167,6 +168,12 @@ export function useSettingsState(
resetForceCompactEpisodeView,
forceCompactEpisodeViewChanged,
] = useDerived(forceCompactEpisodeView);
const [
enableLowPerformanceModeState,
setEnableLowPerformanceModeState,
resetEnableLowPerformanceMode,
enableLowPerformanceModeChanged,
] = useDerived(enableLowPerformanceMode);
function reset() {
resetTheme();
@ -191,6 +198,7 @@ export function useSettingsState(
resetProxyTmdb();
resetEnableCarouselView();
resetForceCompactEpisodeView();
resetEnableLowPerformanceMode();
}
const changed =
@ -214,7 +222,8 @@ export function useSettingsState(
enableSourceOrderChanged ||
proxyTmdbChanged ||
enableCarouselViewChanged ||
forceCompactEpisodeViewChanged;
forceCompactEpisodeViewChanged ||
enableLowPerformanceModeChanged;
return {
reset,
@ -324,5 +333,10 @@ export function useSettingsState(
set: setForceCompactEpisodeViewState,
changed: forceCompactEpisodeViewChanged,
},
enableLowPerformanceMode: {
state: enableLowPerformanceModeState,
set: setEnableLowPerformanceModeState,
changed: enableLowPerformanceModeChanged,
},
};
}

View file

@ -70,6 +70,9 @@ export function HomePage() {
const enableCarouselView = usePreferencesStore(
(state) => state.enableCarouselView,
);
const enableLowPerformanceMode = usePreferencesStore(
(state) => state.enableLowPerformanceMode,
);
const handleClick = (path: To) => {
window.scrollTo(0, 0);
@ -168,7 +171,8 @@ export function HomePage() {
{/* Under user content */}
<WideContainer ultraWide classNames="!px-3 md:!px-9">
{/* Empty text */}
{!(showBookmarks || showWatching) && !enableDiscover ? (
{!(showBookmarks || showWatching) &&
(!enableDiscover || enableLowPerformanceMode) ? (
<div className="flex flex-col translate-y-[-30px] items-center justify-center pt-20">
<p className="text-[18.5px] pb-3">{emptyText}</p>
</div>
@ -186,12 +190,12 @@ export function HomePage() {
{/* there... perfect. */}
{/* Discover section or discover button */}
{enableDiscover && !search ? (
{enableDiscover && !search && !enableLowPerformanceMode ? (
<DiscoverContent />
) : (
<div className="flex flex-col justify-center items-center h-40 space-y-4">
<div className="flex flex-col items-center justify-center">
{!search && (
{!search && !enableLowPerformanceMode && (
<Button
className="px-py p-[0.35em] mt-3 rounded-xl text-type-dimmed box-content text-[18px] bg-largeCard-background justify-center items-center"
onClick={() => handleClick("/discover")}

View file

@ -185,6 +185,13 @@ export function SettingsPage() {
(s) => s.setForceCompactEpisodeView,
);
const enableLowPerformanceMode = usePreferencesStore(
(s) => s.enableLowPerformanceMode,
);
const setEnableLowPerformanceMode = usePreferencesStore(
(s) => s.setEnableLowPerformanceMode,
);
const account = useAuthStore((s) => s.account);
const updateProfile = useAuthStore((s) => s.setAccountProfile);
const updateDeviceName = useAuthStore((s) => s.updateDeviceName);
@ -235,6 +242,7 @@ export function SettingsPage() {
enableImageLogos,
enableCarouselView,
forceCompactEpisodeView,
enableLowPerformanceMode,
);
const availableSources = useMemo(() => {
@ -291,7 +299,8 @@ export function SettingsPage() {
state.enableSourceOrder.changed ||
state.proxyTmdb.changed ||
state.enableCarouselView.changed ||
state.forceCompactEpisodeView.changed
state.forceCompactEpisodeView.changed ||
state.enableLowPerformanceMode.changed
) {
await updateSettings(backendUrl, account, {
applicationLanguage: state.appLanguage.state,
@ -311,6 +320,7 @@ export function SettingsPage() {
proxyTmdb: state.proxyTmdb.state,
enableCarouselView: state.enableCarouselView.state,
forceCompactEpisodeView: state.forceCompactEpisodeView.state,
enableLowPerformanceMode: state.enableLowPerformanceMode.state,
});
}
if (state.deviceName.changed) {
@ -348,6 +358,7 @@ export function SettingsPage() {
setProxyTmdb(state.proxyTmdb.state);
setEnableCarouselView(state.enableCarouselView.state);
setForceCompactEpisodeView(state.forceCompactEpisodeView.state);
setEnableLowPerformanceMode(state.enableLowPerformanceMode.state);
if (state.profile.state) {
updateProfile(state.profile.state);
@ -390,6 +401,7 @@ export function SettingsPage() {
setProxyTmdb,
setEnableCarouselView,
setForceCompactEpisodeView,
setEnableLowPerformanceMode,
]);
return (
<SubPageLayout>
@ -438,6 +450,8 @@ export function SettingsPage() {
setSourceOrder={state.sourceOrder.set}
enableSourceOrder={state.enableSourceOrder.state}
setenableSourceOrder={state.enableSourceOrder.set}
enableLowPerformanceMode={state.enableLowPerformanceMode.state}
setEnableLowPerformanceMode={state.enableLowPerformanceMode.set}
/>
</div>
<div id="settings-appearance" className="mt-28">
@ -457,6 +471,7 @@ export function SettingsPage() {
setEnableCarouselView={state.enableCarouselView.set}
forceCompactEpisodeView={state.forceCompactEpisodeView.state}
setForceCompactEpisodeView={state.forceCompactEpisodeView.set}
enableLowPerformanceMode={state.enableLowPerformanceMode.state}
/>
</div>
<div id="settings-captions" className="mt-28">

View file

@ -219,6 +219,8 @@ export function AppearancePart(props: {
forceCompactEpisodeView: boolean;
setForceCompactEpisodeView: (v: boolean) => void;
enableLowPerformanceMode: boolean;
}) {
const { t } = useTranslation();
@ -227,6 +229,33 @@ export function AppearancePart(props: {
const [isAtTop, setIsAtTop] = useState(true);
const [isAtBottom, setIsAtBottom] = useState(false);
const {
enableLowPerformanceMode,
setEnableDiscover,
setEnableFeatured,
setEnableDetailsModal,
setEnableImageLogos,
setForceCompactEpisodeView,
} = props;
// Apply low performance mode restrictions
useEffect(() => {
if (enableLowPerformanceMode) {
setEnableDiscover(false);
setEnableFeatured(false);
setEnableDetailsModal(false);
setEnableImageLogos(false);
setForceCompactEpisodeView(true);
}
}, [
enableLowPerformanceMode,
setEnableDiscover,
setEnableFeatured,
setEnableDetailsModal,
setEnableImageLogos,
setForceCompactEpisodeView,
]);
const checkScrollPosition = () => {
const container = carouselRef.current;
if (!container) return;
@ -285,13 +314,20 @@ export function AppearancePart(props: {
</p>
<div
onClick={() => {
const newDiscoverValue = !props.enableDiscover;
props.setEnableDiscover(newDiscoverValue);
if (!newDiscoverValue) {
props.setEnableFeatured(false);
if (!props.enableLowPerformanceMode) {
const newDiscoverValue = !props.enableDiscover;
props.setEnableDiscover(newDiscoverValue);
if (!newDiscoverValue) {
props.setEnableFeatured(false);
}
}
}}
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
props.enableLowPerformanceMode
? "cursor-not-allowed opacity-50 pointer-events-none"
: "cursor-pointer opacity-100 pointer-events-auto",
)}
>
<Toggle enabled={props.enableDiscover} />
<p className="flex-1 text-white font-bold">
@ -300,7 +336,7 @@ export function AppearancePart(props: {
</div>
</div>
{/* Featured Carousel */}
{props.enableDiscover && (
{props.enableDiscover && !props.enableLowPerformanceMode && (
<div className="pt-4 pl-4 border-l-8 border-dropdown-background">
<p className="text-white font-bold mb-3">
{t("settings.appearance.options.featured")}
@ -329,11 +365,14 @@ export function AppearancePart(props: {
</p>
<div
onClick={() =>
!props.enableLowPerformanceMode &&
props.setEnableDetailsModal(!props.enableDetailsModal)
}
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
"cursor-pointer opacity-100 pointer-events-auto",
props.enableLowPerformanceMode
? "cursor-not-allowed opacity-50 pointer-events-none"
: "cursor-pointer opacity-100 pointer-events-auto",
)}
>
<Toggle enabled={props.enableDetailsModal} />
@ -356,10 +395,15 @@ export function AppearancePart(props: {
{t("settings.appearance.options.logosNotice")}
</p>
<div
onClick={() => props.setEnableImageLogos(!props.enableImageLogos)}
onClick={() =>
!props.enableLowPerformanceMode &&
props.setEnableImageLogos(!props.enableImageLogos)
}
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
"cursor-pointer opacity-100 pointer-events-auto",
props.enableLowPerformanceMode
? "cursor-not-allowed opacity-50 pointer-events-none"
: "cursor-pointer opacity-100 pointer-events-auto",
)}
>
<Toggle enabled={props.enableImageLogos} />
@ -405,11 +449,14 @@ export function AppearancePart(props: {
</p>
<div
onClick={() =>
!props.enableLowPerformanceMode &&
props.setForceCompactEpisodeView(!props.forceCompactEpisodeView)
}
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
"cursor-pointer opacity-100 pointer-events-auto",
props.enableLowPerformanceMode
? "cursor-not-allowed opacity-50 pointer-events-none"
: "cursor-pointer opacity-100 pointer-events-auto",
)}
>
<Toggle enabled={props.forceCompactEpisodeView} />

View file

@ -27,6 +27,8 @@ export function PreferencesPart(props: {
setSourceOrder: (v: string[]) => void;
enableSourceOrder: boolean;
setenableSourceOrder: (v: boolean) => void;
enableLowPerformanceMode: boolean;
setEnableLowPerformanceMode: (v: boolean) => void;
}) {
const { t } = useTranslation();
const sorted = sortLangCodes(appLanguageOptions.map((item) => item.code));
@ -58,6 +60,17 @@ export function PreferencesPart(props: {
const navigate = useNavigate();
const handleLowPerformanceModeToggle = () => {
const newMode = !props.enableLowPerformanceMode;
props.setEnableLowPerformanceMode(newMode);
// When enabling low performance mode, disable bandwidth-heavy features
if (newMode) {
props.setEnableThumbnails(false);
props.setEnableAutoplay(false);
}
};
return (
<div className="space-y-12">
<Heading1 border>{t("settings.preferences.title")}</Heading1>
@ -89,8 +102,17 @@ export function PreferencesPart(props: {
{t("settings.preferences.thumbnailDescription")}
</p>
<div
onClick={() => props.setEnableThumbnails(!props.enableThumbnails)}
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
onClick={() => {
if (!props.enableLowPerformanceMode) {
props.setEnableThumbnails(!props.enableThumbnails);
}
}}
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
props.enableLowPerformanceMode
? "cursor-not-allowed opacity-50 pointer-events-none"
: "cursor-pointer opacity-100 pointer-events-auto",
)}
>
<Toggle enabled={props.enableThumbnails} />
<p className="flex-1 text-white font-bold">
@ -109,13 +131,13 @@ export function PreferencesPart(props: {
</p>
<div
onClick={() =>
allowAutoplay
allowAutoplay && !props.enableLowPerformanceMode
? props.setEnableAutoplay(!props.enableAutoplay)
: null
}
className={classNames(
"bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg",
allowAutoplay
allowAutoplay && !props.enableLowPerformanceMode
? "cursor-pointer opacity-100 pointer-events-auto"
: "cursor-not-allowed opacity-50 pointer-events-none",
)}
@ -127,27 +149,47 @@ export function PreferencesPart(props: {
</div>
{/* Skip End Credits Preference */}
{props.enableAutoplay && allowAutoplay && (
<div className="pt-4 pl-4 border-l-8 border-dropdown-background">
<p className="text-white font-bold mb-3">
{t("settings.preferences.skipCredits")}
</p>
<p className="max-w-[25rem] font-medium">
{t("settings.preferences.skipCreditsDescription")}
</p>
<div
onClick={() =>
props.setEnableSkipCredits(!props.enableSkipCredits)
}
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
>
<Toggle enabled={props.enableSkipCredits} />
<p className="flex-1 text-white font-bold">
{t("settings.preferences.skipCreditsLabel")}
{props.enableAutoplay &&
allowAutoplay &&
!props.enableLowPerformanceMode && (
<div className="pt-4 pl-4 border-l-8 border-dropdown-background">
<p className="text-white font-bold mb-3">
{t("settings.preferences.skipCredits")}
</p>
<p className="max-w-[25rem] font-medium">
{t("settings.preferences.skipCreditsDescription")}
</p>
<div
onClick={() =>
props.setEnableSkipCredits(!props.enableSkipCredits)
}
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
>
<Toggle enabled={props.enableSkipCredits} />
<p className="flex-1 text-white font-bold">
{t("settings.preferences.skipCreditsLabel")}
</p>
</div>
</div>
</div>
)}
)}
</div>
{/* Low Performance Mode */}
<div>
<p className="text-white font-bold mb-3">
{t("settings.preferences.lowPerformanceMode")}
</p>
<p className="max-w-[25rem] font-medium">
{t("settings.preferences.lowPerformanceModeDescription")}
</p>
<div
onClick={handleLowPerformanceModeToggle}
className="bg-dropdown-background hover:bg-dropdown-hoverBackground select-none my-4 cursor-pointer space-x-3 flex items-center max-w-[25rem] py-3 px-4 rounded-lg"
>
<Toggle enabled={props.enableLowPerformanceMode} />
<p className="flex-1 text-white font-bold">
{t("settings.preferences.lowPerformanceModeLabel")}
</p>
</div>
</div>
</div>

View file

@ -11,6 +11,7 @@ import {
import { convertLegacyUrl, isLegacyUrl } from "@/backend/metadata/getmeta";
import { generateQuickSearchMediaUrl } from "@/backend/metadata/tmdb";
import { useLowPerformanceMode } from "@/hooks/useLowPerformanceMode";
import { useOnlineListener } from "@/hooks/usePing";
import { AboutPage } from "@/pages/About";
import { AdminPage } from "@/pages/admin/AdminPage";
@ -98,6 +99,7 @@ export const maintenanceTime = "March 31th 11:00 PM - 5:00 AM EST";
function App() {
useHistoryListener();
useOnlineListener();
useLowPerformanceMode(); // Check for ?lp parameter in URL
const maintenance = false; // Shows maintance page
const [showDowntime, setShowDowntime] = useState(maintenance);

View file

@ -17,6 +17,7 @@ export interface PreferencesStore {
proxyTmdb: boolean;
febboxKey: string | null;
realDebridKey: string | null;
enableLowPerformanceMode: boolean;
setEnableThumbnails(v: boolean): void;
setEnableAutoplay(v: boolean): void;
@ -32,6 +33,7 @@ export interface PreferencesStore {
setProxyTmdb(v: boolean): void;
setFebboxKey(v: string | null): void;
setRealDebridKey(v: string | null): void;
setEnableLowPerformanceMode(v: boolean): void;
}
export const usePreferencesStore = create(
@ -51,6 +53,7 @@ export const usePreferencesStore = create(
proxyTmdb: false,
febboxKey: null,
realDebridKey: null,
enableLowPerformanceMode: false,
setEnableThumbnails(v) {
set((s) => {
s.enableThumbnails = v;
@ -121,6 +124,11 @@ export const usePreferencesStore = create(
s.realDebridKey = v;
});
},
setEnableLowPerformanceMode(v) {
set((s) => {
s.enableLowPerformanceMode = v;
});
},
})),
{
name: "__MW::preferences",