- {!search && (
+ {!search && !enableLowPerformanceMode && (
handleClick("/discover")}
diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx
index 273fc1fc..5dfb172d 100644
--- a/src/pages/Settings.tsx
+++ b/src/pages/Settings.tsx
@@ -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 (
@@ -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}
/>
@@ -457,6 +471,7 @@ export function SettingsPage() {
setEnableCarouselView={state.enableCarouselView.set}
forceCompactEpisodeView={state.forceCompactEpisodeView.state}
setForceCompactEpisodeView={state.forceCompactEpisodeView.set}
+ enableLowPerformanceMode={state.enableLowPerformanceMode.state}
/>
diff --git a/src/pages/parts/settings/AppearancePart.tsx b/src/pages/parts/settings/AppearancePart.tsx
index 78dbf882..e7645d6e 100644
--- a/src/pages/parts/settings/AppearancePart.tsx
+++ b/src/pages/parts/settings/AppearancePart.tsx
@@ -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: {
{
- 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",
+ )}
>
@@ -300,7 +336,7 @@ export function AppearancePart(props: {
{/* Featured Carousel */}
- {props.enableDiscover && (
+ {props.enableDiscover && !props.enableLowPerformanceMode && (
{t("settings.appearance.options.featured")}
@@ -329,11 +365,14 @@ export function AppearancePart(props: {
+ !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",
)}
>
@@ -356,10 +395,15 @@ export function AppearancePart(props: {
{t("settings.appearance.options.logosNotice")}
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",
)}
>
@@ -405,11 +449,14 @@ export function AppearancePart(props: {
+ !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",
)}
>
diff --git a/src/pages/parts/settings/PreferencesPart.tsx b/src/pages/parts/settings/PreferencesPart.tsx
index 6a6f90ef..17c74497 100644
--- a/src/pages/parts/settings/PreferencesPart.tsx
+++ b/src/pages/parts/settings/PreferencesPart.tsx
@@ -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 (
{t("settings.preferences.title")}
@@ -89,8 +102,17 @@ export function PreferencesPart(props: {
{t("settings.preferences.thumbnailDescription")}
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",
+ )}
>
@@ -109,13 +131,13 @@ export function PreferencesPart(props: {
- 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: {
{/* Skip End Credits Preference */}
- {props.enableAutoplay && allowAutoplay && (
-
-
- {t("settings.preferences.skipCredits")}
-
-
- {t("settings.preferences.skipCreditsDescription")}
-
-
- 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"
- >
-
-
- {t("settings.preferences.skipCreditsLabel")}
+ {props.enableAutoplay &&
+ allowAutoplay &&
+ !props.enableLowPerformanceMode && (
+
+
+ {t("settings.preferences.skipCredits")}
+
+ {t("settings.preferences.skipCreditsDescription")}
+
+
+ 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"
+ >
+
+
+ {t("settings.preferences.skipCreditsLabel")}
+
+
-
- )}
+ )}
+
+ {/* Low Performance Mode */}
+
+
+ {t("settings.preferences.lowPerformanceMode")}
+
+
+ {t("settings.preferences.lowPerformanceModeDescription")}
+
+
+
+
+ {t("settings.preferences.lowPerformanceModeLabel")}
+
+
diff --git a/src/setup/App.tsx b/src/setup/App.tsx
index 601f94b8..8d754c01 100644
--- a/src/setup/App.tsx
+++ b/src/setup/App.tsx
@@ -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);
diff --git a/src/stores/preferences/index.tsx b/src/stores/preferences/index.tsx
index f470b777..60387c15 100644
--- a/src/stores/preferences/index.tsx
+++ b/src/stores/preferences/index.tsx
@@ -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",