mirror of
https://github.com/arkorty/Osborne.git
synced 2026-03-18 00:57:14 +00:00
style
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, Suspense } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import {
|
||||
@@ -9,13 +9,81 @@ import {
|
||||
InputOTPSlot,
|
||||
} from "@/components/ui/input-otp";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
import Image from "next/image";
|
||||
import { ThemeProvider } from "next-themes";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import {
|
||||
VSCODE_THEMES,
|
||||
getThemeById,
|
||||
applyTheme,
|
||||
saveThemeToCookie,
|
||||
getThemeFromCookie,
|
||||
} from "@/lib/themes";
|
||||
|
||||
const Home = () => {
|
||||
const router = useRouter();
|
||||
const [newRoomCode, setNewRoomCode] = useState("");
|
||||
const [currentThemeIndex, setCurrentThemeIndex] = useState(0);
|
||||
const [isClient, setIsClient] = useState(false);
|
||||
|
||||
const nextTheme = useCallback(() => {
|
||||
setCurrentThemeIndex((prevIndex) => {
|
||||
const newIndex = (prevIndex + 1) % VSCODE_THEMES.length;
|
||||
const theme = VSCODE_THEMES[newIndex];
|
||||
applyTheme(theme);
|
||||
saveThemeToCookie(theme.id);
|
||||
return newIndex;
|
||||
});
|
||||
}, []);
|
||||
|
||||
const prevTheme = useCallback(() => {
|
||||
setCurrentThemeIndex((prevIndex) => {
|
||||
const newIndex = prevIndex === 0
|
||||
? VSCODE_THEMES.length - 1
|
||||
: prevIndex - 1;
|
||||
const theme = VSCODE_THEMES[newIndex];
|
||||
applyTheme(theme);
|
||||
saveThemeToCookie(theme.id);
|
||||
return newIndex;
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
setIsClient(true);
|
||||
|
||||
// Initialize theme from cookie
|
||||
const savedThemeId = getThemeFromCookie();
|
||||
if (savedThemeId) {
|
||||
const themeIndex = VSCODE_THEMES.findIndex(
|
||||
(theme) => theme.id === savedThemeId
|
||||
);
|
||||
if (themeIndex !== -1) {
|
||||
setCurrentThemeIndex(themeIndex);
|
||||
const theme = getThemeById(savedThemeId);
|
||||
if (theme) {
|
||||
applyTheme(theme);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Apply default theme (first in array)
|
||||
const defaultTheme = VSCODE_THEMES[0];
|
||||
applyTheme(defaultTheme);
|
||||
}
|
||||
|
||||
// Simple keyboard navigation
|
||||
const handleKeyPress = (e: KeyboardEvent) => {
|
||||
if (e.key === "ArrowLeft") {
|
||||
e.preventDefault();
|
||||
prevTheme();
|
||||
} else if (e.key === "ArrowRight") {
|
||||
e.preventDefault();
|
||||
nextTheme();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("keydown", handleKeyPress);
|
||||
return () => {
|
||||
window.removeEventListener("keydown", handleKeyPress);
|
||||
};
|
||||
}, [nextTheme, prevTheme]);
|
||||
|
||||
useEffect(() => {
|
||||
const joinRoom = () => {
|
||||
@@ -38,21 +106,51 @@ const Home = () => {
|
||||
router.push(`/room?code=${code}`);
|
||||
};
|
||||
|
||||
if (!isClient) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const currentTheme = VSCODE_THEMES[currentThemeIndex];
|
||||
|
||||
return (
|
||||
<div className="relative min-h-screen flex items-center justify-center bg-background dark:bg-background">
|
||||
<Card className="relative z-10 max-w-md backdrop-blur-sm shadow-lg bg-card/0 bg-opacity-0 dark:bg-card/70 border border-border dark:border-border p-6 flex flex-col items-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<div className=" m-8 bg-black">
|
||||
<Image
|
||||
src="/logo.png"
|
||||
alt="Room Logo"
|
||||
width={128}
|
||||
height={128}
|
||||
className=""
|
||||
/>
|
||||
<div className="relative min-h-screen flex items-center justify-center bg-background dark:bg-background ui-font">
|
||||
<Card className="relative z-10 max-w-md min-w-96 backdrop-blur-sm shadow-lg bg-card/0 bg-opacity-0 dark:bg-card/70 border border-border dark:border-border p-6 flex flex-col items-center">
|
||||
{/* Theme Slider - Simple Version */}
|
||||
<div className="w-full mb-6">
|
||||
<div className="flex items-center justify-between bg-card rounded-lg p-3 border">
|
||||
<button
|
||||
onClick={prevTheme}
|
||||
className="p-1 rounded hover:bg-muted transition-colors"
|
||||
aria-label="Previous theme"
|
||||
>
|
||||
←
|
||||
</button>
|
||||
|
||||
<div className="text-center flex-1 mx-4">
|
||||
<div className="text-sm font-medium text-foreground">
|
||||
{currentTheme.name}
|
||||
</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
{currentThemeIndex + 1} of {VSCODE_THEMES.length}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
onClick={nextTheme}
|
||||
className="p-1 rounded hover:bg-muted transition-colors"
|
||||
aria-label="Next theme"
|
||||
>
|
||||
→
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<CardContent className="flex flex-col items-center space-y-4 font-jetbrains-mono">
|
||||
|
||||
<div className="flex flex-col items-center">
|
||||
<h1 className="text-6xl font-bold text-foreground mb-4">
|
||||
Osborne
|
||||
</h1>
|
||||
</div>
|
||||
<CardContent className="flex flex-col items-center space-y-4 ui-font">
|
||||
<InputOTP
|
||||
value={newRoomCode}
|
||||
onChange={(value) => setNewRoomCode(value.toUpperCase())}
|
||||
@@ -62,21 +160,17 @@ const Home = () => {
|
||||
>
|
||||
<InputOTPGroup>
|
||||
{[...Array(6)].map((_, index) => (
|
||||
<InputOTPSlot
|
||||
key={index}
|
||||
index={index}
|
||||
className="text-foreground bg-background dark:text-foreground dark:bg-background dark:caret-foreground"
|
||||
/>
|
||||
<InputOTPSlot key={index} index={index} className="otp-input" />
|
||||
))}
|
||||
</InputOTPGroup>
|
||||
</InputOTP>
|
||||
<span className="text-lg text-foreground/70 dark:text-foreground/70">
|
||||
<span className="text-xl text-foreground/70 ui-font font-medium">
|
||||
or
|
||||
</span>
|
||||
<Button
|
||||
onClick={createNewRoom}
|
||||
variant="default"
|
||||
className="w-min bg-primary text-primary-foreground text-lg font-semibold hover:bg-primary/80"
|
||||
className="w-min bg-primary text-primary-foreground text-xl font-semibold hover:bg-primary/80 ui-font px-6 py-3"
|
||||
>
|
||||
Create Room
|
||||
</Button>
|
||||
@@ -86,30 +180,9 @@ const Home = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const SkeletonHome = () => {
|
||||
return (
|
||||
<div className="relative min-h-screen flex items-center justify-center bg-background dark:bg-background">
|
||||
<div className="relative z-10 max-w-md backdrop-blur-sm shadow-lg bg-card/0 bg-opacity-0 dark:bg-card/70 border border-border dark:border-border p-6 flex flex-col items-center">
|
||||
<div className="flex flex-col items-center">
|
||||
<Skeleton className="w-[128px] h-[128px] bg-black m-8" />
|
||||
</div>
|
||||
<div className="flex flex-col items-center space-y-4">
|
||||
<Skeleton className="w-full h-12 bg-background dark:bg-background" />
|
||||
<span className="text-lg text-foreground/70 dark:text-foreground/70">
|
||||
or
|
||||
</span>
|
||||
<Skeleton className="w-32 h-12 bg-primary" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const HomeWrapper = () => (
|
||||
<ThemeProvider attribute="class" defaultTheme="dark">
|
||||
<Suspense fallback={<SkeletonHome />}>
|
||||
<Home />
|
||||
</Suspense>
|
||||
<Home />
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user