From f15ac3a566d65fb43c1fa1a531d57910ebff2286 Mon Sep 17 00:00:00 2001
From: Zoe Roux <zoe.roux@zoriya.dev>
Date: Sun, 2 Feb 2025 00:24:34 +0100
Subject: [PATCH] Start to remove workspace & move theme to root package

---
 front/app/_layout.tsx                         |  86 ++++----
 front/app/index.tsx                           |   9 +-
 front/package.json                            |   3 -
 .../primitives/src/themes/catppuccin.ts       |  70 -------
 .../packages/primitives/src/themes/theme.tsx  | 192 -----------------
 front/src/primitives/theme/catppuccin.tsx     |  69 +++++++
 front/src/primitives/theme/index.ts           |   1 +
 front/src/primitives/theme/theme.tsx          | 193 ++++++++++++++++++
 front/src/providers.tsx                       |   5 +-
 9 files changed, 314 insertions(+), 314 deletions(-)
 create mode 100644 front/src/primitives/theme/catppuccin.tsx
 create mode 100644 front/src/primitives/theme/index.ts
 create mode 100644 front/src/primitives/theme/theme.tsx

diff --git a/front/app/_layout.tsx b/front/app/_layout.tsx
index 5248e0027..2eab9e0e8 100644
--- a/front/app/_layout.tsx
+++ b/front/app/_layout.tsx
@@ -1,57 +1,55 @@
 import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
 import { Slot } from "one";
-// import { WebTooltip } from "@kyoo/primitives/src/tooltip.web";
-// import { HiddenIfNoJs, SkeletonCss, TouchOnlyCss } from "@kyoo/primitives";
 import { useServerHeadInsertion } from "one";
 import { StyleRegistryProvider, createStyleRegistry, useTheme } from "yoshiki/web";
 import { Providers } from "~/providers";
 
 const GlobalCssTheme = () => {
-	const theme = useTheme();
+	// const theme = useTheme();
 	// TODO: add fonts here
 	// body {font-family: ${font.style.fontFamily};}
+	// background-color: ${theme.background};
 	return (
 		<>
-			{/* <style jsx global>{` */}
-			{/* 	body { */}
-			{/* 		margin: 0px; */}
-			{/* 		padding: 0px; */}
-			{/* 		overflow: "hidden"; */}
-			{/* 		background-color: ${theme.background}; */}
-			{/* 	} */}
-			{/**/}
-			{/* 	*::-webkit-scrollbar { */}
-			{/* 		height: 6px; */}
-			{/* 		width: 6px; */}
-			{/* 		background: transparent; */}
-			{/* 	} */}
-			{/**/}
-			{/* 	*::-webkit-scrollbar-thumb { */}
-			{/* 		background-color: #999; */}
-			{/* 		border-radius: 90px; */}
-			{/* 	} */}
-			{/* 	*:hover::-webkit-scrollbar-thumb { */}
-			{/* 		background-color: rgb(134, 127, 127); */}
-			{/* 	} */}
-			{/**/}
-			{/* 	#__next { */}
-			{/* 		height: 100vh; */}
-			{/* 	} */}
-			{/**/}
-			{/* 	.infinite-scroll-component__outerdiv { */}
-			{/* 		width: 100%; */}
-			{/* 		height: 100%; */}
-			{/* 	} */}
-			{/**/}
-			{/* 	::cue { */}
-			{/* 		background-color: transparent; */}
-			{/* 		text-shadow: */}
-			{/* 			-1px -1px 0 #000, */}
-			{/* 			1px -1px 0 #000, */}
-			{/* 			-1px 1px 0 #000, */}
-			{/* 			1px 1px 0 #000; */}
-			{/* 	} */}
-			{/* `}</style> */}
+			<style>{`
+				body {
+					margin: 0px;
+					padding: 0px;
+					overflow: "hidden";
+				}
+
+				*::-webkit-scrollbar {
+					height: 6px;
+					width: 6px;
+					background: transparent;
+				}
+
+				*::-webkit-scrollbar-thumb {
+					background-color: #999;
+					border-radius: 90px;
+				}
+				*:hover::-webkit-scrollbar-thumb {
+					background-color: rgb(134, 127, 127);
+				}
+
+				#__next {
+					height: 100vh;
+				}
+
+				.infinite-scroll-component__outerdiv {
+					width: 100%;
+					height: 100%;
+				}
+
+				::cue {
+					background-color: transparent;
+					text-shadow:
+						-1px -1px 0 #000,
+						1px -1px 0 #000,
+						-1px 1px 0 #000,
+						1px 1px 0 #000;
+				}
+			`}</style>
 			{/* <WebTooltip theme={theme} /> */}
 			{/* <SkeletonCss /> */}
 			{/* <TouchOnlyCss /> */}
@@ -76,7 +74,7 @@ export default function Layout() {
 				<link rel="icon" type="image/png" sizes="64x64" href="/icon-64x64.png" />
 				<link rel="icon" type="image/png" sizes="128x128" href="/icon-128x128.png" />
 				<link rel="icon" type="image/png" sizes="256x256" href="/icon-256x256.png" />
-				{/* <GlobalCssTheme /> */}
+				<GlobalCssTheme />
 			</head>
 
 			<body className="hoverEnabled">
diff --git a/front/app/index.tsx b/front/app/index.tsx
index 99584d210..a58e035d8 100644
--- a/front/app/index.tsx
+++ b/front/app/index.tsx
@@ -1,14 +1,17 @@
-import { View, Text } from "react-native";
+import { Text, View } from "react-native";
+import { useYoshiki } from "yoshiki/native";
 
 export default function MyApp() {
+	const { css } = useYoshiki();
+
 	return (
 		<View
-			style={{
+			{...css({
 				flex: 1,
 				justifyContent: "center",
 				alignItems: "center",
 				minHeight: "100%",
-			}}
+			})}
 		>
 			<Text>Hello from One</Text>
 		</View>
diff --git a/front/package.json b/front/package.json
index fd63bc785..83d88bcea 100644
--- a/front/package.json
+++ b/front/package.json
@@ -12,10 +12,7 @@
 		"format": "biome format .",
 		"format:fix": "biome format . --write"
 	},
-	"workspaces": ["packages/*"],
 	"dependencies": {
-		"@kyoo/models": "workspace:*",
-		"@kyoo/primitives": "workspace:*",
 		"@tanstack/react-query": "^5.66.0",
 		"caniuse-api": "^3.0.0",
 		"expo": "~52.0.28",
diff --git a/front/packages/primitives/src/themes/catppuccin.ts b/front/packages/primitives/src/themes/catppuccin.ts
index 869883632..609d690d9 100644
--- a/front/packages/primitives/src/themes/catppuccin.ts
+++ b/front/packages/primitives/src/themes/catppuccin.ts
@@ -17,73 +17,3 @@
  * You should have received a copy of the GNU General Public License
  * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
  */
-
-import type { ThemeBuilder } from "./theme";
-
-// Ref: https://github.com/catppuccin/catppuccin
-export const catppuccin: ThemeBuilder = {
-	light: {
-		// Catppuccin latte
-		overlay0: "#9ca0b0",
-		overlay1: "#7c7f93",
-		lightOverlay: "#eff1f599",
-		darkOverlay: "#4c4f6999",
-		link: "#1e66f5",
-		default: {
-			background: "#eff1f5",
-			accent: "#e64553",
-			divider: "#8c8fa1",
-			heading: "#4c4f69",
-			paragraph: "#5c5f77",
-			subtext: "#6c6f85",
-		},
-		variant: {
-			background: "#e6e9ef",
-			accent: "#d20f39",
-			divider: "#dd7878",
-			heading: "#4c4f69",
-			paragraph: "#5c5f77",
-			subtext: "#6c6f85",
-		},
-		colors: {
-			red: "#d20f39",
-			green: "#40a02b",
-			blue: "#1e66f5",
-			yellow: "#df8e1d",
-			black: "#4c4f69",
-			white: "#eff1f5",
-		},
-	},
-	dark: {
-		// Catppuccin mocha
-		overlay0: "#6c7086",
-		overlay1: "#9399b2",
-		lightOverlay: "#f5f0f899",
-		darkOverlay: "#11111b99",
-		link: "#89b4fa",
-		default: {
-			background: "#1e1e2e",
-			accent: "#89b4fa",
-			divider: "#7f849c",
-			heading: "#cdd6f4",
-			paragraph: "#bac2de",
-			subtext: "#a6adc8",
-		},
-		variant: {
-			background: "#181825",
-			accent: "#74c7ec",
-			divider: "#1e1e2e",
-			heading: "#cdd6f4",
-			paragraph: "#bac2de",
-			subtext: "#a6adc8",
-		},
-		colors: {
-			red: "#f38ba8",
-			green: "#a6e3a1",
-			blue: "#89b4fa",
-			yellow: "#f9e2af",
-			black: "#11111b",
-			white: "#f5f0f8",
-		},
-	},
-};
diff --git a/front/packages/primitives/src/themes/theme.tsx b/front/packages/primitives/src/themes/theme.tsx
index ffc764ce7..b4d49ce95 100644
--- a/front/packages/primitives/src/themes/theme.tsx
+++ b/front/packages/primitives/src/themes/theme.tsx
@@ -18,195 +18,3 @@
  * along with Kyoo. If not, see <https://www.gnu.org/licenses/>.
  */
 
-import type { Property } from "csstype";
-import type { ReactNode } from "react";
-import { Platform, type TextStyle } from "react-native";
-import { type Theme, ThemeProvider, useAutomaticTheme } from "yoshiki";
-import "yoshiki";
-import { useTheme, useYoshiki } from "yoshiki/native";
-import "yoshiki/native";
-import { catppuccin } from "./catppuccin";
-
-type FontList = Partial<
-	Record<Exclude<TextStyle["fontWeight"], null | undefined | number>, string>
->;
-
-type Mode = {
-	mode: "light" | "dark" | "auto";
-	overlay0: Property.Color;
-	overlay1: Property.Color;
-	lightOverlay: Property.Color;
-	darkOverlay: Property.Color;
-	themeOverlay: Property.Color;
-	link: Property.Color;
-	contrast: Property.Color;
-	variant: Variant;
-	colors: {
-		red: Property.Color;
-		green: Property.Color;
-		blue: Property.Color;
-		yellow: Property.Color;
-		white: Property.Color;
-		black: Property.Color;
-	};
-};
-
-type Variant = {
-	background: Property.Color;
-	accent: Property.Color;
-	divider: Property.Color;
-	heading: Property.Color;
-	paragraph: Property.Color;
-	subtext: Property.Color;
-};
-
-declare module "yoshiki" {
-	export interface Theme extends Mode, Variant {
-		light: Mode & Variant;
-		dark: Mode & Variant;
-		user: Mode & Variant;
-		alternate: Mode & Variant;
-		font: FontList;
-	}
-}
-
-export type { Theme } from "yoshiki";
-export type ThemeBuilder = {
-	light: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant };
-	dark: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant };
-};
-
-const selectMode = (
-	theme: ThemeBuilder & { font: FontList },
-	mode: "light" | "dark" | "auto",
-): Theme => {
-	const { light: lightBuilder, dark: darkBuilder, ...options } = theme;
-	const light: Mode & Variant = {
-		...lightBuilder,
-		...lightBuilder.default,
-		contrast: lightBuilder.colors.black,
-		themeOverlay: lightBuilder.lightOverlay,
-		mode: "light",
-	};
-	const dark: Mode & Variant = {
-		...darkBuilder,
-		...darkBuilder.default,
-		contrast: darkBuilder.colors.white,
-		themeOverlay: darkBuilder.darkOverlay,
-		mode: "dark",
-	};
-	if (Platform.OS !== "web" || mode !== "auto") {
-		const value = mode === "light" ? light : dark;
-		const alternate = mode === "light" ? dark : light;
-		return {
-			...options,
-			...value,
-			light,
-			dark,
-			user: value,
-			alternate,
-		};
-	}
-
-	const auto = useAutomaticTheme("theme", { light, dark });
-	const alternate = useAutomaticTheme("alternate", { dark: light, light: dark });
-	return {
-		...options,
-		...auto,
-		mode: "auto",
-		light,
-		dark,
-		user: { ...auto, mode: "auto" },
-		alternate: { ...alternate, mode: "auto" },
-	};
-};
-
-const switchVariant = (theme: Theme) => {
-	return {
-		...theme,
-		...theme.variant,
-		variant: {
-			background: theme.background,
-			accent: theme.accent,
-			divider: theme.divider,
-			heading: theme.heading,
-			paragraph: theme.paragraph,
-			subtext: theme.subtext,
-		},
-	};
-};
-
-export const ThemeSelector = ({
-	children,
-	theme,
-	font,
-}: {
-	children: ReactNode;
-	theme: "light" | "dark" | "auto";
-	font: FontList;
-}) => {
-	const newTheme = selectMode({ ...catppuccin, font }, theme);
-
-	return <ThemeProvider theme={newTheme}>{children as any}</ThemeProvider>;
-};
-
-export type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T;
-
-const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => {
-	const yoshiki = useYoshiki();
-	return <>{children(yoshiki)}</>;
-};
-
-export const SwitchVariant = ({ children }: { children: ReactNode | YoshikiFunc<ReactNode> }) => {
-	const theme = useTheme();
-
-	return (
-		<ThemeProvider theme={switchVariant(theme)}>
-			{typeof children === "function" ? (
-				<YoshikiProvider>{children}</YoshikiProvider>
-			) : (
-				(children as any)
-			)}
-		</ThemeProvider>
-	);
-};
-
-export const ContrastArea = ({
-	children,
-	mode = "dark",
-	contrastText,
-}: {
-	children: ReactNode | YoshikiFunc<ReactNode>;
-	mode?: "light" | "dark" | "user" | "alternate";
-	contrastText?: boolean;
-}) => {
-	const oldTheme = useTheme();
-	const theme: Theme = { ...oldTheme, ...oldTheme[mode] };
-
-	return (
-		<ThemeProvider
-			theme={
-				contrastText
-					? {
-							...theme,
-							// Keep the same skeletons, it looks weird otherwise.
-							overlay0: theme.user.overlay0,
-							overlay1: theme.user.overlay1,
-							heading: theme.contrast,
-							paragraph: theme.heading,
-						}
-					: theme
-			}
-		>
-			{typeof children === "function" ? (
-				<YoshikiProvider>{children}</YoshikiProvider>
-			) : (
-				(children as any)
-			)}
-		</ThemeProvider>
-	);
-};
-
-export const alpha = (color: Property.Color, alpha: number) => {
-	return color + Math.round(alpha * 255).toString(16);
-};
diff --git a/front/src/primitives/theme/catppuccin.tsx b/front/src/primitives/theme/catppuccin.tsx
new file mode 100644
index 000000000..1c3af6c8b
--- /dev/null
+++ b/front/src/primitives/theme/catppuccin.tsx
@@ -0,0 +1,69 @@
+import type { ThemeBuilder } from "./theme";
+
+// Ref: https://github.com/catppuccin/catppuccin
+export const catppuccin: ThemeBuilder = {
+	light: {
+		// Catppuccin latte
+		overlay0: "#9ca0b0",
+		overlay1: "#7c7f93",
+		lightOverlay: "#eff1f599",
+		darkOverlay: "#4c4f6999",
+		link: "#1e66f5",
+		default: {
+			background: "#eff1f5",
+			accent: "#e64553",
+			divider: "#8c8fa1",
+			heading: "#4c4f69",
+			paragraph: "#5c5f77",
+			subtext: "#6c6f85",
+		},
+		variant: {
+			background: "#e6e9ef",
+			accent: "#d20f39",
+			divider: "#dd7878",
+			heading: "#4c4f69",
+			paragraph: "#5c5f77",
+			subtext: "#6c6f85",
+		},
+		colors: {
+			red: "#d20f39",
+			green: "#40a02b",
+			blue: "#1e66f5",
+			yellow: "#df8e1d",
+			black: "#4c4f69",
+			white: "#eff1f5",
+		},
+	},
+	dark: {
+		// Catppuccin mocha
+		overlay0: "#6c7086",
+		overlay1: "#9399b2",
+		lightOverlay: "#f5f0f899",
+		darkOverlay: "#11111b99",
+		link: "#89b4fa",
+		default: {
+			background: "#1e1e2e",
+			accent: "#89b4fa",
+			divider: "#7f849c",
+			heading: "#cdd6f4",
+			paragraph: "#bac2de",
+			subtext: "#a6adc8",
+		},
+		variant: {
+			background: "#181825",
+			accent: "#74c7ec",
+			divider: "#1e1e2e",
+			heading: "#cdd6f4",
+			paragraph: "#bac2de",
+			subtext: "#a6adc8",
+		},
+		colors: {
+			red: "#f38ba8",
+			green: "#a6e3a1",
+			blue: "#89b4fa",
+			yellow: "#f9e2af",
+			black: "#11111b",
+			white: "#f5f0f8",
+		},
+	},
+};
diff --git a/front/src/primitives/theme/index.ts b/front/src/primitives/theme/index.ts
new file mode 100644
index 000000000..3797aeae0
--- /dev/null
+++ b/front/src/primitives/theme/index.ts
@@ -0,0 +1 @@
+export * from "./theme";
diff --git a/front/src/primitives/theme/theme.tsx b/front/src/primitives/theme/theme.tsx
new file mode 100644
index 000000000..fbd134bb2
--- /dev/null
+++ b/front/src/primitives/theme/theme.tsx
@@ -0,0 +1,193 @@
+import type { Property } from "csstype";
+import type { ReactNode } from "react";
+import { Platform, type TextStyle } from "react-native";
+import { type Theme, ThemeProvider, useAutomaticTheme } from "yoshiki";
+import "yoshiki";
+import { useTheme, useYoshiki } from "yoshiki/native";
+import "yoshiki/native";
+import { catppuccin } from "./catppuccin";
+
+type FontList = Partial<
+	Record<Exclude<TextStyle["fontWeight"], null | undefined | number>, string>
+>;
+
+type Mode = {
+	mode: "light" | "dark" | "auto";
+	overlay0: Property.Color;
+	overlay1: Property.Color;
+	lightOverlay: Property.Color;
+	darkOverlay: Property.Color;
+	themeOverlay: Property.Color;
+	link: Property.Color;
+	contrast: Property.Color;
+	variant: Variant;
+	colors: {
+		red: Property.Color;
+		green: Property.Color;
+		blue: Property.Color;
+		yellow: Property.Color;
+		white: Property.Color;
+		black: Property.Color;
+	};
+};
+
+type Variant = {
+	background: Property.Color;
+	accent: Property.Color;
+	divider: Property.Color;
+	heading: Property.Color;
+	paragraph: Property.Color;
+	subtext: Property.Color;
+};
+
+declare module "yoshiki" {
+	export interface Theme extends Mode, Variant {
+		light: Mode & Variant;
+		dark: Mode & Variant;
+		user: Mode & Variant;
+		alternate: Mode & Variant;
+		font: FontList;
+	}
+}
+
+export type { Theme } from "yoshiki";
+export type ThemeBuilder = {
+	light: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant };
+	dark: Omit<Mode, "contrast" | "mode" | "themeOverlay"> & { default: Variant };
+};
+
+const selectMode = (
+	theme: ThemeBuilder & { font: FontList },
+	mode: "light" | "dark" | "auto",
+): Theme => {
+	const { light: lightBuilder, dark: darkBuilder, ...options } = theme;
+	const light: Mode & Variant = {
+		...lightBuilder,
+		...lightBuilder.default,
+		contrast: lightBuilder.colors.black,
+		themeOverlay: lightBuilder.lightOverlay,
+		mode: "light",
+	};
+	const dark: Mode & Variant = {
+		...darkBuilder,
+		...darkBuilder.default,
+		contrast: darkBuilder.colors.white,
+		themeOverlay: darkBuilder.darkOverlay,
+		mode: "dark",
+	};
+	if (Platform.OS !== "web" || mode !== "auto") {
+		const value = mode === "light" ? light : dark;
+		const alternate = mode === "light" ? dark : light;
+		return {
+			...options,
+			...value,
+			light,
+			dark,
+			user: value,
+			alternate,
+		};
+	}
+
+	const auto = useAutomaticTheme("theme", { light, dark });
+	const alternate = useAutomaticTheme("alternate", { dark: light, light: dark });
+	return {
+		...options,
+		...auto,
+		mode: "auto",
+		light,
+		dark,
+		user: { ...auto, mode: "auto" },
+		alternate: { ...alternate, mode: "auto" },
+	};
+};
+
+const switchVariant = (theme: Theme) => {
+	return {
+		...theme,
+		...theme.variant,
+		variant: {
+			background: theme.background,
+			accent: theme.accent,
+			divider: theme.divider,
+			heading: theme.heading,
+			paragraph: theme.paragraph,
+			subtext: theme.subtext,
+		},
+	};
+};
+
+export const ThemeSelector = ({
+	children,
+	theme,
+	font,
+}: {
+	children: ReactNode;
+	theme: "light" | "dark" | "auto";
+	font: FontList;
+}) => {
+	const newTheme = selectMode({ ...catppuccin, font }, theme);
+
+	return <ThemeProvider theme={newTheme}>{children as any}</ThemeProvider>;
+};
+
+export type YoshikiFunc<T> = (props: ReturnType<typeof useYoshiki>) => T;
+
+const YoshikiProvider = ({ children }: { children: YoshikiFunc<ReactNode> }) => {
+	const yoshiki = useYoshiki();
+	return <>{children(yoshiki)}</>;
+};
+
+export const SwitchVariant = ({ children }: { children: ReactNode | YoshikiFunc<ReactNode> }) => {
+	const theme = useTheme();
+
+	return (
+		<ThemeProvider theme={switchVariant(theme)}>
+			{typeof children === "function" ? (
+				<YoshikiProvider>{children}</YoshikiProvider>
+			) : (
+				(children as any)
+			)}
+		</ThemeProvider>
+	);
+};
+
+export const ContrastArea = ({
+	children,
+	mode = "dark",
+	contrastText,
+}: {
+	children: ReactNode | YoshikiFunc<ReactNode>;
+	mode?: "light" | "dark" | "user" | "alternate";
+	contrastText?: boolean;
+}) => {
+	const oldTheme = useTheme();
+	const theme: Theme = { ...oldTheme, ...oldTheme[mode] };
+
+	return (
+		<ThemeProvider
+			theme={
+				contrastText
+					? {
+							...theme,
+							// Keep the same skeletons, it looks weird otherwise.
+							overlay0: theme.user.overlay0,
+							overlay1: theme.user.overlay1,
+							heading: theme.contrast,
+							paragraph: theme.heading,
+						}
+					: theme
+			}
+		>
+			{typeof children === "function" ? (
+				<YoshikiProvider>{children}</YoshikiProvider>
+			) : (
+				(children as any)
+			)}
+		</ThemeProvider>
+	);
+};
+
+export const alpha = (color: Property.Color, alpha: number) => {
+	return color + Math.round(alpha * 255).toString(16);
+};
+
diff --git a/front/src/providers.tsx b/front/src/providers.tsx
index 313c33ebe..7e9a46941 100644
--- a/front/src/providers.tsx
+++ b/front/src/providers.tsx
@@ -1,7 +1,8 @@
-// import { useUserTheme } from "@kyoo/models";
-import { ThemeSelector } from "@kyoo/primitives";
 import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
 import { ComponentType, type ReactNode, useState } from "react";
+// import { useUserTheme } from "@kyoo/models";
+// import { createQueryClient } from "@kyoo/models";
+import { ThemeSelector } from "~/primitives/theme";
 
 const QueryProvider = ({ children }: { children: ReactNode }) => {
 	// const [queryClient] = useState(() => createQueryClient());