mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-05-31 04:04:21 -04:00
Add unauthorized guard for the admin panel
This commit is contained in:
parent
81131edf2d
commit
1fb3088f0e
23
front/apps/mobile/app/(app)/admin/index.tsx
Normal file
23
front/apps/mobile/app/(app)/admin/index.tsx
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AdminPage } from "@kyoo/ui";
|
||||||
|
|
||||||
|
export default AdminPage;
|
@ -24,7 +24,8 @@ import { StatusBar, StatusBarProps } from "react-native";
|
|||||||
import * as ScreenOrientation from "expo-screen-orientation";
|
import * as ScreenOrientation from "expo-screen-orientation";
|
||||||
import * as NavigationBar from "expo-navigation-bar";
|
import * as NavigationBar from "expo-navigation-bar";
|
||||||
import arrayShuffle from "array-shuffle";
|
import arrayShuffle from "array-shuffle";
|
||||||
import { QueryPage } from "@kyoo/models";
|
import { QueryPage, useHasPermission } from "@kyoo/models";
|
||||||
|
import { Unauthorized } from "@kyoo/ui";
|
||||||
|
|
||||||
const FullscreenProvider = () => {
|
const FullscreenProvider = () => {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -49,6 +50,11 @@ export const withRoute = <Props,>(
|
|||||||
const { statusBar, fullscreen, ...routeOptions } = options ?? {};
|
const { statusBar, fullscreen, ...routeOptions } = options ?? {};
|
||||||
const WithUseRoute = (props: any) => {
|
const WithUseRoute = (props: any) => {
|
||||||
const routeParams = useLocalSearchParams();
|
const routeParams = useLocalSearchParams();
|
||||||
|
const hasPermissions = useHasPermission((Component as QueryPage).requiredPermissions ?? []);
|
||||||
|
|
||||||
|
if (!hasPermissions)
|
||||||
|
return <Unauthorized missing={(Component as QueryPage).requiredPermissions!} />;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{routeOptions && <Stack.Screen {...routeOptions} />}
|
{routeOptions && <Stack.Screen {...routeOptions} />}
|
||||||
|
24
front/apps/web/src/pages/admin/index.tsx
Normal file
24
front/apps/web/src/pages/admin/index.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AdminPage } from "@kyoo/ui";
|
||||||
|
import { withRoute } from "~/router";
|
||||||
|
|
||||||
|
export default withRoute(AdminPage);
|
@ -18,6 +18,8 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { QueryPage, useHasPermission } from "@kyoo/models";
|
||||||
|
import { Unauthorized } from "@kyoo/ui";
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from "next/router";
|
||||||
import { ComponentType } from "react";
|
import { ComponentType } from "react";
|
||||||
|
|
||||||
@ -27,7 +29,10 @@ export const withRoute = <Props,>(
|
|||||||
) => {
|
) => {
|
||||||
const WithUseRoute = (props: Props) => {
|
const WithUseRoute = (props: Props) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const hasPermissions = useHasPermission((Component as QueryPage).requiredPermissions ?? []);
|
||||||
|
|
||||||
|
if (!hasPermissions)
|
||||||
|
return <Unauthorized missing={(Component as QueryPage).requiredPermissions!} />;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return <Component {...defaultProps} {...router.query} {...props} />;
|
return <Component {...defaultProps} {...router.query} {...props} />;
|
||||||
};
|
};
|
||||||
|
@ -158,9 +158,11 @@ export const useAccounts = () => {
|
|||||||
return useContext(AccountContext);
|
return useContext(AccountContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHasPermission = (...perms: string[]) => {
|
export const useHasPermission = (perms?: string[]) => {
|
||||||
const account = useAccount();
|
const account = useAccount();
|
||||||
|
|
||||||
|
if (!perms) return true;
|
||||||
|
|
||||||
// TODO: Read permission of guest account here.
|
// TODO: Read permission of guest account here.
|
||||||
if (!account) return false;
|
if (!account) return false;
|
||||||
return perms.every((perm) => account.permissions.includes(perm));
|
return perms.every((perm) => account.permissions.includes(perm));
|
||||||
|
@ -183,6 +183,7 @@ export type QueryPage<Props = {}, Items = unknown> = ComponentType<
|
|||||||
getLayout?:
|
getLayout?:
|
||||||
| QueryPage<{ page: ReactElement }>
|
| QueryPage<{ page: ReactElement }>
|
||||||
| { Layout: QueryPage<{ page: ReactElement }>; props: object };
|
| { Layout: QueryPage<{ page: ReactElement }>; props: object };
|
||||||
|
requiredPermissions?: string[]
|
||||||
randomItems?: Items[];
|
randomItems?: Items[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
35
front/packages/ui/src/admin/index.tsx
Normal file
35
front/packages/ui/src/admin/index.tsx
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { QueryPage } from "@kyoo/models";
|
||||||
|
import { P, ts } from "@kyoo/primitives";
|
||||||
|
import { ScrollView } from "react-native";
|
||||||
|
import { DefaultLayout } from "../layout";
|
||||||
|
|
||||||
|
export const AdminPage: QueryPage = () => {
|
||||||
|
return (
|
||||||
|
<ScrollView contentContainerStyle={{ gap: ts(4), paddingBottom: ts(4) }}>
|
||||||
|
<P>hbgen</P>
|
||||||
|
</ScrollView>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AdminPage.getLayout = DefaultLayout;
|
||||||
|
AdminPage.requiredPermissions = ["admin.read"];
|
@ -28,7 +28,7 @@ import {
|
|||||||
import { Container, H2, ImageBackground, Link, P, focusReset, ts } from "@kyoo/primitives";
|
import { Container, H2, ImageBackground, Link, P, focusReset, ts } from "@kyoo/primitives";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Theme, useYoshiki } from "yoshiki/native";
|
import { Theme, useYoshiki } from "yoshiki/native";
|
||||||
import { ErrorView } from "../fetch";
|
import { ErrorView } from "../errors";
|
||||||
|
|
||||||
export const PartOf = ({
|
export const PartOf = ({
|
||||||
name,
|
name,
|
||||||
|
46
front/packages/ui/src/errors/error.tsx
Normal file
46
front/packages/ui/src/errors/error.tsx
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { KyooErrors } from "@kyoo/models";
|
||||||
|
import { P } from "@kyoo/primitives";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
|
export const ErrorView = ({ error }: { error: KyooErrors }) => {
|
||||||
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
{...css({
|
||||||
|
backgroundColor: (theme) => theme.colors.red,
|
||||||
|
flexGrow: 1,
|
||||||
|
flexShrink: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{error.errors.map((x, i) => (
|
||||||
|
<P key={i} {...css({ color: (theme) => theme.colors.white })}>
|
||||||
|
{x}
|
||||||
|
</P>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
22
front/packages/ui/src/errors/index.tsx
Normal file
22
front/packages/ui/src/errors/index.tsx
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from "./error";
|
||||||
|
export * from "./unauthorized";
|
42
front/packages/ui/src/errors/unauthorized.tsx
Normal file
42
front/packages/ui/src/errors/unauthorized.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Kyoo - A portable and vast media library solution.
|
||||||
|
* Copyright (c) Kyoo.
|
||||||
|
*
|
||||||
|
* See AUTHORS.md and LICENSE file in the project root for full license information.
|
||||||
|
*
|
||||||
|
* Kyoo is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* Kyoo is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { P } from "@kyoo/primitives";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
|
export const Unauthorized = ({ missing }: { missing: string[] }) => {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
{...css({
|
||||||
|
flexGrow: 1,
|
||||||
|
flexShrink: 1,
|
||||||
|
justifyContent: "center",
|
||||||
|
alignItems: "center",
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<P>{t("errors.unauthorized", { permission: missing.join(", ") })}</P>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
@ -22,7 +22,8 @@ import { Page, QueryIdentifier, useInfiniteFetch } from "@kyoo/models";
|
|||||||
import { useBreakpointMap, HR } from "@kyoo/primitives";
|
import { useBreakpointMap, HR } from "@kyoo/primitives";
|
||||||
import { ContentStyle, FlashList } from "@shopify/flash-list";
|
import { ContentStyle, FlashList } from "@shopify/flash-list";
|
||||||
import { ComponentProps, ComponentType, isValidElement, ReactElement, useRef } from "react";
|
import { ComponentProps, ComponentType, isValidElement, ReactElement, useRef } from "react";
|
||||||
import { EmptyView, ErrorView, Layout, OfflineView, WithLoading, addHeader } from "./fetch";
|
import { EmptyView, Layout, OfflineView, WithLoading, addHeader } from "./fetch";
|
||||||
|
import { ErrorView } from "./errors";
|
||||||
import { FlatList, View, ViewStyle } from "react-native";
|
import { FlatList, View, ViewStyle } from "react-native";
|
||||||
|
|
||||||
const emulateGap = (
|
const emulateGap = (
|
||||||
|
@ -31,7 +31,8 @@ import {
|
|||||||
useRef,
|
useRef,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Stylable, nativeStyleToCss, useYoshiki, ysMap } from "yoshiki";
|
import { Stylable, nativeStyleToCss, useYoshiki, ysMap } from "yoshiki";
|
||||||
import { EmptyView, ErrorView, Layout, WithLoading, addHeader } from "./fetch";
|
import { EmptyView, Layout, WithLoading, addHeader } from "./fetch";
|
||||||
|
import { ErrorView } from "./errors";
|
||||||
import type { ContentStyle } from "@shopify/flash-list";
|
import type { ContentStyle } from "@shopify/flash-list";
|
||||||
|
|
||||||
const InfiniteScroll = <Props,>({
|
const InfiniteScroll = <Props,>({
|
||||||
|
@ -18,12 +18,13 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
import { Page, QueryIdentifier, useFetch } from "@kyoo/models";
|
||||||
import { Breakpoint, P } from "@kyoo/primitives";
|
import { Breakpoint, P } from "@kyoo/primitives";
|
||||||
import { ComponentType, ReactElement, isValidElement } from "react";
|
import { ComponentType, ReactElement, isValidElement } from "react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { View } from "react-native";
|
import { View } from "react-native";
|
||||||
import { useYoshiki } from "yoshiki/native";
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
import { ErrorView } from "./errors";
|
||||||
|
|
||||||
export type Layout = {
|
export type Layout = {
|
||||||
numColumns: Breakpoint<number>;
|
numColumns: Breakpoint<number>;
|
||||||
@ -84,28 +85,6 @@ export const OfflineView = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ErrorView = ({ error }: { error: KyooErrors }) => {
|
|
||||||
const { css } = useYoshiki();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
{...css({
|
|
||||||
backgroundColor: (theme) => theme.colors.red,
|
|
||||||
flexGrow: 1,
|
|
||||||
flexShrink: 1,
|
|
||||||
justifyContent: "center",
|
|
||||||
alignItems: "center",
|
|
||||||
})}
|
|
||||||
>
|
|
||||||
{error.errors.map((x, i) => (
|
|
||||||
<P key={i} {...css({ color: (theme) => theme.colors.white })}>
|
|
||||||
{x}
|
|
||||||
</P>
|
|
||||||
))}
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const EmptyView = ({ message }: { message: string }) => {
|
export const EmptyView = ({ message }: { message: string }) => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
@ -28,3 +28,5 @@ export { SearchPage } from "./search";
|
|||||||
export { LoginPage, RegisterPage } from "./login";
|
export { LoginPage, RegisterPage } from "./login";
|
||||||
export { DownloadPage, DownloadProvider } from "./downloads";
|
export { DownloadPage, DownloadProvider } from "./downloads";
|
||||||
export { SettingsPage } from "./settings";
|
export { SettingsPage } from "./settings";
|
||||||
|
export { AdminPage } from "./admin";
|
||||||
|
export * from "./errors";
|
||||||
|
@ -44,6 +44,7 @@ import Admin from "@material-symbols/svg-400/rounded/admin_panel_settings.svg";
|
|||||||
import Settings from "@material-symbols/svg-400/rounded/settings.svg";
|
import Settings from "@material-symbols/svg-400/rounded/settings.svg";
|
||||||
import { KyooLongLogo } from "./icon";
|
import { KyooLongLogo } from "./icon";
|
||||||
import { forwardRef, useEffect, useRef, useState } from "react";
|
import { forwardRef, useEffect, useRef, useState } from "react";
|
||||||
|
import { AdminPage } from "../admin";
|
||||||
|
|
||||||
export const NavbarTitle = (props: Stylable & { onLayout?: ViewProps["onLayout"] }) => {
|
export const NavbarTitle = (props: Stylable & { onLayout?: ViewProps["onLayout"] }) => {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
@ -139,7 +140,7 @@ export const NavbarRight = () => {
|
|||||||
const { css, theme } = useYoshiki();
|
const { css, theme } = useYoshiki();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
const isAdmin = useHasPermission("admin.read");
|
const isAdmin = useHasPermission(AdminPage.requiredPermissions);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View {...css({ flexDirection: "row", alignItems: "center", flexShrink: 1 })}>
|
<View {...css({ flexDirection: "row", alignItems: "center", flexShrink: 1 })}>
|
||||||
|
@ -22,12 +22,12 @@ import { useFetch, QueryIdentifier, imageFn, Chapter } from "@kyoo/models";
|
|||||||
import { Sprite, P, imageBorderRadius, ts } from "@kyoo/primitives";
|
import { Sprite, P, imageBorderRadius, ts } from "@kyoo/primitives";
|
||||||
import { View, Platform } from "react-native";
|
import { View, Platform } from "react-native";
|
||||||
import { percent, useYoshiki, px, Theme, useForceRerender } from "yoshiki/native";
|
import { percent, useYoshiki, px, Theme, useForceRerender } from "yoshiki/native";
|
||||||
import { ErrorView } from "../../fetch";
|
|
||||||
import { useMemo } from "react";
|
import { useMemo } from "react";
|
||||||
import { useAtomValue } from "jotai";
|
import { useAtomValue } from "jotai";
|
||||||
import { durationAtom } from "../state";
|
import { durationAtom } from "../state";
|
||||||
import { toTimerString } from "./left-buttons";
|
import { toTimerString } from "./left-buttons";
|
||||||
import { seekProgressAtom } from "./hover";
|
import { seekProgressAtom } from "./hover";
|
||||||
|
import { ErrorView } from "../../errors";
|
||||||
|
|
||||||
type Thumb = {
|
type Thumb = {
|
||||||
from: number;
|
from: number;
|
||||||
|
@ -40,8 +40,8 @@ import { fullscreenAtom, Video } from "./state";
|
|||||||
import { episodeDisplayNumber } from "../details/episode";
|
import { episodeDisplayNumber } from "../details/episode";
|
||||||
import { useVideoKeyboard } from "./keyboard";
|
import { useVideoKeyboard } from "./keyboard";
|
||||||
import { MediaSessionManager } from "./media-session";
|
import { MediaSessionManager } from "./media-session";
|
||||||
import { ErrorView } from "../fetch";
|
|
||||||
import { WatchStatusObserver } from "./watch-status-observer";
|
import { WatchStatusObserver } from "./watch-status-observer";
|
||||||
|
import { ErrorView } from "../errors";
|
||||||
|
|
||||||
type Item = (Movie & { type: "movie" }) | (Episode & { type: "episode" });
|
type Item = (Movie & { type: "movie" }) | (Episode & { type: "episode" });
|
||||||
|
|
||||||
@ -66,8 +66,6 @@ const mapData = (
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
let firstSlug: string | null = null;
|
|
||||||
|
|
||||||
export const Player = ({
|
export const Player = ({
|
||||||
slug,
|
slug,
|
||||||
type,
|
type,
|
||||||
|
@ -189,11 +189,12 @@
|
|||||||
},
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"connection": "Could not connect to the kyoo's server",
|
"connection": "Could not connect to the kyoo's server",
|
||||||
"connection-tips": "Troublshotting tips:\n - Are you connected to internet?\n - Is your kyoo's server online?\n - Have your account been banned?",
|
"connection-tips": "Troubleshooting tips:\n - Are you connected to internet?\n - Is your kyoo's server online?\n - Have your account been banned?",
|
||||||
"unknown": "Unknown error",
|
"unknown": "Unknown error",
|
||||||
"try-again": "Try again",
|
"try-again": "Try again",
|
||||||
"re-login": "Re login",
|
"re-login": "Re login",
|
||||||
"offline": "You are not connected to internet. Try again later."
|
"offline": "You are not connected to internet. Try again later.",
|
||||||
|
"unauthorized": "You are missing the permissions {{permission}} to access this page."
|
||||||
},
|
},
|
||||||
"mediainfo": {
|
"mediainfo": {
|
||||||
"file": "File",
|
"file": "File",
|
||||||
|
@ -193,7 +193,8 @@
|
|||||||
"unknown": "Erreur inconnue",
|
"unknown": "Erreur inconnue",
|
||||||
"try-again": "Réessayer",
|
"try-again": "Réessayer",
|
||||||
"re-login": "Se reconnecter",
|
"re-login": "Se reconnecter",
|
||||||
"offline": "Vous n'êtes pas connecté à Internet. Réessayez plus tard."
|
"offline": "Vous n'êtes pas connecté à Internet. Réessayez plus tard.",
|
||||||
|
"unauthorized": "Il vous manque les autorisations {{permission}} pour accéder à cette page."
|
||||||
},
|
},
|
||||||
"mediainfo": {
|
"mediainfo": {
|
||||||
"file": "Fichier",
|
"file": "Fichier",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user