mirror of
https://github.com/p-stream/p-stream.git
synced 2026-01-11 20:10:32 +00:00
Update debrid key entry
This commit is contained in:
parent
a4f48b3e97
commit
0a7816ff77
11 changed files with 209 additions and 276 deletions
|
|
@ -1267,14 +1267,18 @@
|
|||
"invalid_token": "Failed to fetch a 'VIP' stream. Your token is invalid!"
|
||||
}
|
||||
},
|
||||
"realdebrid": {
|
||||
"title": "Real Debrid (Beta)",
|
||||
"description": "Enter your Real Debrid API key to access Real Debrid. Extension required.",
|
||||
"debrid": {
|
||||
"title": "Debrid (Beta)",
|
||||
"description": "Enter your Debrid API key to access Debrid services. Requires a paid <0>Real-Debrid</0> or <1>TorBox</1> account!",
|
||||
"tokenLabel": "API Key",
|
||||
"serviceOptions": {
|
||||
"realdebrid": "Real Debrid",
|
||||
"torbox": "TorBox"
|
||||
},
|
||||
"status": {
|
||||
"failure": "Failed to connect to Real Debrid. Please check your API key.",
|
||||
"api_down": "Real Debrid API is currently unavailable. Please try again later.",
|
||||
"invalid_token": "Invalid API key or non-premium account. Real Debrid requires a premium account."
|
||||
"failure": "Failed to connect to Debrid. Please check your API key.",
|
||||
"api_down": "Hmm, something went wrong. Please try again later.",
|
||||
"invalid_token": "Invalid API key or non-premium account. Debrid requires a premium account."
|
||||
}
|
||||
},
|
||||
"watchParty": {
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ export interface SettingsInput {
|
|||
defaultSubtitleLanguage?: string;
|
||||
proxyUrls?: string[] | null;
|
||||
febboxKey?: string | null;
|
||||
realDebridKey?: string | null;
|
||||
debridToken?: string | null;
|
||||
debridService?: string;
|
||||
enableThumbnails?: boolean;
|
||||
enableAutoplay?: boolean;
|
||||
enableSkipCredits?: boolean;
|
||||
|
|
@ -42,7 +43,8 @@ export interface SettingsResponse {
|
|||
defaultSubtitleLanguage?: string | null;
|
||||
proxyUrls?: string[] | null;
|
||||
febboxKey?: string | null;
|
||||
realDebridKey?: string | null;
|
||||
debridToken?: string | null;
|
||||
debridService?: string;
|
||||
enableThumbnails?: boolean;
|
||||
enableAutoplay?: boolean;
|
||||
enableSkipCredits?: boolean;
|
||||
|
|
|
|||
|
|
@ -32,7 +32,8 @@ export function useAuthData() {
|
|||
(s) => s.importSubtitleLanguage,
|
||||
);
|
||||
const setFebboxKey = usePreferencesStore((s) => s.setFebboxKey);
|
||||
const setRealDebridKey = usePreferencesStore((s) => s.setRealDebridKey);
|
||||
const setdebridToken = usePreferencesStore((s) => s.setdebridToken);
|
||||
const setdebridService = usePreferencesStore((s) => s.setdebridService);
|
||||
|
||||
const replaceBookmarks = useBookmarkStore((s) => s.replaceBookmarks);
|
||||
const replaceItems = useProgressStore((s) => s.replaceItems);
|
||||
|
|
@ -232,8 +233,12 @@ export function useAuthData() {
|
|||
setFebboxKey(settings.febboxKey);
|
||||
}
|
||||
|
||||
if (settings.realDebridKey !== undefined) {
|
||||
setRealDebridKey(settings.realDebridKey);
|
||||
if (settings.debridToken !== undefined) {
|
||||
setdebridToken(settings.debridToken);
|
||||
}
|
||||
|
||||
if (settings.debridService !== undefined) {
|
||||
setdebridService(settings.debridService);
|
||||
}
|
||||
|
||||
if (settings.enableLowPerformanceMode !== undefined) {
|
||||
|
|
@ -288,7 +293,8 @@ export function useAuthData() {
|
|||
setDisabledEmbeds,
|
||||
setProxyTmdb,
|
||||
setFebboxKey,
|
||||
setRealDebridKey,
|
||||
setdebridToken,
|
||||
setdebridService,
|
||||
setEnableLowPerformanceMode,
|
||||
setEnableNativeSubtitles,
|
||||
setEnableHoldToBoost,
|
||||
|
|
|
|||
|
|
@ -46,7 +46,8 @@ export function useSettingsState(
|
|||
proxyUrls: string[] | null,
|
||||
backendUrl: string | null,
|
||||
febboxKey: string | null,
|
||||
realDebridKey: string | null,
|
||||
debridToken: string | null,
|
||||
debridService: string,
|
||||
profile:
|
||||
| {
|
||||
colorA: string;
|
||||
|
|
@ -86,11 +87,17 @@ export function useSettingsState(
|
|||
const [febboxKeyState, setFebboxKey, resetFebboxKey, febboxKeyChanged] =
|
||||
useDerived(febboxKey);
|
||||
const [
|
||||
realDebridKeyState,
|
||||
setRealDebridKey,
|
||||
resetRealDebridKey,
|
||||
realDebridKeyChanged,
|
||||
] = useDerived(realDebridKey);
|
||||
debridTokenState,
|
||||
setdebridToken,
|
||||
resetdebridToken,
|
||||
debridTokenChanged,
|
||||
] = useDerived(debridToken);
|
||||
const [
|
||||
debridServiceState,
|
||||
setdebridService,
|
||||
_resetdebridService,
|
||||
debridServiceChanged,
|
||||
] = useDerived(debridService);
|
||||
const [themeState, setTheme, resetTheme, themeChanged] = useDerived(theme);
|
||||
const setPreviewTheme = usePreviewThemeStore((s) => s.setPreviewTheme);
|
||||
const resetPreviewTheme = useCallback(
|
||||
|
|
@ -264,7 +271,7 @@ export function useSettingsState(
|
|||
resetProxyUrls();
|
||||
resetBackendUrl();
|
||||
resetFebboxKey();
|
||||
resetRealDebridKey();
|
||||
resetdebridToken();
|
||||
resetDeviceName();
|
||||
resetNickname();
|
||||
resetProfile();
|
||||
|
|
@ -303,7 +310,7 @@ export function useSettingsState(
|
|||
backendUrlChanged ||
|
||||
proxyUrlsChanged ||
|
||||
febboxKeyChanged ||
|
||||
realDebridKeyChanged ||
|
||||
debridTokenChanged ||
|
||||
profileChanged ||
|
||||
enableThumbnailsChanged ||
|
||||
enableAutoplayChanged ||
|
||||
|
|
@ -373,10 +380,15 @@ export function useSettingsState(
|
|||
set: setFebboxKey,
|
||||
changed: febboxKeyChanged,
|
||||
},
|
||||
realDebridKey: {
|
||||
state: realDebridKeyState,
|
||||
set: setRealDebridKey,
|
||||
changed: realDebridKeyChanged,
|
||||
debridToken: {
|
||||
state: debridTokenState,
|
||||
set: setdebridToken,
|
||||
changed: debridTokenChanged,
|
||||
},
|
||||
debridService: {
|
||||
state: debridServiceState,
|
||||
set: setdebridService,
|
||||
changed: debridServiceChanged,
|
||||
},
|
||||
profile: {
|
||||
state: profileState,
|
||||
|
|
|
|||
|
|
@ -369,8 +369,10 @@ export function SettingsPage() {
|
|||
const febboxKey = usePreferencesStore((s) => s.febboxKey);
|
||||
const setFebboxKey = usePreferencesStore((s) => s.setFebboxKey);
|
||||
|
||||
const realDebridKey = usePreferencesStore((s) => s.realDebridKey);
|
||||
const setRealDebridKey = usePreferencesStore((s) => s.setRealDebridKey);
|
||||
const debridToken = usePreferencesStore((s) => s.debridToken);
|
||||
const setdebridToken = usePreferencesStore((s) => s.setdebridToken);
|
||||
const debridService = usePreferencesStore((s) => s.debridService);
|
||||
const setdebridService = usePreferencesStore((s) => s.setdebridService);
|
||||
|
||||
const enableThumbnails = usePreferencesStore((s) => s.enableThumbnails);
|
||||
const setEnableThumbnails = usePreferencesStore((s) => s.setEnableThumbnails);
|
||||
|
|
@ -511,13 +513,16 @@ export function SettingsPage() {
|
|||
if (settings.febboxKey) {
|
||||
setFebboxKey(settings.febboxKey);
|
||||
}
|
||||
if (settings.realDebridKey) {
|
||||
setRealDebridKey(settings.realDebridKey);
|
||||
if (settings.debridToken) {
|
||||
setdebridToken(settings.debridToken);
|
||||
}
|
||||
if (settings.debridService) {
|
||||
setdebridService(settings.debridService);
|
||||
}
|
||||
}
|
||||
};
|
||||
loadSettings();
|
||||
}, [account, backendUrl, setFebboxKey, setRealDebridKey]);
|
||||
}, [account, backendUrl, setFebboxKey, setdebridToken, setdebridService]);
|
||||
|
||||
const state = useSettingsState(
|
||||
activeTheme,
|
||||
|
|
@ -528,7 +533,8 @@ export function SettingsPage() {
|
|||
proxySet,
|
||||
backendUrlSetting,
|
||||
febboxKey,
|
||||
realDebridKey,
|
||||
debridToken,
|
||||
debridService,
|
||||
account ? account.profile : undefined,
|
||||
enableThumbnails,
|
||||
enableAutoplay,
|
||||
|
|
@ -598,7 +604,8 @@ export function SettingsPage() {
|
|||
state.theme.changed ||
|
||||
state.proxyUrls.changed ||
|
||||
state.febboxKey.changed ||
|
||||
state.realDebridKey.changed ||
|
||||
state.debridToken.changed ||
|
||||
state.debridService.changed ||
|
||||
state.enableThumbnails.changed ||
|
||||
state.enableAutoplay.changed ||
|
||||
state.enableSkipCredits.changed ||
|
||||
|
|
@ -625,7 +632,8 @@ export function SettingsPage() {
|
|||
applicationTheme: state.theme.state,
|
||||
proxyUrls: state.proxyUrls.state?.filter((v) => v !== "") ?? null,
|
||||
febboxKey: state.febboxKey.state,
|
||||
realDebridKey: state.realDebridKey.state,
|
||||
debridToken: state.debridToken.state,
|
||||
debridService: state.debridService.state,
|
||||
enableThumbnails: state.enableThumbnails.state,
|
||||
enableAutoplay: state.enableAutoplay.state,
|
||||
enableSkipCredits: state.enableSkipCredits.state,
|
||||
|
|
@ -690,7 +698,8 @@ export function SettingsPage() {
|
|||
setProxySet(state.proxyUrls.state?.filter((v) => v !== "") ?? null);
|
||||
setEnableSourceOrder(state.enableSourceOrder.state);
|
||||
setFebboxKey(state.febboxKey.state);
|
||||
setRealDebridKey(state.realDebridKey.state);
|
||||
setdebridToken(state.debridToken.state);
|
||||
setdebridService(state.debridService.state);
|
||||
setProxyTmdb(state.proxyTmdb.state);
|
||||
setEnableCarouselView(state.enableCarouselView.state);
|
||||
setForceCompactEpisodeView(state.forceCompactEpisodeView.state);
|
||||
|
|
@ -720,7 +729,8 @@ export function SettingsPage() {
|
|||
backendUrl,
|
||||
setEnableThumbnails,
|
||||
setFebboxKey,
|
||||
setRealDebridKey,
|
||||
setdebridToken,
|
||||
setdebridService,
|
||||
state,
|
||||
setEnableAutoplay,
|
||||
setEnableSkipCredits,
|
||||
|
|
@ -881,8 +891,10 @@ export function SettingsPage() {
|
|||
setProxyUrls={state.proxyUrls.set}
|
||||
febboxKey={state.febboxKey.state}
|
||||
setFebboxKey={state.febboxKey.set}
|
||||
realDebridKey={state.realDebridKey.state}
|
||||
setRealDebridKey={state.realDebridKey.set}
|
||||
debridToken={state.debridToken.state}
|
||||
setdebridToken={state.debridToken.set}
|
||||
debridService={state.debridService.state}
|
||||
setdebridService={state.debridService.set}
|
||||
proxyTmdb={state.proxyTmdb.state}
|
||||
setProxyTmdb={state.proxyTmdb.set}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -1,10 +1,7 @@
|
|||
import { useEffect, useState } from "react";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Toggle } from "@/components/buttons/Toggle";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { SettingsCard } from "@/components/layout/SettingsCard";
|
||||
import { Stepper } from "@/components/layout/Stepper";
|
||||
import { BiggerCenterContainer } from "@/components/layout/ThinContainer";
|
||||
import { VerticalLine } from "@/components/layout/VerticalLine";
|
||||
|
|
@ -14,11 +11,6 @@ import {
|
|||
ModalCard,
|
||||
useModal,
|
||||
} from "@/components/overlays/Modal";
|
||||
import {
|
||||
StatusCircle,
|
||||
StatusCircleProps,
|
||||
} from "@/components/player/internals/StatusCircle";
|
||||
import { AuthInputBox } from "@/components/text-inputs/AuthInputBox";
|
||||
import { Divider } from "@/components/utils/Divider";
|
||||
import { Ol } from "@/components/utils/Ol";
|
||||
import {
|
||||
|
|
@ -43,133 +35,7 @@ import { conf } from "@/setup/config";
|
|||
import { usePreferencesStore } from "@/stores/preferences";
|
||||
import { getProxyUrls } from "@/utils/proxyUrls";
|
||||
|
||||
import { FebboxSetup } from "../parts/settings/ConnectionsPart";
|
||||
import { Status, testRealDebridKey } from "../parts/settings/SetupPart";
|
||||
|
||||
async function getRealDebridKeyStatus(realDebridKey: string | null) {
|
||||
if (realDebridKey) {
|
||||
const status: Status = await testRealDebridKey(realDebridKey);
|
||||
return status;
|
||||
}
|
||||
return "unset";
|
||||
}
|
||||
|
||||
export function RealDebridSetup() {
|
||||
const { t } = useTranslation();
|
||||
const realDebridKey = usePreferencesStore((s) => s.realDebridKey);
|
||||
const setRealDebridKey = usePreferencesStore((s) => s.setRealDebridKey);
|
||||
|
||||
// Initialize isExpanded based on whether realDebridKey has a value
|
||||
const [isExpanded, setIsExpanded] = useState(
|
||||
realDebridKey !== null && realDebridKey !== "",
|
||||
);
|
||||
|
||||
// Add a separate effect to set the initial state
|
||||
useEffect(() => {
|
||||
// If we have a valid key, make sure the section is expanded
|
||||
if (realDebridKey && realDebridKey.length > 0) {
|
||||
setIsExpanded(true);
|
||||
}
|
||||
}, [realDebridKey]);
|
||||
|
||||
const [status, setStatus] = useState<Status>("unset");
|
||||
const statusMap: Record<Status, StatusCircleProps["type"]> = {
|
||||
error: "error",
|
||||
success: "success",
|
||||
unset: "noresult",
|
||||
api_down: "error",
|
||||
invalid_token: "error",
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const checkTokenStatus = async () => {
|
||||
const result = await getRealDebridKeyStatus(realDebridKey);
|
||||
setStatus(result);
|
||||
};
|
||||
checkTokenStatus();
|
||||
}, [realDebridKey]);
|
||||
|
||||
// Toggle handler that preserves the key
|
||||
const toggleExpanded = () => {
|
||||
if (isExpanded) {
|
||||
// Store the key temporarily instead of setting to null
|
||||
setRealDebridKey("");
|
||||
setIsExpanded(false);
|
||||
} else {
|
||||
setIsExpanded(true);
|
||||
}
|
||||
};
|
||||
|
||||
if (conf().ALLOW_REAL_DEBRID_KEY) {
|
||||
return (
|
||||
<div className="mt-6">
|
||||
<SettingsCard>
|
||||
<div className="flex justify-between items-center gap-4">
|
||||
<div className="my-3">
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("settings.connections.realdebrid.title", "Real Debrid API")}
|
||||
</p>
|
||||
<p className="max-w-[30rem] font-medium">
|
||||
{t(
|
||||
"settings.connections.realdebrid.description",
|
||||
"Enter your Real Debrid API key to access premium sources.",
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<Toggle onClick={toggleExpanded} enabled={isExpanded} />
|
||||
</div>
|
||||
</div>
|
||||
{isExpanded ? (
|
||||
<>
|
||||
<Divider marginClass="my-6 px-8 box-content -mx-8" />
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("settings.connections.realdebrid.tokenLabel", "API Key")}
|
||||
</p>
|
||||
<div className="flex items-center w-full">
|
||||
<StatusCircle type={statusMap[status]} className="mx-2 mr-4" />
|
||||
<AuthInputBox
|
||||
onChange={(newToken) => {
|
||||
setRealDebridKey(newToken);
|
||||
}}
|
||||
value={realDebridKey ?? ""}
|
||||
placeholder="API Key"
|
||||
passwordToggleable
|
||||
className="flex-grow"
|
||||
/>
|
||||
</div>
|
||||
{status === "error" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t(
|
||||
"settings.connections.realdebrid.status.failure",
|
||||
"Failed to connect to Real Debrid. Please check your API key.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{status === "api_down" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t(
|
||||
"settings.connections.realdebrid.status.api_down",
|
||||
"Real Debrid API is currently unavailable. Please try again later.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
{status === "invalid_token" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t(
|
||||
"settings.connections.realdebrid.status.invalid_token",
|
||||
"Invalid API key or non-premium account. Real Debrid requires a premium account.",
|
||||
)}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
</SettingsCard>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
import { DebridEdit, FebboxSetup } from "../parts/settings/ConnectionsPart";
|
||||
|
||||
function Item(props: { title: string; children: React.ReactNode }) {
|
||||
return (
|
||||
|
|
@ -419,7 +285,6 @@ export function OnboardingPage() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
{/* <RealDebridSetup /> */}
|
||||
<div className="mt-6">
|
||||
<FebboxSetup
|
||||
febboxKey={usePreferencesStore((s) => s.febboxKey)}
|
||||
|
|
@ -427,6 +292,14 @@ export function OnboardingPage() {
|
|||
mode="onboarding"
|
||||
/>
|
||||
</div>
|
||||
<div className="mt-6">
|
||||
<DebridEdit
|
||||
debridToken={usePreferencesStore((s) => s.debridToken)}
|
||||
setdebridToken={usePreferencesStore((s) => s.setdebridToken)}
|
||||
debridService={usePreferencesStore((s) => s.debridService)}
|
||||
setdebridService={usePreferencesStore((s) => s.setdebridService)}
|
||||
/>
|
||||
</div>
|
||||
</BiggerCenterContainer>
|
||||
</MinimalPageLayout>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ export function VerifyPassphrase(props: VerifyPassphraseProps) {
|
|||
disabledEmbeds: store.disabledEmbeds,
|
||||
proxyTmdb: store.proxyTmdb,
|
||||
febboxKey: store.febboxKey,
|
||||
realDebridKey: store.realDebridKey,
|
||||
debridToken: store.debridToken,
|
||||
debridService: store.debridService,
|
||||
enableLowPerformanceMode: store.enableLowPerformanceMode,
|
||||
enableNativeSubtitles: store.enableNativeSubtitles,
|
||||
enableHoldToBoost: store.enableHoldToBoost,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { Trans, useTranslation } from "react-i18next";
|
|||
|
||||
import { Button } from "@/components/buttons/Button";
|
||||
import { Toggle } from "@/components/buttons/Toggle";
|
||||
import { Dropdown } from "@/components/form/Dropdown";
|
||||
import { Icon, Icons } from "@/components/Icon";
|
||||
import { SettingsCard } from "@/components/layout/SettingsCard";
|
||||
import { Modal, ModalCard, useModal } from "@/components/overlays/Modal";
|
||||
|
|
@ -24,7 +25,7 @@ import {
|
|||
SetupPart,
|
||||
Status,
|
||||
testFebboxKey,
|
||||
testRealDebridKey,
|
||||
testdebridToken,
|
||||
} from "@/pages/parts/settings/SetupPart";
|
||||
import { conf } from "@/setup/config";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
|
|
@ -49,9 +50,11 @@ interface FebboxKeyProps {
|
|||
setFebboxKey: (value: string | null) => void;
|
||||
}
|
||||
|
||||
interface RealDebridKeyProps {
|
||||
realDebridKey: string | null;
|
||||
setRealDebridKey: Dispatch<SetStateAction<string | null>>;
|
||||
interface DebridProps {
|
||||
debridToken: string | null;
|
||||
setdebridToken: (value: string | null) => void;
|
||||
debridService: string;
|
||||
setdebridService: (value: string) => void;
|
||||
}
|
||||
|
||||
function ProxyEdit({
|
||||
|
|
@ -460,33 +463,30 @@ export function FebboxSetup({
|
|||
}
|
||||
}
|
||||
|
||||
async function getRealDebridKeyStatus(realDebridKey: string | null) {
|
||||
if (realDebridKey) {
|
||||
const status: Status = await testRealDebridKey(realDebridKey);
|
||||
async function getdebridTokenStatus(debridToken: string | null) {
|
||||
if (debridToken) {
|
||||
const status: Status = await testdebridToken(debridToken);
|
||||
return status;
|
||||
}
|
||||
return "unset";
|
||||
}
|
||||
|
||||
function RealDebridKeyEdit({
|
||||
realDebridKey,
|
||||
setRealDebridKey,
|
||||
}: RealDebridKeyProps) {
|
||||
export function DebridEdit({
|
||||
debridToken,
|
||||
setdebridToken,
|
||||
debridService,
|
||||
setdebridService,
|
||||
}: DebridProps) {
|
||||
const { t } = useTranslation();
|
||||
const user = useAuthStore();
|
||||
const preferences = usePreferencesStore();
|
||||
|
||||
// Enable Real Debrid token when account is loaded and we have a token
|
||||
useEffect(() => {
|
||||
if (user.account && realDebridKey === null && preferences.realDebridKey) {
|
||||
setRealDebridKey(preferences.realDebridKey);
|
||||
if (user.account && debridToken === null && preferences.debridToken) {
|
||||
setdebridToken(preferences.debridToken);
|
||||
}
|
||||
}, [
|
||||
user.account,
|
||||
realDebridKey,
|
||||
preferences.realDebridKey,
|
||||
setRealDebridKey,
|
||||
]);
|
||||
}, [user.account, debridToken, preferences.debridToken, setdebridToken]);
|
||||
|
||||
const [status, setStatus] = useState<Status>("unset");
|
||||
const statusMap: Record<Status, StatusCircleProps["type"]> = {
|
||||
|
|
@ -499,73 +499,78 @@ function RealDebridKeyEdit({
|
|||
|
||||
useEffect(() => {
|
||||
const checkTokenStatus = async () => {
|
||||
const result = await getRealDebridKeyStatus(realDebridKey);
|
||||
const result = await getdebridTokenStatus(debridToken);
|
||||
setStatus(result);
|
||||
};
|
||||
checkTokenStatus();
|
||||
}, [realDebridKey]);
|
||||
}, [debridToken]);
|
||||
|
||||
if (conf().ALLOW_REAL_DEBRID_KEY) {
|
||||
if (conf().ALLOW_DEBRID_KEY) {
|
||||
return (
|
||||
<SettingsCard>
|
||||
<div className="flex justify-between items-center gap-4">
|
||||
<div className="my-3">
|
||||
<p className="text-white font-bold mb-3">{t("realdebrid.title")}</p>
|
||||
<p className="max-w-[30rem] font-medium">
|
||||
{t("realdebrid.description")}
|
||||
</p>
|
||||
<MwLink>
|
||||
<a
|
||||
href="https://real-debrid.com/"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
>
|
||||
real-debrid.com
|
||||
</a>
|
||||
</MwLink>
|
||||
<p className="text-white font-bold mb-3">{t("debrid.title")}</p>
|
||||
<Trans i18nKey="debrid.description">
|
||||
<MwLink to="https://real-debrid.com/" />
|
||||
{/* fifth's referral code */}
|
||||
<MwLink to="https://torbox.app/subscription?referral=3f665ece-0405-4012-9db7-c6f90e8567e1" />
|
||||
</Trans>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<Toggle
|
||||
onClick={() => setRealDebridKey((s) => (s === null ? "" : null))}
|
||||
enabled={realDebridKey !== null}
|
||||
onClick={() => setdebridToken(debridToken === null ? "" : null)}
|
||||
enabled={debridToken !== null}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{realDebridKey !== null ? (
|
||||
<>
|
||||
<Divider marginClass="my-6 px-8 box-content -mx-8" />
|
||||
<p className="text-white font-bold mb-3">
|
||||
{t("realdebrid.tokenLabel")}
|
||||
</p>
|
||||
<div className="flex items-center w-full">
|
||||
<StatusCircle type={statusMap[status]} className="mx-2 mr-4" />
|
||||
<AuthInputBox
|
||||
onChange={(newToken) => {
|
||||
setRealDebridKey(newToken);
|
||||
}}
|
||||
value={realDebridKey ?? ""}
|
||||
placeholder="ABC123..."
|
||||
passwordToggleable
|
||||
className="flex-grow"
|
||||
/>
|
||||
</div>
|
||||
{status === "error" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t("realdebrid.status.failure")}
|
||||
</p>
|
||||
)}
|
||||
{status === "api_down" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t("realdebrid.status.api_down")}
|
||||
</p>
|
||||
)}
|
||||
{status === "invalid_token" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t("realdebrid.status.invalid_token")}
|
||||
</p>
|
||||
)}
|
||||
</>
|
||||
) : null}
|
||||
<Divider marginClass="my-6 px-8 box-content -mx-8" />
|
||||
<p className="text-white font-bold mb-3">{t("debrid.tokenLabel")}</p>
|
||||
<div className="flex md:flex-row flex-col items-center w-full gap-4">
|
||||
<div className="flex items-center w-full">
|
||||
<StatusCircle type={statusMap[status]} className="mx-2 mr-4" />
|
||||
<AuthInputBox
|
||||
onChange={(newToken) => {
|
||||
setdebridToken(newToken);
|
||||
}}
|
||||
value={debridToken ?? ""}
|
||||
placeholder="ABC123..."
|
||||
passwordToggleable
|
||||
className="flex-grow"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<Dropdown
|
||||
options={[
|
||||
{
|
||||
id: "realdebrid",
|
||||
name: t("debrid.serviceOptions.realdebrid"),
|
||||
},
|
||||
{
|
||||
id: "torbox",
|
||||
name: t("debrid.serviceOptions.torbox"),
|
||||
},
|
||||
]}
|
||||
selectedItem={{
|
||||
id: debridService,
|
||||
name: t(`debrid.serviceOptions.${debridService}`),
|
||||
}}
|
||||
setSelectedItem={(item) => setdebridService(item.id)}
|
||||
direction="up"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{status === "error" && (
|
||||
<p className="text-type-danger mt-4">{t("debrid.status.failure")}</p>
|
||||
)}
|
||||
{status === "api_down" && (
|
||||
<p className="text-type-danger mt-4">{t("debrid.status.api_down")}</p>
|
||||
)}
|
||||
{status === "invalid_token" && (
|
||||
<p className="text-type-danger mt-4">
|
||||
{t("debrid.status.invalid_token")}
|
||||
</p>
|
||||
)}
|
||||
</SettingsCard>
|
||||
);
|
||||
}
|
||||
|
|
@ -573,10 +578,7 @@ function RealDebridKeyEdit({
|
|||
}
|
||||
|
||||
export function ConnectionsPart(
|
||||
props: BackendEditProps &
|
||||
ProxyEditProps &
|
||||
FebboxKeyProps &
|
||||
RealDebridKeyProps,
|
||||
props: BackendEditProps & ProxyEditProps & FebboxKeyProps & DebridProps,
|
||||
) {
|
||||
const { t } = useTranslation();
|
||||
return (
|
||||
|
|
@ -594,15 +596,17 @@ export function ConnectionsPart(
|
|||
backendUrl={props.backendUrl}
|
||||
setBackendUrl={props.setBackendUrl}
|
||||
/>
|
||||
<RealDebridKeyEdit
|
||||
realDebridKey={props.realDebridKey}
|
||||
setRealDebridKey={props.setRealDebridKey}
|
||||
/>
|
||||
<FebboxSetup
|
||||
febboxKey={props.febboxKey}
|
||||
setFebboxKey={props.setFebboxKey}
|
||||
mode="settings"
|
||||
/>
|
||||
<DebridEdit
|
||||
debridToken={props.debridToken}
|
||||
setdebridToken={props.setdebridToken}
|
||||
debridService={props.debridService}
|
||||
setdebridService={props.setdebridService}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ type SetupData = {
|
|||
proxy: Status;
|
||||
defaultProxy: Status;
|
||||
febboxKeyTest?: Status;
|
||||
realDebridKeyTest?: Status;
|
||||
debridTokenTest?: Status;
|
||||
};
|
||||
|
||||
function testProxy(url: string) {
|
||||
|
|
@ -142,10 +142,10 @@ export async function testFebboxKey(febboxKey: string | null): Promise<Status> {
|
|||
return "api_down";
|
||||
}
|
||||
|
||||
export async function testRealDebridKey(
|
||||
realDebridKey: string | null,
|
||||
export async function testdebridToken(
|
||||
debridToken: string | null,
|
||||
): Promise<Status> {
|
||||
if (!realDebridKey) {
|
||||
if (!debridToken) {
|
||||
return "unset";
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +160,7 @@ export async function testRealDebridKey(
|
|||
{
|
||||
method: "GET",
|
||||
headers: {
|
||||
Authorization: `Bearer ${realDebridKey}`,
|
||||
Authorization: `Bearer ${debridToken}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
},
|
||||
|
|
@ -191,10 +191,21 @@ export async function testRealDebridKey(
|
|||
return "api_down";
|
||||
}
|
||||
|
||||
export async function testTorboxToken(
|
||||
torboxToken: string | null,
|
||||
): Promise<Status> {
|
||||
if (!torboxToken) {
|
||||
return "unset";
|
||||
}
|
||||
|
||||
// TODO: Implement Torbox token test
|
||||
return "success";
|
||||
}
|
||||
|
||||
function useIsSetup() {
|
||||
const proxyUrls = useAuthStore((s) => s.proxySet);
|
||||
const febboxKey = usePreferencesStore((s) => s.febboxKey);
|
||||
const realDebridKey = usePreferencesStore((s) => s.realDebridKey);
|
||||
const debridToken = usePreferencesStore((s) => s.debridToken);
|
||||
const { loading, value } = useAsync(async (): Promise<SetupData> => {
|
||||
const extensionStatus: Status = (await isExtensionActive())
|
||||
? "success"
|
||||
|
|
@ -210,7 +221,7 @@ function useIsSetup() {
|
|||
}
|
||||
|
||||
const febboxKeyStatus: Status = await testFebboxKey(febboxKey);
|
||||
const realDebridKeyStatus: Status = await testRealDebridKey(realDebridKey);
|
||||
const debridTokenStatus: Status = await testdebridToken(debridToken);
|
||||
|
||||
return {
|
||||
extension: extensionStatus,
|
||||
|
|
@ -219,23 +230,23 @@ function useIsSetup() {
|
|||
...(conf().ALLOW_FEBBOX_KEY && {
|
||||
febboxKeyTest: febboxKeyStatus,
|
||||
}),
|
||||
realDebridKeyTest: realDebridKeyStatus,
|
||||
debridTokenTest: debridTokenStatus,
|
||||
};
|
||||
}, [proxyUrls, febboxKey, realDebridKey]);
|
||||
}, [proxyUrls, febboxKey, debridToken]);
|
||||
|
||||
let globalState: Status = "unset";
|
||||
if (
|
||||
value?.extension === "success" ||
|
||||
value?.proxy === "success" ||
|
||||
value?.febboxKeyTest === "success" ||
|
||||
value?.realDebridKeyTest === "success"
|
||||
value?.debridTokenTest === "success"
|
||||
)
|
||||
globalState = "success";
|
||||
if (
|
||||
value?.proxy === "error" ||
|
||||
value?.extension === "error" ||
|
||||
value?.febboxKeyTest === "error" ||
|
||||
value?.realDebridKeyTest === "error"
|
||||
value?.debridTokenTest === "error"
|
||||
)
|
||||
globalState = "error";
|
||||
|
||||
|
|
@ -375,9 +386,9 @@ export function SetupPart() {
|
|||
>
|
||||
{t("settings.connections.setup.items.default")}
|
||||
</SetupCheckList>
|
||||
{conf().ALLOW_REAL_DEBRID_KEY && (
|
||||
<SetupCheckList status={setupStates.realDebridKeyTest || "unset"}>
|
||||
Real Debrid token
|
||||
{conf().ALLOW_DEBRID_KEY && (
|
||||
<SetupCheckList status={setupStates.debridTokenTest || "unset"}>
|
||||
Debrid Service
|
||||
</SetupCheckList>
|
||||
)}
|
||||
{conf().ALLOW_FEBBOX_KEY && (
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ interface Config {
|
|||
ONBOARDING_PROXY_INSTALL_LINK: string;
|
||||
ALLOW_AUTOPLAY: boolean;
|
||||
ALLOW_FEBBOX_KEY: boolean;
|
||||
ALLOW_REAL_DEBRID_KEY: boolean;
|
||||
ALLOW_DEBRID_KEY: boolean;
|
||||
SHOW_AD: boolean;
|
||||
AD_CONTENT_URL: string;
|
||||
TRACK_SCRIPT: string; // like <script src="https://umami.com/script.js"></script>
|
||||
|
|
@ -42,7 +42,7 @@ export interface RuntimeConfig {
|
|||
DMCA_EMAIL: string | null;
|
||||
TWITTER_LINK: string;
|
||||
TMDB_READ_API_KEY: string | null;
|
||||
ALLOW_REAL_DEBRID_KEY: boolean;
|
||||
ALLOW_DEBRID_KEY: boolean;
|
||||
NORMAL_ROUTER: boolean;
|
||||
PROXY_URLS: string[];
|
||||
M3U8_PROXY_URLS: string[];
|
||||
|
|
@ -87,7 +87,7 @@ const env: Record<keyof Config, undefined | string> = {
|
|||
HAS_ONBOARDING: import.meta.env.VITE_HAS_ONBOARDING,
|
||||
ALLOW_AUTOPLAY: import.meta.env.VITE_ALLOW_AUTOPLAY,
|
||||
ALLOW_FEBBOX_KEY: import.meta.env.VITE_ALLOW_FEBBOX_KEY,
|
||||
ALLOW_REAL_DEBRID_KEY: import.meta.env.VITE_ALLOW_REAL_DEBRID_KEY,
|
||||
ALLOW_DEBRID_KEY: import.meta.env.VITE_ALLOW_DEBRID_KEY,
|
||||
SHOW_AD: import.meta.env.VITE_SHOW_AD,
|
||||
AD_CONTENT_URL: import.meta.env.VITE_AD_CONTENT_URL,
|
||||
TRACK_SCRIPT: import.meta.env.VITE_TRACK_SCRIPT,
|
||||
|
|
@ -159,7 +159,7 @@ export function conf(): RuntimeConfig {
|
|||
)
|
||||
.filter((v) => v.length === 2), // The format is <beforeA>:<afterA>,<beforeB>:<afterB>
|
||||
ALLOW_FEBBOX_KEY: getKey("ALLOW_FEBBOX_KEY", "false") === "true",
|
||||
ALLOW_REAL_DEBRID_KEY: getKey("ALLOW_REAL_DEBRID_KEY", "false") === "true",
|
||||
ALLOW_DEBRID_KEY: getKey("ALLOW_DEBRID_KEY", "false") === "true",
|
||||
SHOW_AD: getKey("SHOW_AD", "false") === "true",
|
||||
AD_CONTENT_URL: getKey("AD_CONTENT_URL", "")
|
||||
.split(",")
|
||||
|
|
|
|||
|
|
@ -22,7 +22,8 @@ export interface PreferencesStore {
|
|||
disabledEmbeds: string[];
|
||||
proxyTmdb: boolean;
|
||||
febboxKey: string | null;
|
||||
realDebridKey: string | null;
|
||||
debridToken: string | null;
|
||||
debridService: string;
|
||||
enableLowPerformanceMode: boolean;
|
||||
enableNativeSubtitles: boolean;
|
||||
enableHoldToBoost: boolean;
|
||||
|
|
@ -49,7 +50,8 @@ export interface PreferencesStore {
|
|||
setDisabledEmbeds(v: string[]): void;
|
||||
setProxyTmdb(v: boolean): void;
|
||||
setFebboxKey(v: string | null): void;
|
||||
setRealDebridKey(v: string | null): void;
|
||||
setdebridToken(v: string | null): void;
|
||||
setdebridService(v: string): void;
|
||||
setEnableLowPerformanceMode(v: boolean): void;
|
||||
setEnableNativeSubtitles(v: boolean): void;
|
||||
setEnableHoldToBoost(v: boolean): void;
|
||||
|
|
@ -80,7 +82,8 @@ export const usePreferencesStore = create(
|
|||
disabledEmbeds: [],
|
||||
proxyTmdb: false,
|
||||
febboxKey: null,
|
||||
realDebridKey: null,
|
||||
debridToken: null,
|
||||
debridService: "realdebrid",
|
||||
enableLowPerformanceMode: false,
|
||||
enableNativeSubtitles: false,
|
||||
enableHoldToBoost: true,
|
||||
|
|
@ -182,9 +185,14 @@ export const usePreferencesStore = create(
|
|||
s.febboxKey = v;
|
||||
});
|
||||
},
|
||||
setRealDebridKey(v) {
|
||||
setdebridToken(v) {
|
||||
set((s) => {
|
||||
s.realDebridKey = v;
|
||||
s.debridToken = v;
|
||||
});
|
||||
},
|
||||
setdebridService(v) {
|
||||
set((s) => {
|
||||
s.debridService = v;
|
||||
});
|
||||
},
|
||||
setEnableLowPerformanceMode(v) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue