mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-07-09 03:04:20 -04:00
Merge pull request #129 from AnonymusRaccoon/feat/models
Add a model package and a fetch component
This commit is contained in:
commit
ceaafc495d
@ -8,6 +8,7 @@ COPY apps/web/package.json apps/web/package.json
|
|||||||
COPY apps/mobile/package.json apps/mobile/package.json
|
COPY apps/mobile/package.json apps/mobile/package.json
|
||||||
COPY packages/ui/package.json packages/ui/package.json
|
COPY packages/ui/package.json packages/ui/package.json
|
||||||
COPY packages/primitives/package.json packages/primitives/package.json
|
COPY packages/primitives/package.json packages/primitives/package.json
|
||||||
|
COPY packages/models/package.json packages/models/package.json
|
||||||
RUN yarn --immutable
|
RUN yarn --immutable
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
|
@ -8,6 +8,7 @@ COPY apps/web/package.json apps/web/package.json
|
|||||||
COPY apps/mobile/package.json apps/mobile/package.json
|
COPY apps/mobile/package.json apps/mobile/package.json
|
||||||
COPY packages/ui/package.json packages/ui/package.json
|
COPY packages/ui/package.json packages/ui/package.json
|
||||||
COPY packages/primitives/package.json packages/primitives/package.json
|
COPY packages/primitives/package.json packages/primitives/package.json
|
||||||
|
COPY packages/models/package.json packages/models/package.json
|
||||||
RUN yarn --immutable
|
RUN yarn --immutable
|
||||||
|
|
||||||
ENV NEXT_TELEMETRY_DISABLED 1
|
ENV NEXT_TELEMETRY_DISABLED 1
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"slug": "kyoo",
|
"slug": "kyoo",
|
||||||
"scheme": "kyoo",
|
"scheme": "kyoo",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"orientation": "portrait",
|
"orientation": "default",
|
||||||
"icon": "./assets/icon.png",
|
"icon": "./assets/icon.png",
|
||||||
"entryPoint": "./index.ts",
|
"entryPoint": "./index.ts",
|
||||||
"userInterfaceStyle": "light",
|
"userInterfaceStyle": "light",
|
||||||
|
@ -22,6 +22,9 @@ import { Stack } from "expo-router";
|
|||||||
import { Avatar, ThemeSelector } from "@kyoo/primitives";
|
import { Avatar, ThemeSelector } from "@kyoo/primitives";
|
||||||
import { useTheme } from "yoshiki/native";
|
import { useTheme } from "yoshiki/native";
|
||||||
import { NavbarTitle } from "@kyoo/ui";
|
import { NavbarTitle } from "@kyoo/ui";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import { createQueryClient } from "@kyoo/models";
|
||||||
|
|
||||||
const ThemedStack = () => {
|
const ThemedStack = () => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -44,9 +47,13 @@ const ThemedStack = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default function Root() {
|
export default function Root() {
|
||||||
|
const [queryClient] = useState(() => createQueryClient());
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
<ThemeSelector>
|
<ThemeSelector>
|
||||||
<ThemedStack />
|
<ThemedStack />
|
||||||
</ThemeSelector>
|
</ThemeSelector>
|
||||||
|
</QueryClientProvider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { Navbar } from "@kyoo/ui";
|
||||||
import { Text, View } from "react-native";
|
import { Text, View } from "react-native";
|
||||||
import { useYoshiki } from "yoshiki/native";
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
@ -26,7 +27,7 @@ const App = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<View {...css({ backgroundColor: (theme) => theme.background })}>
|
<View {...css({ backgroundColor: (theme) => theme.background })}>
|
||||||
{/* <Navbar /> */}
|
<Navbar />
|
||||||
<Text>toto</Text>
|
<Text>toto</Text>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,23 @@
|
|||||||
// Learn more https://docs.expo.dev/guides/monorepos
|
/*
|
||||||
|
* 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/>.
|
||||||
|
*/
|
||||||
|
|
||||||
const { getDefaultConfig } = require("expo/metro-config");
|
const { getDefaultConfig } = require("expo/metro-config");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
|
|
||||||
|
@ -81,6 +81,7 @@ const nextConfig = {
|
|||||||
transpilePackages: [
|
transpilePackages: [
|
||||||
"@kyoo/ui",
|
"@kyoo/ui",
|
||||||
"@kyoo/primitives",
|
"@kyoo/primitives",
|
||||||
|
"@kyoo/models",
|
||||||
"solito",
|
"solito",
|
||||||
"react-native",
|
"react-native",
|
||||||
"react-native-web",
|
"react-native-web",
|
||||||
|
@ -14,12 +14,12 @@
|
|||||||
"@emotion/react": "^11.9.3",
|
"@emotion/react": "^11.9.3",
|
||||||
"@emotion/styled": "^11.9.3",
|
"@emotion/styled": "^11.9.3",
|
||||||
"@jellyfin/libass-wasm": "^4.1.1",
|
"@jellyfin/libass-wasm": "^4.1.1",
|
||||||
|
"@kyoo/models": "workspace:^",
|
||||||
"@kyoo/primitives": "workspace:^",
|
"@kyoo/primitives": "workspace:^",
|
||||||
"@kyoo/ui": "workspace:^",
|
"@kyoo/ui": "workspace:^",
|
||||||
"@mui/icons-material": "^5.8.4",
|
"@mui/icons-material": "^5.8.4",
|
||||||
"@mui/material": "^5.8.7",
|
"@mui/material": "^5.8.7",
|
||||||
"@mui/system": "^5.10.10",
|
"@mui/system": "^5.10.10",
|
||||||
"@tanstack/react-query": "^4.18.0",
|
|
||||||
"clsx": "^1.2.1",
|
"clsx": "^1.2.1",
|
||||||
"csstype": "^3.1.1",
|
"csstype": "^3.1.1",
|
||||||
"hls.js": "^1.2.8",
|
"hls.js": "^1.2.8",
|
||||||
|
@ -18,16 +18,4 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
export * from "@kyoo/models";
|
||||||
|
|
||||||
export const zdate = () => {
|
|
||||||
return z.preprocess((arg) => {
|
|
||||||
if (arg instanceof Date) return arg;
|
|
||||||
|
|
||||||
if (typeof arg === "string" && /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?/.test(arg)) {
|
|
||||||
return new Date(arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
}, z.date());
|
|
||||||
};
|
|
@ -24,7 +24,7 @@ import { useTheme, useMobileHover } from "yoshiki/web";
|
|||||||
import { createTheme, ThemeProvider as MTheme } from "@mui/material";
|
import { createTheme, ThemeProvider as MTheme } from "@mui/material";
|
||||||
import NextApp, { AppContext, type AppProps } from "next/app";
|
import NextApp, { AppContext, type AppProps } from "next/app";
|
||||||
import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
|
import { Hydrate, QueryClientProvider } from "@tanstack/react-query";
|
||||||
import { createQueryClient, fetchQuery, QueryIdentifier, QueryPage } from "~/utils/query";
|
import { createQueryClient, fetchQuery, QueryIdentifier, QueryPage } from "@kyoo/models";
|
||||||
import superjson from "superjson";
|
import superjson from "superjson";
|
||||||
import Head from "next/head";
|
import Head from "next/head";
|
||||||
import { ThemeSelector as KThemeSelector } from "@kyoo/primitives";
|
import { ThemeSelector as KThemeSelector } from "@kyoo/primitives";
|
||||||
|
@ -39,11 +39,11 @@ import { ErrorPage } from "~/components/errors";
|
|||||||
import { Navbar } from "@kyoo/ui";
|
import { Navbar } from "@kyoo/ui";
|
||||||
import { Poster, Image } from "@kyoo/primitives";
|
import { Poster, Image } from "@kyoo/primitives";
|
||||||
import { ItemType, LibraryItem, LibraryItemP } from "~/models";
|
import { ItemType, LibraryItem, LibraryItemP } from "~/models";
|
||||||
import { getDisplayDate } from "~/models/utils";
|
import { getDisplayDate } from "@kyoo/models";
|
||||||
import { InfiniteScroll } from "~/utils/infinite-scroll";
|
import { InfiniteScroll } from "~/utils/infinite-scroll";
|
||||||
import { Link } from "~/utils/link";
|
import { Link } from "~/utils/link";
|
||||||
import { withRoute } from "~/utils/router";
|
import { withRoute } from "~/utils/router";
|
||||||
import { QueryIdentifier, QueryPage, useInfiniteFetch } from "~/utils/query";
|
import { QueryIdentifier, QueryPage, useInfiniteFetch } from "@kyoo/models";
|
||||||
import { px } from "yoshiki/native";
|
import { px } from "yoshiki/native";
|
||||||
|
|
||||||
enum SortBy {
|
enum SortBy {
|
||||||
|
23
front/packages/models/package.json
Normal file
23
front/packages/models/package.json
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"name": "@kyoo/models",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"types": "src/index.ts",
|
||||||
|
"packageManager": "yarn@3.2.4",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/react": "^18.0.25",
|
||||||
|
"typescript": "^4.9.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "*",
|
||||||
|
"react-native": "*"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-native-web": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@tanstack/react-query": "^4.18.0",
|
||||||
|
"zod": "^3.19.1"
|
||||||
|
}
|
||||||
|
}
|
@ -18,7 +18,10 @@
|
|||||||
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
* along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
export * from "./resources";
|
||||||
|
export * from "./traits";
|
||||||
export * from "./page";
|
export * from "./page";
|
||||||
export * from "./kyoo-errors";
|
export * from "./kyoo-errors";
|
||||||
export * from "./traits";
|
export * from "./utils"
|
||||||
export * from "./resources";
|
|
||||||
|
export * from "./query";
|
@ -27,10 +27,10 @@ import {
|
|||||||
useQuery,
|
useQuery,
|
||||||
} from "@tanstack/react-query";
|
} from "@tanstack/react-query";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { KyooErrors, Page } from "~/models";
|
import { KyooErrors } from "./kyoo-errors";
|
||||||
import { Paged } from "~/models/page";
|
import { Page, Paged } from "./page";
|
||||||
|
|
||||||
const queryFn = async <Data>(
|
const queryFn = async <Data,>(
|
||||||
type: z.ZodType<Data>,
|
type: z.ZodType<Data>,
|
||||||
context: QueryFunctionContext,
|
context: QueryFunctionContext,
|
||||||
): Promise<Data> => {
|
): Promise<Data> => {
|
||||||
@ -104,13 +104,13 @@ export type QueryPage<Props = {}> = ComponentType<Props> & {
|
|||||||
getLayout?: (page: ReactElement) => ReactNode;
|
getLayout?: (page: ReactElement) => ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
const toQueryKey = <Data>(query: QueryIdentifier<Data>) => {
|
const toQueryKey = <Data,>(query: QueryIdentifier<Data>) => {
|
||||||
if (query.params) {
|
if (query.params) {
|
||||||
return [
|
return [
|
||||||
...query.path,
|
...query.path,
|
||||||
"?" +
|
"?" +
|
||||||
Object.entries(query.params)
|
Object.entries(query.params)
|
||||||
.filter(([k, v]) => v !== undefined)
|
.filter(([_, v]) => v !== undefined)
|
||||||
.map(([k, v]) => `${k}=${Array.isArray(v) ? v.join(",") : v}`)
|
.map(([k, v]) => `${k}=${Array.isArray(v) ? v.join(",") : v}`)
|
||||||
.join("&"),
|
.join("&"),
|
||||||
];
|
];
|
||||||
@ -119,14 +119,14 @@ const toQueryKey = <Data>(query: QueryIdentifier<Data>) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useFetch = <Data>(query: QueryIdentifier<Data>) => {
|
export const useFetch = <Data,>(query: QueryIdentifier<Data>) => {
|
||||||
return useQuery<Data, KyooErrors>({
|
return useQuery<Data, KyooErrors>({
|
||||||
queryKey: toQueryKey(query),
|
queryKey: toQueryKey(query),
|
||||||
queryFn: (ctx) => queryFn(query.parser, ctx),
|
queryFn: (ctx) => queryFn(query.parser, ctx),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useInfiniteFetch = <Data>(query: QueryIdentifier<Data>) => {
|
export const useInfiniteFetch = <Data,>(query: QueryIdentifier<Data>) => {
|
||||||
const ret = useInfiniteQuery<Page<Data>, KyooErrors>({
|
const ret = useInfiniteQuery<Page<Data>, KyooErrors>({
|
||||||
queryKey: toQueryKey(query),
|
queryKey: toQueryKey(query),
|
||||||
queryFn: (ctx) => queryFn(Paged(query.parser), ctx),
|
queryFn: (ctx) => queryFn(Paged(query.parser), ctx),
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "~/utils/zod";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP } from "../traits";
|
import { ImagesP } from "../traits";
|
||||||
import { ResourceP } from "../traits/resource";
|
import { ResourceP } from "../traits/resource";
|
||||||
|
|
@ -34,7 +34,7 @@ export enum ItemType {
|
|||||||
|
|
||||||
export const LibraryItemP = z.preprocess(
|
export const LibraryItemP = z.preprocess(
|
||||||
(x: any) => {
|
(x: any) => {
|
||||||
x.aliases ??= [];
|
if (!x.aliases) x.aliases = [];
|
||||||
return x;
|
return x;
|
||||||
},
|
},
|
||||||
z.union([
|
z.union([
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "~/utils/zod";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP, ResourceP } from "../traits";
|
import { ImagesP, ResourceP } from "../traits";
|
||||||
import { GenreP } from "./genre";
|
import { GenreP } from "./genre";
|
||||||
import { StudioP } from "./studio";
|
import { StudioP } from "./studio";
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "~/utils/zod";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP } from "../traits";
|
import { ImagesP } from "../traits";
|
||||||
import { ResourceP } from "../traits/resource";
|
import { ResourceP } from "../traits/resource";
|
||||||
|
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "~/utils/zod";
|
import { zdate } from "../utils";
|
||||||
import { ImagesP, ResourceP } from "../traits";
|
import { ImagesP, ResourceP } from "../traits";
|
||||||
import { GenreP } from "./genre";
|
import { GenreP } from "./genre";
|
||||||
import { SeasonP } from "./season";
|
import { SeasonP } from "./season";
|
@ -19,7 +19,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { zdate } from "~/utils/zod";
|
import { zdate } from "../utils";
|
||||||
import { ResourceP, ImagesP, imageFn } from "../traits";
|
import { ResourceP, ImagesP, imageFn } from "../traits";
|
||||||
import { EpisodeP } from "./episode";
|
import { EpisodeP } from "./episode";
|
||||||
|
|
@ -19,6 +19,19 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Movie, Show } from "./resources";
|
import { Movie, Show } from "./resources";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export const zdate = () => {
|
||||||
|
return z.preprocess((arg) => {
|
||||||
|
if (arg instanceof Date) return arg;
|
||||||
|
|
||||||
|
if (typeof arg === "string" && /\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z?/.test(arg)) {
|
||||||
|
return new Date(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}, z.date());
|
||||||
|
};
|
||||||
|
|
||||||
export const getDisplayDate = (data: Show | Movie) => {
|
export const getDisplayDate = (data: Show | Movie) => {
|
||||||
const {
|
const {
|
26
front/packages/models/tsconfig.json
Executable file
26
front/packages/models/tsconfig.json
Executable file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es5",
|
||||||
|
"lib": ["dom", "dom.iterable", "esnext"],
|
||||||
|
"declaration": true,
|
||||||
|
"sourceMap": true,
|
||||||
|
"noEmit": true,
|
||||||
|
"allowJs": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"module": "esnext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"isolatedModules": true,
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"incremental": true,
|
||||||
|
"baseUrl": ".",
|
||||||
|
"paths": {
|
||||||
|
"~/*": ["src/*"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"include": ["**/*.ts", "**/*.tsx"],
|
||||||
|
"exclude": ["node_modules"]
|
||||||
|
}
|
@ -20,6 +20,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@expo/html-elements": "^0.2.2",
|
"@expo/html-elements": "^0.2.2",
|
||||||
"@expo/vector-icons": "AnonymusRaccoon/expo-vector-icons#no-prepare",
|
"@expo/vector-icons": "AnonymusRaccoon/expo-vector-icons#no-prepare",
|
||||||
|
"@tanstack/react-query": "^4.18.0",
|
||||||
"solito": "^2.0.5"
|
"solito": "^2.0.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,12 +20,14 @@
|
|||||||
|
|
||||||
import { ThemeBuilder } from "./theme";
|
import { ThemeBuilder } from "./theme";
|
||||||
|
|
||||||
|
// Ref: https://github.com/catppuccin/catppuccin
|
||||||
export const catppuccin: ThemeBuilder = {
|
export const catppuccin: ThemeBuilder = {
|
||||||
fonts: {
|
fonts: {
|
||||||
heading: "Pacifico",
|
heading: "Pacifico",
|
||||||
paragraph: "Poppins",
|
paragraph: "Poppins",
|
||||||
},
|
},
|
||||||
light: {
|
light: {
|
||||||
|
// Catppuccin latte
|
||||||
appbar: "#e64553",
|
appbar: "#e64553",
|
||||||
contrast: "#cdd6f4",
|
contrast: "#cdd6f4",
|
||||||
subcontrast: "#bac2de",
|
subcontrast: "#bac2de",
|
||||||
@ -45,8 +47,17 @@ export const catppuccin: ThemeBuilder = {
|
|||||||
paragraph: "#5c5f77",
|
paragraph: "#5c5f77",
|
||||||
subtext: "#6c6f85",
|
subtext: "#6c6f85",
|
||||||
},
|
},
|
||||||
|
colors: {
|
||||||
|
red: "#d20f39",
|
||||||
|
green: "#40a02b",
|
||||||
|
blue: "#1e66f5",
|
||||||
|
yellow: "#df8e1d",
|
||||||
|
black: "#4c4f69",
|
||||||
|
white: "#eff1f5",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
dark: {
|
dark: {
|
||||||
|
// Catppuccin mocha
|
||||||
appbar: "#94e2d5",
|
appbar: "#94e2d5",
|
||||||
contrast: "#cdd6f4",
|
contrast: "#cdd6f4",
|
||||||
subcontrast: "#bac2de",
|
subcontrast: "#bac2de",
|
||||||
@ -66,5 +77,13 @@ export const catppuccin: ThemeBuilder = {
|
|||||||
paragraph: "#bac2de",
|
paragraph: "#bac2de",
|
||||||
subtext: "#a6adc8",
|
subtext: "#a6adc8",
|
||||||
},
|
},
|
||||||
|
colors: {
|
||||||
|
red: "#f38ba8",
|
||||||
|
green: "#a6e3a1",
|
||||||
|
blue: "#89b4fa",
|
||||||
|
yellow: "#f9e2af",
|
||||||
|
black: "#11111b",
|
||||||
|
white: "#cdd6f4",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -39,6 +39,14 @@ type Mode = {
|
|||||||
contrast: Property.Color;
|
contrast: Property.Color;
|
||||||
subcontrast: Property.Color;
|
subcontrast: Property.Color;
|
||||||
variant: Variant;
|
variant: Variant;
|
||||||
|
colors: {
|
||||||
|
red: Property.Color,
|
||||||
|
green: Property.Color,
|
||||||
|
blue: Property.Color,
|
||||||
|
yellow: Property.Color,
|
||||||
|
white: Property.Color,
|
||||||
|
black: Property.Color,
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
type Variant = {
|
type Variant = {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react-native",
|
"jsx": "react-jsx",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"packageManager": "yarn@3.2.4",
|
"packageManager": "yarn@3.2.4",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@kyoo/models": "workspace:^",
|
||||||
"@kyoo/primitives": "workspace:^",
|
"@kyoo/primitives": "workspace:^",
|
||||||
"react-native-svg": "^13.6.0"
|
"react-native-svg": "^13.6.0"
|
||||||
},
|
},
|
||||||
|
73
front/packages/ui/src/fetch.tsx
Normal file
73
front/packages/ui/src/fetch.tsx
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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 { Page, QueryIdentifier, useFetch, KyooErrors } from "@kyoo/models";
|
||||||
|
import { P } from "@kyoo/primitives";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
|
||||||
|
export type WithLoading<Item> = (Item & { isLoading: false }) | { isLoading: true };
|
||||||
|
|
||||||
|
const isPage = <T = unknown,>(obj: unknown): obj is Page<T> =>
|
||||||
|
(typeof obj === "object" && obj && "items" in obj) || false;
|
||||||
|
|
||||||
|
export const Fetch = <Data,>({
|
||||||
|
query,
|
||||||
|
placeholderCount,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
query: QueryIdentifier<Data>;
|
||||||
|
placeholderCount: number;
|
||||||
|
children: (
|
||||||
|
item: Data extends Page<infer Item> ? WithLoading<Item> : WithLoading<Data>,
|
||||||
|
i: number,
|
||||||
|
) => JSX.Element | null;
|
||||||
|
}): JSX.Element | null => {
|
||||||
|
const { data, error } = useFetch(query);
|
||||||
|
|
||||||
|
if (error) return <ErrorView error={error} />;
|
||||||
|
if (!data)
|
||||||
|
return (
|
||||||
|
<>{[...Array(placeholderCount)].map((_, i) => children({ isLoading: true } as any, i))}</>
|
||||||
|
);
|
||||||
|
if (!isPage<object>(data))
|
||||||
|
return children(data ? { ...data, isLoading: false } : ({ isLoading: true } as any), 0);
|
||||||
|
return <>{data.items.map((item, i) => children({ ...item, isLoading: false } as any, i))}</>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ErrorView = ({ error }: { error: KyooErrors }) => {
|
||||||
|
const { css } = useYoshiki();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
{...css({
|
||||||
|
backgroundColor: (theme) => theme.colors.red,
|
||||||
|
flex: 1,
|
||||||
|
alignItems: "center"
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
{error.errors.map((x, i) => (
|
||||||
|
<P key={i} {...css({ color: (theme) => theme.colors.white })}>
|
||||||
|
{x}
|
||||||
|
</P>
|
||||||
|
))}
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
@ -19,12 +19,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import useTranslation from "next-translate/useTranslation";
|
import useTranslation from "next-translate/useTranslation";
|
||||||
/* import { Library, LibraryP, Page, Paged } from "~/models"; */
|
import { Library, LibraryP, Page, Paged, QueryIdentifier } from "@kyoo/models";
|
||||||
/* import { QueryIdentifier, useFetch } from "~/utils/query"; */
|
|
||||||
/* import { ErrorSnackbar } from "./errors"; */
|
|
||||||
import { useYoshiki } from "yoshiki/native";
|
|
||||||
import { IconButton, Header, Avatar, A, ts } from "@kyoo/primitives";
|
import { IconButton, Header, Avatar, A, ts } from "@kyoo/primitives";
|
||||||
import { View } from "react-native";
|
import { useYoshiki } from "yoshiki/native";
|
||||||
|
import { Text, View } from "react-native";
|
||||||
|
import { Fetch } from "../fetch";
|
||||||
import { KyooLongLogo } from "./icon";
|
import { KyooLongLogo } from "./icon";
|
||||||
|
|
||||||
const tooltip = (tooltip: string): object => ({});
|
const tooltip = (tooltip: string): object => ({});
|
||||||
@ -34,7 +33,6 @@ export const NavbarTitle = KyooLongLogo;
|
|||||||
export const Navbar = () => {
|
export const Navbar = () => {
|
||||||
const { css } = useYoshiki();
|
const { css } = useYoshiki();
|
||||||
const { t } = useTranslation("common");
|
const { t } = useTranslation("common");
|
||||||
/* const { data, error, isSuccess, isError } = useFetch(Navbar.query()); */
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header
|
<Header
|
||||||
@ -67,35 +65,36 @@ export const Navbar = () => {
|
|||||||
<View
|
<View
|
||||||
{...css({
|
{...css({
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
|
flexShrink: 1,
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
display: { xs: "none", sm: "flex" },
|
display: { xs: "none", sm: "flex" },
|
||||||
marginLeft: ts(2),
|
marginX: ts(2),
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{
|
<Fetch query={Navbar.query()} placeholderCount={4}>
|
||||||
/*isSuccess
|
{(library, i) =>
|
||||||
? data.items.map((library) => */ true
|
!library.isLoading ? (
|
||||||
? [...Array(4)].map((_, i) => (
|
|
||||||
<A
|
<A
|
||||||
href={`/browse/${i /* library.slug */}`}
|
href={`/browse/${library.slug}`}
|
||||||
key={i} //{library.slug}
|
key={library.slug}
|
||||||
{...css({
|
{...css({
|
||||||
marginX: ts(1),
|
marginX: ts(1),
|
||||||
textTransform: "uppercase",
|
textTransform: "uppercase",
|
||||||
color: "white",
|
color: "white",
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
Toto
|
{library.name}
|
||||||
{/* {library.name} */}
|
|
||||||
</A>
|
</A>
|
||||||
))
|
) : (
|
||||||
: [...Array(4)].map(
|
<>
|
||||||
(_, i) => null,
|
<Text>Toto</Text>
|
||||||
/* <Typography key={i} variant="button" px=".25rem"> */
|
{/* <Typography key={i} variant="button" px=".25rem"> */}
|
||||||
/* <Skeleton width="5rem" /> */
|
{/* <Skeleton width="5rem" /> */}
|
||||||
/* </Typography> */
|
{/* </Typography> */}
|
||||||
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
</Fetch>
|
||||||
</View>
|
</View>
|
||||||
<A href="/auth/login" {...tooltip(t("navbar.login"))}>
|
<A href="/auth/login" {...tooltip(t("navbar.login"))}>
|
||||||
<Avatar alt={t("navbar.login")} size={30} />
|
<Avatar alt={t("navbar.login")} size={30} />
|
||||||
@ -105,7 +104,7 @@ export const Navbar = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Navbar.query = (): QueryIdentifier<Page<Library>> => ({ */
|
Navbar.query = (): QueryIdentifier<Page<Library>> => ({
|
||||||
/* parser: Paged(LibraryP), */
|
parser: Paged(LibraryP),
|
||||||
/* path: ["libraries"], */
|
path: ["libraries"],
|
||||||
/* }); */
|
});
|
||||||
|
@ -15,8 +15,6 @@
|
|||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "react-jsx",
|
||||||
"jsxImportSource": "@emotion/react",
|
|
||||||
"types": ["@emotion/react/types/css-prop"],
|
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"paths": {
|
"paths": {
|
||||||
|
@ -2341,12 +2341,30 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@kyoo/models@workspace:^, @kyoo/models@workspace:packages/models":
|
||||||
|
version: 0.0.0-use.local
|
||||||
|
resolution: "@kyoo/models@workspace:packages/models"
|
||||||
|
dependencies:
|
||||||
|
"@tanstack/react-query": ^4.18.0
|
||||||
|
"@types/react": ^18.0.25
|
||||||
|
typescript: ^4.9.3
|
||||||
|
zod: ^3.19.1
|
||||||
|
peerDependencies:
|
||||||
|
react: "*"
|
||||||
|
react-native: "*"
|
||||||
|
peerDependenciesMeta:
|
||||||
|
react-native-web:
|
||||||
|
optional: true
|
||||||
|
languageName: unknown
|
||||||
|
linkType: soft
|
||||||
|
|
||||||
"@kyoo/primitives@workspace:^, @kyoo/primitives@workspace:packages/primitives":
|
"@kyoo/primitives@workspace:^, @kyoo/primitives@workspace:packages/primitives":
|
||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@kyoo/primitives@workspace:packages/primitives"
|
resolution: "@kyoo/primitives@workspace:packages/primitives"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@expo/html-elements": ^0.2.2
|
"@expo/html-elements": ^0.2.2
|
||||||
"@expo/vector-icons": "AnonymusRaccoon/expo-vector-icons#no-prepare"
|
"@expo/vector-icons": "AnonymusRaccoon/expo-vector-icons#no-prepare"
|
||||||
|
"@tanstack/react-query": ^4.18.0
|
||||||
"@types/react": ^18.0.25
|
"@types/react": ^18.0.25
|
||||||
solito: ^2.0.5
|
solito: ^2.0.5
|
||||||
typescript: ^4.9.3
|
typescript: ^4.9.3
|
||||||
@ -2364,6 +2382,7 @@ __metadata:
|
|||||||
version: 0.0.0-use.local
|
version: 0.0.0-use.local
|
||||||
resolution: "@kyoo/ui@workspace:packages/ui"
|
resolution: "@kyoo/ui@workspace:packages/ui"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
"@kyoo/models": "workspace:^"
|
||||||
"@kyoo/primitives": "workspace:^"
|
"@kyoo/primitives": "workspace:^"
|
||||||
"@types/react": ^18.0.25
|
"@types/react": ^18.0.25
|
||||||
react-native-svg: ^13.6.0
|
react-native-svg: ^13.6.0
|
||||||
@ -12907,12 +12926,12 @@ __metadata:
|
|||||||
"@emotion/react": ^11.9.3
|
"@emotion/react": ^11.9.3
|
||||||
"@emotion/styled": ^11.9.3
|
"@emotion/styled": ^11.9.3
|
||||||
"@jellyfin/libass-wasm": ^4.1.1
|
"@jellyfin/libass-wasm": ^4.1.1
|
||||||
|
"@kyoo/models": "workspace:^"
|
||||||
"@kyoo/primitives": "workspace:^"
|
"@kyoo/primitives": "workspace:^"
|
||||||
"@kyoo/ui": "workspace:^"
|
"@kyoo/ui": "workspace:^"
|
||||||
"@mui/icons-material": ^5.8.4
|
"@mui/icons-material": ^5.8.4
|
||||||
"@mui/material": ^5.8.7
|
"@mui/material": ^5.8.7
|
||||||
"@mui/system": ^5.10.10
|
"@mui/system": ^5.10.10
|
||||||
"@tanstack/react-query": ^4.18.0
|
|
||||||
"@types/node": 18.11.9
|
"@types/node": 18.11.9
|
||||||
"@types/react": 18.0.25
|
"@types/react": 18.0.25
|
||||||
"@types/react-dom": 18.0.9
|
"@types/react-dom": 18.0.9
|
||||||
|
Loading…
x
Reference in New Issue
Block a user